diff --git a/OpenParsec/audio.c b/OpenParsec/audio.c index 3803439..7dae111 100644 --- a/OpenParsec/audio.c +++ b/OpenParsec/audio.c @@ -8,8 +8,14 @@ #define BUFFER_SIZE 4096 #define SILENT_SIZE 4096 #define FAKE_SIZE 0 +#define ALLOW_DELAY 8 +#define LOWEST_NUM_BUFFER 3 bool isMuted = false; bool isStart = false; +int lastbuf = 0; + +unsigned int silence_inqueue = 0; +unsigned int silence_outqueue = 0; AudioQueueBufferRef silence_buf; typedef struct RecycleChain { @@ -28,6 +34,7 @@ struct audio { AudioQueueRef q; AudioQueueBufferRef audio_buf[NUM_AUDIO_BUF]; char *mem[NUM_AUDIO_BUF * 2]; + int loc[NUM_AUDIO_BUF]; RecycleChainMgr rcm; int32_t fail_num; int32_t in_use; @@ -36,7 +43,9 @@ struct audio { static void audio_queue_callback(void *opaque, AudioQueueRef queue, AudioQueueBufferRef buffer) { struct audio *ctx = (struct audio *) opaque; - + int deltaBuf = 0; + //int silence_use_count = (int)(silence_buf->mUserData); + if (ctx == NULL) return; @@ -45,26 +54,85 @@ static void audio_queue_callback(void *opaque, AudioQueueRef queue, AudioQueueBu ctx->in_use -= buffer->mAudioDataByteSize; } - if(buffer != silence_buf) buffer->mAudioDataByteSize = FAKE_SIZE; - RecycleChain *tmp = ctx->rcm.last_to_queue->next; - if ( /*(*tmp->curt)->mAudioDataByteSize != FAKE_SIZE &&*/ tmp != ctx->rcm.first) + if(buffer != silence_buf) { - //while(ctx->rcm.last_to_queue->next != ctx->rcm.first) - //{ - AudioQueueEnqueueBuffer(ctx->q, (*(ctx->rcm.last_to_queue->next->curt)), 0, NULL); - ctx->rcm.last_to_queue = ctx->rcm.last_to_queue->next; - //} + buffer->mAudioDataByteSize = FAKE_SIZE; + lastbuf = *((int *)(buffer->mUserData)); } - else //if ((*ctx->rcm.last_use)->mAudioDataByteSize == FAKE_SIZE) + else { - AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL); - AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL); - AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL); - /*AudioQueueStop(ctx->q, true); - isStart = false; - ctx->in_use = 0;*/ + //silence_use_count = 0; + //silence_buf->mUserData = (void *)(0); + ++silence_outqueue; + } + + if (isMuted) return; + + deltaBuf = *((int *)((*ctx->rcm.first->curt)->mUserData)); + deltaBuf = deltaBuf - lastbuf - 1; + if (deltaBuf < 0) deltaBuf += NUM_AUDIO_BUF; + + while(ctx->rcm.last_to_queue->next != ctx->rcm.first) + { + AudioQueueEnqueueBuffer(ctx->q, (*(ctx->rcm.last_to_queue->next->curt)), 0, NULL); + ctx->rcm.last_to_queue = ctx->rcm.last_to_queue->next; + } + + if (deltaBuf + silence_inqueue < LOWEST_NUM_BUFFER + 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))); + if (numAddBuffer > LOWEST_NUM_BUFFER) + { + numAddBuffer = LOWEST_NUM_BUFFER - deltaBuf; + } + else + { + silence_inqueue = silence_outqueue = 0; + } + for (int i=0; iq, silence_buf, 0, NULL); + } + if (numAddBuffer > 0) silence_inqueue += numAddBuffer; } + //RecycleChain *tmp = ctx->rcm.last_to_queue->next; + //if ( /*(*tmp->curt)->mAudioDataByteSize != FAKE_SIZE &&*/ tmp != ctx->rcm.first) + //if (deltaBuf > ALLOW_DELAY) + //{ + // //while(ctx->rcm.last_to_queue->next != ctx->rcm.first) + // for (int i = 0; i < deltaBuf - ALLOW_DELAY + 1; ++i) + // { + // AudioQueueEnqueueBuffer(ctx->q, (*(ctx->rcm.last_to_queue->next->curt)), 0, NULL); + // ctx->rcm.last_to_queue = ctx->rcm.last_to_queue->next; + // } + //} + //else + //{ + // int silence_use_count = (int)(silence_buf->mUserData); + // if ( deltaBuf > 0 ) + // { + // AudioQueueEnqueueBuffer(ctx->q, (*(ctx->rcm.last_to_queue->next->curt)), 0, NULL); + // ctx->rcm.last_to_queue = ctx->rcm.last_to_queue->next; + // } + // else if (silence_use_count == 0) + // { + // AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL); + // //int tmp = (int)(silence_buf->mUserData); + // //++tmp; + // silence_buf->mUserData = (void *)(1); + // } + //} + //else //if ((*ctx->rcm.last_use)->mAudioDataByteSize == FAKE_SIZE) + //{ + // AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL); + // AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL); + // AudioQueueEnqueueBuffer(ctx->q, silence_buf, 0, NULL); + // /*AudioQueueStop(ctx->q, true); + // isStart = false; + // ctx->in_use = 0;*/ + //} + /*if(ctx->rcm.last_to_queue->curt == &buffer && ctx->rcm.last_to_queue->next == ctx->rcm.first) // && (*ctx->rcm.first->curt)->mAudioDataByteSize == FAKE_SIZE) { AudioQueueStop(ctx->q, true); @@ -107,7 +175,8 @@ void audio_init(struct audio **ctx_out) for (int32_t x = 0; x < NUM_AUDIO_BUF; x++) { AudioQueueAllocateBuffer(ctx->q, BUFFER_SIZE, &ctx->audio_buf[x]); ctx->audio_buf[x]->mAudioDataByteSize = FAKE_SIZE; - + ctx->loc[x] = x; + ctx->audio_buf[x]->mUserData = (void *)(&ctx->loc[x]); rcTraverse->curt = &ctx->audio_buf[x]; if( x != NUM_AUDIO_BUF - 1) { @@ -119,16 +188,17 @@ void audio_init(struct audio **ctx_out) //ctx->rcm.first = rcTraverse; rcTraverse->next = ctx->rcm.rc; } - } isStart = false; ctx->fail_num = 0; ctx->in_use = 0; + silence_inqueue = 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; } void audio_destroy(struct audio **ctx_out) @@ -151,6 +221,7 @@ void audio_destroy(struct audio **ctx_out) *ctx_out = NULL; isStart = false; AudioQueueFreeBuffer(ctx->q, silence_buf); + silence_inqueue = silence_outqueue = 0; } void audio_clear(struct audio **ctx_out) @@ -181,6 +252,7 @@ void audio_clear(struct audio **ctx_out) isStart = false; ctx->in_use = 0; ctx->fail_num = 0; + silence_inqueue = silence_outqueue = 0; } void audio_cb(const int16_t *pcm, uint32_t frames, void *opaque)