michaeltyson / TPCircularBuffer

A simple, fast circular buffer implementation
http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/
839 stars 141 forks source link

TPCircularBuffer cause noise #29

Closed orklann closed 1 year ago

orklann commented 5 years ago

I am playing raw PCM data over Bluetooth, and I do a lost of tests, and finally found that when TPCircularBuffer produce bytes, the noise happen, here is the two part of my code (One get PCM data from Bluetooth device, one use Portaudio to render the PCM).

Produce bytes ->:

- (void)a2dpSink:(A2DPSink *)sink channel:(IOBluetoothL2CAPChannel *)channel rawRTPdataReceived:(NSData *)data
{
    NSData *mediaPayload = getMediaPayloadInRTP(data);
    getSBCFramesInMediaPayload(mediaPayload);
    recordCount++;

    if (recordCount == 50) {
        long index = 0;
        uint16 i;
        long size = 0;
        for (i = 0; i < [sbcFrames count]; i++) {
            size = [[sbcFrames objectAtIndex:i] length];
            memcpy((unsigned char*)buf + index, (unsigned char*)[[sbcFrames objectAtIndex:i] bytes], size);
            index += size;
        }

        [sbcFrames removeAllObjects];

        // Start decode
        int pcmBytes = 0;
        decodeSBCFramesBuffer(buf, (int)index, pcm, &pcmBytes);

        TPCircularBufferProduceBytes(&paData.buffer, pcm, pcmBytes);

        if (!played) {
            framesPerBuffer = pcmBytes / 4;
            playPortAudio();
            played = YES;
        }

        if (!Pa_IsStreamActive(stream)) {
            e = Pa_StartStream(stream);
            if( e != paNoError ) {
                NSLog(@"start stream error!");
            } else {
                NSLog(@"start stream OK!");
            }
        }
        recordCount = 0;
    }
}

Consume bytes ->

static int patestCallback( const void *inputBuffer, void *outputBuffer,
                          unsigned long framesPerBuffer,
                          const PaStreamCallbackTimeInfo* timeInfo,
                          PaStreamCallbackFlags statusFlags,
                          void *userData )
{
    paTestData *data = (paTestData*)userData;
    short *out = (short*)outputBuffer;
    unsigned long i, j;

    (void) timeInfo; /* Prevent unused variable warnings. */
    (void) statusFlags;
    (void) inputBuffer;

    uint32_t availableBytes = 0;
    unsigned char *b = TPCircularBufferTail(&data->buffer, &availableBytes);

    uint32_t frames = availableBytes / 2 / 2;
    if (b == NULL) return paContinue;
    uint32_t availableFrames = (uint32_t) MIN(frames, framesPerBuffer);
    uint32_t index = 0;
    for(i = 0; i < availableFrames; i++){
        for( j = 0; j < CHANNEL_COUNT; ++j ){
            unsigned char high = b[index];
            unsigned char low =  b[index+1];
            short s = low + (high << 8);
            *out++ = s;
            index += 2;
        }
    }
    TPCircularBufferConsume(&data->buffer, (uint32_t)index);
    return paContinue;
}

If I increase the recordCount to like 200

 if (recordCount == 50)

then the noise occur in a long period.

So I think the noise is just happen when TPCircularBufferProduceBytes(&paData.buffer, pcm, pcmBytes); is called, any idea? I am testing this issue for a few days.

pablogeek commented 5 years ago

I think I’m experimenting the same thing