Note that there are some explanatory texts on larger screens.

plurals
  1. POiOS UI are causing a glitch in my audio stream
    primarykey
    data
    text
    <p>I'm writing a VOIP based app for the iPhone. I'm having a strange issue where when the user presses the screen there is a glitch in the audio, this happens also when you press the volume up / down buttons on the phone itself. After days of debugging I've found its something to do with my circular buffer. I swapped mine for the one here:</p> <p><a href="http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/" rel="nofollow">http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/</a></p> <p>this one doesn't cause a glitch but the latency is nearly 4 times longer than mine, I have to have minimal latency and can't figure out whats going on with my app. </p> <p>Setup:</p> <p>I followed: <a href="http://www.stefanpopp.de/2011/capture-iphone-microphone/" rel="nofollow">http://www.stefanpopp.de/2011/capture-iphone-microphone/</a> somewhat to make the basic app but I have different settings / functions etc. I have a view controller that has a property of this audioProcessor class, this class has a variable for the circular buffer. In the recording callback I send the data, this is all fine. In a CFSocket callback I add data from the network to this buffer and then the playback callback pulls data from this buffer and passes it to the system.</p> <p>At some point during the playback if the user presses triggers a UI event it all goes to hell and this strange data shows up. I'm guessing its some sort of threading issue but I have little or no experience in this area. I'd appreciate any help. Here is the relative code:</p> <p><strong>Network Callback - adding data to buffer:</strong></p> <pre><code>static void addDataToBuffer(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) { AudioUnitCBufferProduce(&amp;audioProcessor-&gt;auCBuffer, (uint8_t*)[(__bridge NSData *)data bytes], [(__bridge NSData *)data length]); } </code></pre> <p><strong>Audio unit playback - copying data form the buffer and placing into "targetBuffer" which is pointing to ioData:</strong></p> <pre><code>static OSStatus playbackCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { uint8_t *targetBuffer = (uint8_t*)ioData-&gt;mBuffers[0].mData; AudioUnitCBufferConsume(&amp;audioProcessor-&gt;auCBuffer, targetBuffer, inNumberFrames); return noErr; } </code></pre> <p><strong>Buffer init:</strong></p> <pre><code>void AudioUnitCBufferInit(AudioUnitCBuffer *b) { // create array of bytes of length specified, fill with silence uint8_t buffer[2048]; for(int i = 0; i &lt; 2048; i++) { buffer[i] = 0xd5; } // init buffer elements b-&gt;buffer = buffer; b-&gt;consumer = buffer; b-&gt;producer = buffer; b-&gt;length = 2048; } </code></pre> <p><strong>Buffer producer / consumer:</strong></p> <p>This is written so that you pass in a pointer to the function and this pointer is then filled with the data, should there be no data the pointer will be filled with the ALAW hex value for silence. This keeps the audio unit code small as the buffer ensures that it will always supply it with data. This is also mush faster than copying to somewhere temporary and then memcpy 'ing it into the buffer which the link above uses and is far to slow for my needs.</p> <pre><code>inline static void AudioUnitCBufferProduce(AudioUnitCBuffer *b, uint8_t *bytes, int32_t len) { //printf("\n\ninside producer: len %i \n\n", len); while(len--) { // if producer catches up with consumer, skip a byte if (b-&gt;producer+1 == b-&gt;consumer) { //printf("b-&gt;producer+1 == b-&gt;consumer == continue \n"); continue; } else { //printf("b-&gt;producer+1 != b-&gt;consumer == add byte \n"); *b-&gt;producer = *bytes++; b-&gt;producer++; if(b-&gt;producer == &amp;b-&gt;buffer[b-&gt;length-1]) { //printf("\n\nproducer == end, skipping \n\n"); b-&gt;producer = b-&gt;buffer; } } } } inline static void AudioUnitCBufferConsume(AudioUnitCBuffer *b, uint8_t *bytes, int32_t len) { while(len--) { // if producer catches up with consumer, skip a byte if (b-&gt;consumer == b-&gt;producer) { *bytes++ = 0xd5; } else { *bytes++ = *b-&gt;consumer; b-&gt;consumer++; if(b-&gt;consumer == &amp;b-&gt;buffer[b-&gt;length-1]) { b-&gt;consumer = b-&gt;buffer; } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload