diff --git a/VoidLink/Stream/Connection.m b/VoidLink/Stream/Connection.m index 2acf3dc4..582422cc 100644 --- a/VoidLink/Stream/Connection.m +++ b/VoidLink/Stream/Connection.m @@ -15,6 +15,7 @@ #import "DataManager.h" #import +#include #define SDL_MAIN_HANDLED #import @@ -56,6 +57,7 @@ static AVAudioEngine *audioEngine; static AVAudioPlayerNode *audioPlayerNode; static AVAudioPCMBuffer *pcmBuffer; static AVAudioFormat *audioFormat; +static atomic_long systemAudioQueuedFrames; static bool muteInBackground; static bool fullColorRange; @@ -64,6 +66,20 @@ static VideoDecoderRenderer* renderer; static BandwidthTracker *bwTracker; +static void SystemAudioConsumeQueuedFrames(long frameCount) +{ + long currentFrames; + long newFrames; + + do { + currentFrames = atomic_load(&systemAudioQueuedFrames); + newFrames = currentFrames - frameCount; + if (newFrames < 0) { + newFrames = 0; + } + } while (!atomic_compare_exchange_weak(&systemAudioQueuedFrames, ¤tFrames, newFrames)); +} + int DrDecoderSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { [renderer setupWithVideoFormat:videoFormat width:width height:height frameRate:redrawRate fullRange:fullColorRange]; @@ -348,6 +364,7 @@ void ArCleanup(void) } void AudioEngineInit(int sampleRate, int channelCount) { + atomic_store(&systemAudioQueuedFrames, 0); audioEngine = [[AVAudioEngine alloc] init]; audioPlayerNode = [[AVAudioPlayerNode alloc] init]; @@ -426,20 +443,28 @@ void ArDecodeAndPlaySample(char* sampleData, int sampleLength) float* fbuf = (float*)audioBuffer; if(useSystemAudioEngine){ - // 创建 AVAudioPCMBuffer + long maxQueuedFrames = (long)audioConfig.samplesPerFrame * 10; + while (atomic_load(&systemAudioQueuedFrames) > maxQueuedFrames) { + [NSThread sleepForTimeInterval:0.001f]; + } + AVAudioFrameCount frameCount = decodeLen; AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFormat frameCapacity:frameCount]; buffer.frameLength = frameCount; - // 拷贝数据到 buffer for (int ch = 0; ch < audioConfig.channelCount; ch++) { float *dst = buffer.floatChannelData[ch]; for (int i = 0; i < decodeLen; i++) { dst[i] = fbuf[i * audioConfig.channelCount + ch] * volume; // 非交错数据 } } - // 播放 - if(!audioSessionInterrupted) [audioPlayerNode scheduleBuffer:buffer completionHandler:nil]; + + if(!audioSessionInterrupted) { + atomic_fetch_add(&systemAudioQueuedFrames, frameCount); + [audioPlayerNode scheduleBuffer:buffer completionHandler:^{ + SystemAudioConsumeQueuedFrames(frameCount); + }]; + } } else{ @@ -535,6 +560,7 @@ void ClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t // won't be able to acquire it if LiStartConnection is in // progress. LiInterruptConnection(); + atomic_store(&systemAudioQueuedFrames, 0); [audioPlayerNode stop]; [audioEngine stop]; [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -557,6 +583,7 @@ void ClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t switch (type) { case AVAudioSessionInterruptionTypeBegan: audioSessionInterrupted = true; + atomic_store(&systemAudioQueuedFrames, 0); [audioPlayerNode stop]; [audioEngine stop]; break;