@@ -46,6 +46,7 @@ FileReader::FileReader() : GenericProcessor ("File Reader"),
4646 startSample (0 ),
4747 stopSample (0 ),
4848 bufferCacheWindow (0 ),
49+ needsBufferReset (false ),
4950 m_shouldFillBackBuffer (false ),
5051 m_bufferSize (1024 ),
5152 m_sysSampleRate (44100 ),
@@ -381,6 +382,8 @@ void FileReader::setActiveStream (int index, bool reset)
381382 channelInfo.add (input->getChannelInfo (index, i));
382383
383384 input->seekTo (startSample);
385+ firstProcess = false ;
386+ needsBufferReset.set (false );
384387
385388 updateSettings ();
386389 CoreServices::updateSignalChain (this );
@@ -421,6 +424,15 @@ bool FileReader::startAcquisition()
421424
422425 checkAudioDevice ();
423426
427+ {
428+ const ScopedLock sl (bufferLock);
429+ readAndFillBufferCache (bufferA);
430+ readBuffer = &bufferA;
431+ bufferCacheWindow = 0 ;
432+ needsBufferReset.set (false );
433+ m_shouldFillBackBuffer.set (true );
434+ }
435+
424436 /* Start asynchronous file reading thread */
425437 startThread ();
426438
@@ -449,8 +461,10 @@ int64 FileReader::getCurrentSample()
449461
450462void FileReader::setCurrentSample (int64 sampleNumber)
451463{
464+ const bool wasThreadRunning = isThreadRunning ();
452465 // Stop background thread before modifying shared state
453- stopThread (100 );
466+ if (wasThreadRunning)
467+ stopThread (100 );
454468
455469 const ScopedLock sl (bufferLock);
456470
@@ -460,22 +474,34 @@ void FileReader::setCurrentSample(int64 sampleNumber)
460474 // Reset file position
461475 input->seekTo (sampleNumber);
462476
463- // Get the current back buffer without switching
464- HeapBlock<float >* backBuffer = getBackBuffer ();
465-
466- // Fill only the back buffer first
467- readAndFillBufferCache (*backBuffer);
477+ if (wasThreadRunning)
478+ {
479+ // Get the current back buffer without switching
480+ HeapBlock<float >* backBuffer = getBackBuffer ();
481+ readAndFillBufferCache (*backBuffer);
482+ }
468483
469- // Signal that we want to switch buffers on next process() call
470- bufferCacheWindow.set (BUFFER_WINDOW_CACHE_SIZE - 1 ); // Force buffer switch on next process
471- needsBufferReset.set (true );
484+ if (wasThreadRunning)
485+ {
486+ // Signal that we want to switch buffers on next process() call
487+ bufferCacheWindow.set (BUFFER_WINDOW_CACHE_SIZE - 1 ); // Force buffer switch on next process
488+ needsBufferReset.set (true );
472489
473- // The process() thread will handle the buffer switch and trigger
474- // the background thread to fill the new back buffer
475- m_shouldFillBackBuffer.set (false );
490+ // The process() thread will handle the buffer switch and trigger
491+ // the background thread to fill the new back buffer
492+ m_shouldFillBackBuffer.set (false );
493+ }
494+ else
495+ {
496+ bufferCacheWindow.set (0 );
497+ needsBufferReset.set (false );
498+ readBuffer = &bufferA;
499+ m_shouldFillBackBuffer.set (false );
500+ }
476501
477502 // Restart background thread
478- startThread ();
503+ if (wasThreadRunning)
504+ startThread ();
479505}
480506
481507void FileReader::setPlaybackStart (int64 startSample)
@@ -626,14 +652,9 @@ void FileReader::updateSettings()
626652 input->seekTo (startSample);
627653 currentSample = startSample;
628654
629- /* Pre-fills the front buffer with a blocking read */
630- readAndFillBufferCache (bufferA);
631-
632- readBuffer = &bufferB;
655+ readBuffer = &bufferA;
633656 bufferCacheWindow = 0 ;
634657 m_shouldFillBackBuffer.set (false );
635- if (firstProcess)
636- switchBuffer ();
637658
638659 LOGD (" File Reader finished updating custom settings." );
639660}
@@ -660,11 +681,9 @@ void FileReader::checkAudioDevice()
660681 input->seekTo (startSample);
661682 currentSample = startSample;
662683
663- /* Pre-fills the front buffer with a blocking read */
664- readAndFillBufferCache (bufferA);
665-
666- readBuffer = &bufferB;
684+ readBuffer = &bufferA;
667685 bufferCacheWindow = 0 ;
686+ needsBufferReset.set (false );
668687 m_shouldFillBackBuffer.set (false );
669688 }
670689}
@@ -846,38 +865,44 @@ void FileReader::readAndFillBufferCache (HeapBlock<float>& cacheBuffer)
846865{
847866 const int samplesNeededPerBuffer = m_samplesPerBuffer.get ();
848867 const int samplesNeeded = samplesNeededPerBuffer * BUFFER_WINDOW_CACHE_SIZE;
868+ if (samplesNeeded <= 0 || stopSample <= startSample)
869+ return ;
849870
850871 int samplesRead = 0 ;
851872
852873 // should only loop if reached end of file and resuming from start
853874 while (samplesRead < samplesNeeded)
854875 {
855876 int samplesToRead = samplesNeeded - samplesRead;
877+ int samplesJustRead = 0 ;
878+
879+ const bool wrapsAtEnd = (currentSample + samplesToRead) > stopSample;
856880
857881 // if reached end of file stream
858- if ((currentSample + samplesToRead) > stopSample )
882+ if (wrapsAtEnd )
859883 {
860884 samplesToRead = int (stopSample - currentSample);
861885 if (samplesToRead > 0 )
862- input->readData (cacheBuffer + samplesRead * currentNumChannels, samplesToRead);
886+ samplesJustRead = input->readData (cacheBuffer + samplesRead * currentNumChannels, samplesToRead);
863887
864888 // reset stream to beginning
865889 input->seekTo (startSample);
866890 currentSample = startSample;
867891 }
868892 else // else read the block needed
869893 {
870- input->readData (cacheBuffer + samplesRead * currentNumChannels, samplesToRead);
871-
872- currentSample += samplesToRead;
894+ samplesJustRead = input->readData (cacheBuffer + samplesRead * currentNumChannels, samplesToRead);
895+ currentSample += samplesJustRead;
873896 }
874897
875- samplesRead += samplesToRead ;
898+ samplesRead += samplesJustRead ;
876899
877900 // LOGD("CURRENT SAMPLE: ", currentSample, " samplesRead: ", samplesRead, " samplesNeeded: ", samplesNeeded);
878-
879901 if (samplesRead < 0 )
880902 return ;
903+
904+ if (samplesJustRead <= 0 && ! wrapsAtEnd)
905+ return ;
881906 }
882907}
883908
0 commit comments