osx - Crackling audio due to wrong audio data -


i'm using coreaudio low level api audio capturing. app target mac osx, not ios.

during testing it, time time got annoying noise modulate real audio. phenomena develops time, started barely noticeable , become more , more dominant.

analyze captured audio under audacity indicate end part of audio packet wrong.

here sample picture: enter image description here

the intrusion repeat every 40 ms configured packetization time (in terms of buffer samples)

update: on time gap became larger, here snapshot same captured file 10 minutes later. gap contains 1460 samples 33ms total 40ms of packet!! enter image description here

code snippests:

capture callback

osstatus macos_audiodevice::capturecallback(void *inrefcon,                                             audiounitrenderactionflags *ioactionflags,                                             const audiotimestamp *intimestamp,                                             uint32 inbusnumber,                                             uint32 innumberframes,                                             audiobufferlist *iodata) {     macos_audiodevice* _this = static_cast<macos_audiodevice*>(inrefcon);      // new audio data     osstatus err = audiounitrender(_this->m_auhal, ioactionflags, intimestamp, inbusnumber, innumberframes, _this->m_inputbuffer);     if (err != noerr)     {         ...          return err;     }      // ignore callback on unexpected buffer size     if (_this->m_params.buffersizesamples != innumberframes)     {         ...          return noerr;     }      // deliver audio data      deviceiomessage message;     message.buffersizebytes = _this->m_devicebuffersizebytes;     message.buffer = _this->m_inputbuffer->mbuffers[0].mdata;     if (_this->m_callbackfunc)     {        _this->m_callbackfunc(_this, message);     } } 

open , start capture device:

void macos_audiodevice::openauhalcapture() {     uint32 enableio;     audiostreambasicdescription streamformat;     uint32 size;     sint32 *channelarr;     std::stringstream ss;     audioobjectpropertyaddress devicebufsizeproperty =     {         kaudiodevicepropertybufferframesize,         kaudiodevicepropertyscopeinput,         kaudioobjectpropertyelementmaster     };      // auhal     audiocomponentdescription cd = {kaudiounittype_output, kaudiounitsubtype_haloutput, kaudiounitmanufacturer_apple, 0, 0};     audiocomponent haloutput = audiocomponentfindnext(null, &cd);     verify_macosapi(audiocomponentinstancenew(haloutput, &m_auhal));      verify_macosapi(audiounitinitialize(m_auhal));      // enable input io     enableio = 1;     verify_macosapi(audiounitsetproperty(m_auhal, kaudiooutputunitproperty_enableio, kaudiounitscope_input, 1, &enableio, sizeof(enableio)));      // disable output io     enableio = 0;     verify_macosapi(audiounitsetproperty(m_auhal, kaudiooutputunitproperty_enableio, kaudiounitscope_output, 0, &enableio, sizeof(enableio)));      // setup current device     size = sizeof(audiodeviceid);     verify_macosapi(audiounitsetproperty(m_auhal, kaudiooutputunitproperty_currentdevice, kaudiounitscope_global, 0, &m_macdeviceid, sizeof(audiodeviceid)));      // set device native buffer length before setting auhal stream     size = sizeof(m_originaldevicebuffertimeframes);     verify_macosapi(audioobjectsetpropertydata(m_macdeviceid, &devicebufsizeproperty, 0, null, size, &m_originaldevicebuffertimeframes));      // device format     size = sizeof(audiostreambasicdescription);     verify_macosapi(audiounitgetproperty(m_auhal, kaudiounitproperty_streamformat, kaudiounitscope_input, 1, &streamformat, &size));      // setup channel map     assert(m_params.numofchannels <= streamformat.mchannelsperframe);     channelarr = new sint32[streamformat.mchannelsperframe];     (int = 0; < streamformat.mchannelsperframe; i++)         channelarr[i] = -1;     (int = 0; < m_params.numofchannels; i++)         channelarr[i] = i;      verify_macosapi(audiounitsetproperty(m_auhal, kaudiooutputunitproperty_channelmap, kaudiounitscope_input, 1, channelarr, sizeof(sint32) * streamformat.mchannelsperframe));     delete [] channelarr;      // setup stream converters     streamformat.mformatid = kaudioformatlinearpcm;     streamformat.mformatflags = kaudioformatflagissignedinteger;     streamformat.mframesperpacket = m_samplesperpacket;     streamformat.mbitsperchannel = m_params.sampledepthbits;     streamformat.msamplerate = m_devicesamplerate;     streamformat.mchannelsperframe = 1;     streamformat.mbytesperframe = 2;     streamformat.mbytesperpacket = streamformat.mframesperpacket * streamformat.mbytesperframe;      verify_macosapi(audiounitsetproperty(m_auhal, kaudiounitproperty_streamformat, kaudiounitscope_output, 1, &streamformat, size));      // setup callbacks     aurendercallbackstruct input;     input.inputproc = capturecallback;     input.inputprocrefcon = this;     verify_macosapi(audiounitsetproperty(m_auhal, kaudiooutputunitproperty_setinputcallback, kaudiounitscope_global, 0, &input, sizeof(input)));      // calculate size of io buffer (in samples)     if (m_params.buffersizems != -1)     {         unsigned int desiredsignalsinbuffer = (m_params.buffersizems / (double)1000) * m_devicesamplerate;          // making sure value stay in device's supported range         desiredsignalsinbuffer = std::min<unsigned int>(desiredsignalsinbuffer, m_devicebufferframesrange.mmaximum);         desiredsignalsinbuffer = std::max<unsigned int>(m_devicebufferframesrange.mminimum, desiredsignalsinbuffer);          m_devicebufferframes = desiredsignalsinbuffer;     }      // set device buffer length     size = sizeof(m_devicebufferframes);     verify_macosapi(audioobjectsetpropertydata(m_macdeviceid, &devicebufsizeproperty, 0, null, size, &m_devicebufferframes));      m_devicebuffersizebytes = m_devicebufferframes * streamformat.mbytesperframe;     m_devicebuffertimems = 1000 * m_devicebufferframes/m_devicesamplerate;      // calculate number of buffers channels     size = offsetof(audiobufferlist, mbuffers[0]) + (sizeof(audiobuffer) * m_params.numofchannels);      // allocate input buffer     m_inputbuffer = (audiobufferlist *)malloc(size);     m_inputbuffer->mnumberbuffers = m_params.numofchannels;      // pre-malloc buffers audiobufferlists     for(uint32 = 0; i< m_inputbuffer->mnumberbuffers ; i++)     {         m_inputbuffer->mbuffers[i].mnumberchannels = 1;         m_inputbuffer->mbuffers[i].mdatabytesize = m_devicebuffersizebytes;         m_inputbuffer->mbuffers[i].mdata = malloc(m_devicebuffersizebytes);     }      // update class properties     m_params.sampleratehz = streamformat.msamplerate;     m_params.buffersizesamples = m_devicebufferframes;     m_params.buffersizebytes = m_params.buffersizesamples * streamformat.mbytesperframe;  }   eadmreturncode macos_audiodevice::start() {     eadmreturncode ret = ok;     logapi(ret);      if (!m_isstarted && m_isopen)     {         osstatus err = audiooutputunitstart(m_auhal);         if (err == noerr)             m_isstarted = true;         else             ret = error;     }     return ret; } 

any idea cause , how solve?

thanks in advance!

periodic glitches or dropouts can caused not paying attention or not processing number of frames sent each audio callback. valid buffers don't contain expected or same number of samples (innumberframes might not equal buffersizesamples or previous innumberframes in valid audio buffer).

it possible these types of glitches might caused attempting record @ 44.1k on models of ios devices support 48k audio in hardware.

some types of glitch might caused non-hard-real-time code within m_callbackfunc function (such synchronous file reads/writes, os calls, objective c message dispatch, gc, or memory allocation/deallocation).


Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -