@@ -414,20 +414,35 @@ int64 FileReader::getCurrentSample()
414414 return currentSample;
415415}
416416
417- void FileReader::setCurrentSample (int64 sampleNumber)
417+ void FileReader::setCurrentSample (int64 sampleNumber)
418418{
419+ // Stop background thread before modifying shared state
420+ stopThread (100 );
421+
422+ const ScopedLock sl (bufferLock);
423+
419424 currentSample = sampleNumber;
420- this -> playbackSamplePos = currentSample ;
425+ playbackSamplePos. set (sampleNumber) ;
421426
422- /* Reset stream to start of playback */
423- input->seekTo (currentSample );
427+ // Reset file position
428+ input->seekTo (sampleNumber );
424429
425- /* Pre-fills the front buffer with a blocking read */
426- readAndFillBufferCache (bufferA );
430+ // Get the current back buffer without switching
431+ HeapBlock< float >* backBuffer = getBackBuffer ( );
427432
428- readBuffer = &bufferB;
429- bufferCacheWindow = 0 ;
430- m_shouldFillBackBuffer.set (false );
433+ // Fill only the back buffer first
434+ readAndFillBufferCache (*backBuffer);
435+
436+ // Signal that we want to switch buffers on next process() call
437+ bufferCacheWindow.set (BUFFER_WINDOW_CACHE_SIZE - 1 ); // Force buffer switch on next process
438+ needsBufferReset.set (true );
439+
440+ // The process() thread will handle the buffer switch and trigger
441+ // the background thread to fill the new back buffer
442+ m_shouldFillBackBuffer.set (false );
443+
444+ // Restart background thread
445+ startThread ();
431446}
432447
433448void FileReader::setPlaybackStart (int64 startSample)
@@ -661,68 +676,57 @@ String FileReader::handleConfigMessage (const String& msg)
661676
662677void FileReader::process (AudioBuffer<float >& buffer)
663678{
664- bool switchNeeded = false ;
679+ const ScopedLock sl (bufferLock) ;
665680
666- int samplesNeededPerBuffer = int (float (buffer.getNumSamples ()) * (getDefaultSampleRate () / m_sysSampleRate));
681+ if (needsBufferReset.compareAndSetBool (false , true ))
682+ {
683+ // Switch to the newly prepared back buffer
684+ switchBuffer ();
685+ bufferCacheWindow.set (0 );
686+ }
667687
668- m_samplesPerBuffer.set (samplesNeededPerBuffer);
669- m_samplesPerBuffer.set (samplesNeededPerBuffer);
670- // FIXME: needs to account for the fact that the ratio might not be an exact
671- // integer value
672- m_samplesPerBuffer.set (samplesNeededPerBuffer);
673- // FIXME: needs to account for the fact that the ratio might not be an exact
674- // integer value
688+ int samplesNeededPerBuffer = int (float (buffer.getNumSamples ()) * (getDefaultSampleRate () / m_sysSampleRate));
689+ m_samplesPerBuffer.set (samplesNeededPerBuffer);
675690
676- // if cache window id == 0, we need to read and cache BUFFER_WINDOW_CACHE_SIZE more buffer windows
677- if (bufferCacheWindow == 0 )
691+ // Handle buffer switching
692+ if (bufferCacheWindow. get () == 0 )
678693 {
679694 switchBuffer ();
680695 }
681696
682- const float * tempReadBuffer = readBuffer->getData () + (samplesNeededPerBuffer * currentNumChannels * bufferCacheWindow);
697+ // Get current buffer position
698+ const float * tempReadBuffer = readBuffer->getData () +
699+ (samplesNeededPerBuffer * currentNumChannels * bufferCacheWindow.get ());
683700
701+ // Copy data to output buffer
684702 for (int ch = 0 ; ch < currentNumChannels; ++ch)
685703 {
686- float * writeBuffer = buffer.getWritePointer (ch);
687-
704+ float * writeBuffer = buffer.getWritePointer (ch);
688705 for (int sample = 0 ; sample < samplesNeededPerBuffer; sample++)
689706 {
690707 *(writeBuffer + sample) = *(tempReadBuffer + (currentNumChannels * sample) + ch);
691708 }
692-
693- // DEPRECATED:
694- // offset readBuffer index by current cache window count * buffer window size * num channels
695- // input->processChannelData (*readBuffer + (samplesNeededPerBuffer * currentNumChannels * bufferCacheWindow),
696- // buffer.getWritePointer (i, 0),
697- // i,
698- // samplesNeededPerBuffer);
699709 }
700710
701- setTimestampAndSamples (playbackSamplePos, -1.0 , samplesNeededPerBuffer, dataStreams[0 ]->getStreamId ()); // TODO: Look at this could be total or playback
702-
703- int64 start = playbackSamplePos;
704-
705- playbackSamplePos += samplesNeededPerBuffer;
711+ // Update timestamps and sample positions atomically
712+ int64 start = playbackSamplePos.get ();
713+ playbackSamplePos.set (start + samplesNeededPerBuffer);
714+ int64 stop = playbackSamplePos.get ();
706715
707- // LOGD("Total samples acquired: ", playbackSamplePos );
716+ setTimestampAndSamples (start, - 1.0 , samplesNeededPerBuffer, dataStreams[ 0 ]-> getStreamId () );
708717
709- int64 stop = playbackSamplePos;
710-
711- addEventsInRange (start, stop);
712-
713- if (playbackSamplePos >= stopSample)
718+ // Handle looping
719+ if (playbackSamplePos.get () >= stopSample)
714720 {
715- playbackSamplePos = startSample + (playbackSamplePos - stopSample);
721+ playbackSamplePos. set ( startSample + (playbackSamplePos. get () - stopSample) );
716722 }
717723
718- bufferCacheWindow += 1 ;
719- bufferCacheWindow %= BUFFER_WINDOW_CACHE_SIZE ;
724+ // Process events for this buffer
725+ addEventsInRange (start, stop) ;
720726
721- if (switchNeeded)
722- {
723- bufferCacheWindow = 0 ;
724- this ->stopThread (100 );
725- }
727+ // Update buffer window counter
728+ int newWindow = (bufferCacheWindow.get () + 1 ) % BUFFER_WINDOW_CACHE_SIZE;
729+ bufferCacheWindow.set (newWindow);
726730}
727731
728732void FileReader::addEventsInRange (int64 start, int64 stop)
@@ -761,12 +765,14 @@ int64 FileReader::millisecondsToSamples (unsigned int ms) const
761765
762766void FileReader::switchBuffer ()
763767{
768+ const ScopedLock sl (bufferLock);
769+
764770 if (readBuffer == &bufferA)
765771 readBuffer = &bufferB;
766772 else
767773 readBuffer = &bufferA;
768774
769- m_shouldFillBackBuffer.set (true );
775+ m_shouldFillBackBuffer.set (true );
770776 notify ();
771777}
772778
0 commit comments