Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 27 additions & 21 deletions OpenParsec/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ _Atomic bool isMuted = false;
_Atomic bool isStart = false;
_Atomic int lastbuf = 0;

_Atomic unsigned int silence_inqueue = 0;
_Atomic unsigned int silence_outqueue = 0;

AudioQueueBufferRef silence_buf;
typedef struct RecycleChain {
AudioQueueBufferRef *curt;
struct RecycleChain *next;
Expand All @@ -35,11 +31,14 @@ typedef struct RecycleChainMgr {
struct audio {
AudioQueueRef q;
AudioQueueBufferRef audio_buf[NUM_AUDIO_BUF];
AudioQueueBufferRef silence_buf;
char *mem[NUM_AUDIO_BUF * 2];
int loc[NUM_AUDIO_BUF];
RecycleChainMgr rcm;
_Atomic int32_t fail_num;
_Atomic int32_t in_use;
_Atomic unsigned int silence_inqueue;
_Atomic unsigned int silence_outqueue;
os_unfair_lock clear_lock;
};

Expand All @@ -57,7 +56,7 @@ static void audio_queue_callback(void *opaque, AudioQueueRef queue, AudioQueueBu
ctx->in_use -= buffer->mAudioDataByteSize;
}

if(buffer != silence_buf)
if(buffer != ctx->silence_buf)
{
buffer->mAudioDataByteSize = FAKE_SIZE;
lastbuf = *((int *)(buffer->mUserData));
Expand All @@ -66,7 +65,7 @@ static void audio_queue_callback(void *opaque, AudioQueueRef queue, AudioQueueBu
{
//silence_use_count = 0;
//silence_buf->mUserData = (void *)(0);
++silence_outqueue;
++ctx->silence_outqueue;
}

if (isMuted) return;
Expand All @@ -81,22 +80,22 @@ static void audio_queue_callback(void *opaque, AudioQueueRef queue, AudioQueueBu
ctx->rcm.last_to_queue = ctx->rcm.last_to_queue->next;
}

if (deltaBuf + silence_inqueue < LOWEST_NUM_BUFFER + silence_outqueue)
if (deltaBuf + ctx->silence_inqueue < LOWEST_NUM_BUFFER + ctx->silence_outqueue)
{
int numAddBuffer = ((silence_inqueue >= silence_outqueue) ? (LOWEST_NUM_BUFFER - deltaBuf - (int)(silence_inqueue-silence_outqueue)) : (LOWEST_NUM_BUFFER - deltaBuf - (int)((unsigned int)(0xFFFFFFFF)-silence_outqueue + silence_inqueue + 1)));
int numAddBuffer = ((ctx->silence_inqueue >= ctx->silence_outqueue) ? (LOWEST_NUM_BUFFER - deltaBuf - (int)(ctx->silence_inqueue-ctx->silence_outqueue)) : (LOWEST_NUM_BUFFER - deltaBuf - (int)((unsigned int)(0xFFFFFFFF)-ctx->silence_outqueue + ctx->silence_inqueue + 1)));
if (numAddBuffer > LOWEST_NUM_BUFFER)
{
numAddBuffer = LOWEST_NUM_BUFFER - deltaBuf;
}
else
{
silence_inqueue = silence_outqueue = 0;
ctx->silence_inqueue = ctx->silence_outqueue = 0;
}
for (int i=0; i<numAddBuffer; ++i)
{
AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL);
AudioQueueEnqueueBuffer(ctx->q, ctx->silence_buf, 0, NULL);
}
if (numAddBuffer > 0) silence_inqueue += numAddBuffer;
if (numAddBuffer > 0) ctx->silence_inqueue += numAddBuffer;
}

//RecycleChain *tmp = ctx->rcm.last_to_queue->next;
Expand Down Expand Up @@ -196,12 +195,12 @@ void audio_init(struct audio **ctx_out)
ctx->fail_num = 0;
ctx->in_use = 0;

silence_inqueue = silence_outqueue = 0;
ctx->silence_inqueue = ctx->silence_outqueue = 0;
char silence[SILENT_SIZE] = {0};
AudioQueueAllocateBuffer(ctx->q, SILENT_SIZE, &silence_buf);
memcpy(silence_buf->mAudioData, &silence[0], SILENT_SIZE);
silence_buf->mAudioDataByteSize = SILENT_SIZE;
silence_buf->mUserData = NULL;
AudioQueueAllocateBuffer(ctx->q, SILENT_SIZE, &ctx->silence_buf);
memcpy(ctx->silence_buf->mAudioData, &silence[0], SILENT_SIZE);
ctx->silence_buf->mAudioDataByteSize = SILENT_SIZE;
ctx->silence_buf->mUserData = NULL;
}

void audio_destroy(struct audio **ctx_out)
Expand All @@ -223,8 +222,6 @@ void audio_destroy(struct audio **ctx_out)
free(ctx);
*ctx_out = NULL;
isStart = false;
AudioQueueFreeBuffer(ctx->q, silence_buf);
silence_inqueue = silence_outqueue = 0;
}

void audio_clear(struct audio **ctx_out)
Expand Down Expand Up @@ -256,7 +253,7 @@ void audio_clear(struct audio **ctx_out)
isStart = false;
ctx->in_use = 0;
ctx->fail_num = 0;
silence_inqueue = silence_outqueue = 0;
ctx->silence_inqueue = ctx->silence_outqueue = 0;
os_unfair_lock_unlock(&ctx->clear_lock);
}

Expand All @@ -276,8 +273,17 @@ void audio_cb(const int16_t *pcm, uint32_t frames, void *opaque)
return;
}

memcpy((*find_idle)->mAudioData, pcm, frames * 4);
(*find_idle)->mAudioDataByteSize = frames * 4;
// The idle buffer is a fixed BUFFER_SIZE (4096-byte) AudioQueue
// allocation, but `frames` is host-supplied and unbounded. Normal ~10ms
// chunks are well under 1024 stereo frames, so this clamp is a no-op on
// the happy path — but a post-stall recovery on a flaky link can deliver
// an oversized chunk, and `frames * 4 > BUFFER_SIZE` would memcpy past the
// buffer (heap overflow → crash/corruption). Clamp to what fits; playing a
// truncated chunk is strictly better than overrunning the allocation.
uint32_t bytes = frames * 4;
if (bytes > BUFFER_SIZE) bytes = BUFFER_SIZE;
memcpy((*find_idle)->mAudioData, pcm, bytes);
(*find_idle)->mAudioDataByteSize = bytes;

if(!isStart)
{
Expand Down
Loading