audio - Opus for iOS, crashing with 16000 sample rate -


i developing voip application opus ios (objective-c , c++).
works fine 8000, 12000, 24000 , 48000 sampling rate except 16000, application crashes on opus_encode method.


here doing:

m_oaudiosession = [avaudiosession sharedinstance]; [m_oaudiosession setcategory:avaudiosessioncategoryplayandrecord error:&m_oerror]; [m_oaudiosession setmode:avaudiosessionmodevoicechat error:&m_oerror];  [m_oaudiosession setpreferredsamplerate:voip_audio_driver_default_sample_rate error:&m_oerror]; [m_oaudiosession setpreferredinputnumberofchannels:voip_audio_driver_default_input_channels error:&m_oerror]; [m_oaudiosession setpreferredoutputnumberofchannels:voip_audio_driver_default_output_channels error:&m_oerror]; [m_oaudiosession setpreferrediobufferduration:voip_audio_driver_default_buffer_duration error:&m_oerror];  [m_oaudiosession setactive:yes error:&m_oerror]; 


constants:

voip_audio_driver_default_sample_rate 16000 voip_audio_driver_default_input_channels 1 voip_audio_driver_default_output_channels 1 voip_audio_driver_default_buffer_duration 0.02 voip_audio_driver_frames_per_packet 1 


after using real sampling rate , buffer duration m_oaudiosession.samplerate , m_oaudiosession.iobufferduration. set m_fsamplerate , m_fbufferduration variables.

the configurations are:

//describes audio component: m_saudiodescription.componenttype         = kaudiounittype_output; m_saudiodescription.componentsubtype      = kaudiounitsubtype_voiceprocessingio/*kaudiounitsubtype_remoteio*/; m_saudiodescription.componentflags        = 0; m_saudiodescription.componentflagsmask    = 0; m_saudiodescription.componentmanufacturer = kaudiounitmanufacturer_apple;  m_saudioformat.msamplerate          = m_fsamplerate; m_saudioformat.mformatid            = kaudioformatlinearpcm; m_saudioformat.mformatflags         = kaudioformatflagissignedinteger | kaudioformatflagispacked; m_saudioformat.mframesperpacket     = voip_audio_driver_frames_per_packet; m_saudioformat.mchannelsperframe    = voip_audio_driver_default_input_channels; m_saudioformat.mbitsperchannel      = (uint32)(8 * m_ibytespersample); m_saudioformat.mbytesperframe       = (uint32)((m_saudioformat.mbitsperchannel / 8) * m_saudioformat.mchannelsperframe);  m_saudioformat.mbytesperpacket      = m_saudioformat.mbytesperframe * m_saudioformat.mframesperpacket;  m_saudioformat.mreserved            = 0; 


calculations make are:

m_ibytespersample = sizeof(/*audiosampletype*/sint16);  //calculating buffer size: int samplesperframe = (int)(m_fbufferduration * m_fsamplerate) + 1; m_ibuffersizebytes = samplesperframe * m_ibytespersample;  //allocating input buffer: uint32 inputbufferlistsize = offsetof(audiobufferlist, mbuffers[0]) + (sizeof(audiobuffer) * m_saudioformat.mchannelsperframe); m_sinputbuffer = (audiobufferlist *)voipalloc(inputbufferlistsize); m_sinputbuffer->mnumberbuffers = m_saudioformat.mchannelsperframe;  //pre-mallocating buffers audiobufferlists for(voipuint32 tmp_int1 = 0; tmp_int1 < m_sinputbuffer->mnumberbuffers; tmp_int1++) {     m_sinputbuffer->mbuffers[tmp_int1].mnumberchannels = voip_audio_driver_default_input_channels;     m_sinputbuffer->mbuffers[tmp_int1].mdatabytesize = (uint32)m_ibuffersizebytes;     m_sinputbuffer->mbuffers[tmp_int1].mdata = voipalloc(m_ibuffersizebytes);     memset(m_sinputbuffer->mbuffers[tmp_int1].mdata, 0, m_ibuffersizebytes); } 


reading , writing audio unit done using m_sinputbuffer.


here opus creation:

m_oencoder = opus_encoder_create(m_isamplerate, m_inumberofchannels, voip_audio_codecs_opus_application_type, &_error); if (_error < 0) {     fprintf(stderr, "voipaudiocodecs error: failed create encoder: %s\n", opus_strerror(_error));      return; }  _error = opus_encoder_ctl(m_oencoder, opus_set_bitrate(voip_audio_codecs_opus_bitrate)); if (_error < 0) {     fprintf(stderr, "voipaudiocodecs error: failed set bitrate: %s\n", opus_strerror(_error));      return; }  m_odecoder = opus_decoder_create(m_isamplerate, m_inumberofchannels, &_error); if (_error < 0) {     fprintf(stderr, "voipaudiocodecs error: failed create decoder: %s\n", opus_strerror(_error));      return; } 


opus configurations are:

voip_audio_codecs_opus_bitrate opus_bitrate_max  //64000 //70400 //84800 //112000 voip_audio_codecs_opus_application_type opus_application_voip //opus_application_audio voip_audio_codecs_opus_max_frame_size 5760  //minimum: (120ms; 5760 48khz) voip_audio_codecs_opus_bytes_size 960  //120, 240, 480, 960, 1920, 2880 


when encode , decode use these methods:

encode_opus(voipint16* rawsamples, int rawsamplessize) {     unsigned char encodeddata[m_imaxpacketsize];     voipint32 bytesencoded;     int framesize = rawsamplessize / m_ibytespersample;      bytesencoded = opus_encode(m_oencoder, rawsamples, framesize, encodeddata, m_imaxpacketsize);     if (bytesencoded < 0)     {         fprintf(stderr, "voipaudiocodecs error: encode failed: %s\n", opus_strerror(bytesencoded));          return nullptr;     }      svoipaudiocodecopusencoded* resultstruct = (svoipaudiocodecopusencoded* )voipalloc(sizeof(svoipaudiocodecopusencoded));      resultstruct->m_data = (unsigned char*)voipalloc(bytesencoded);     memcpy(resultstruct->m_data, encodeddata, bytesencoded);     resultstruct->m_datasize = bytesencoded;      return resultstruct; }  decode_opus(void* encodedsamples, voipint32 encodedsamplessize) {     voipint16 decodedpacket[voip_audio_codecs_opus_max_frame_size];      int _framesize = opus_decode(m_odecoder, (const unsigned char*)encodedsamples, encodedsamplessize, decodedpacket, voip_audio_codecs_opus_max_frame_size, 0);     if (_framesize < 0)     {         fprintf(stderr, "voipaudiocodecs error: decoder failed: %s\n", opus_strerror(_framesize));          return nullptr;     }      size_t framesize = (size_t)_framesize;      svoipaudiocodecopusdecoded* resultstruct = (svoipaudiocodecopusdecoded* )voipalloc(sizeof(svoipaudiocodecopusdecoded));      resultstruct->m_data = (voipint16*)voipalloc(framesize * m_ibytespersample);     memcpy(resultstruct->m_data, decodedpacket, (framesize * m_ibytespersample));     resultstruct->m_datasize = framesize * m_ibytespersample;      return resultstruct; } 


when app should send data:

voipuint32 itemsforprocess = inputaudioqueue->getitemcount(); (int tmp_queueitems = 0; tmp_queueitems < itemsforprocess; tmp_queueitems++) {     svoipqueue* tmp_samples = inputaudioqueue->popitem();      m_ocirculartempinputbuffer->writedatatobuffer(tmp_samples->m_pdata, tmp_samples->m_idatasize);     while (void* tmp_buffer = m_ocirculartempinputbuffer->readdatafrombuffer(voip_audio_codecs_opus_bytes_size))     {         svoipaudiocodecopusencoded* encodedsamples = encode_opus((voipint16*)tmp_buffer, voip_audio_codecs_opus_bytes_size);          //then packeting , real sending using tcp socket…     }     //rest of code… } 


here reading:

svoipaudiocodecopusdecoded* decodedsamples = decode_opus(inputpacket->m_ppacketdata, (voipint32)inputpacket->m_ipacketsize); if (decodedsamples != nullptr) {     m_ocirculartempoutputbuffer->writedatatobuffer(decodedsamples->m_data, decodedsamples->m_datasize);      voipfree((void**)&decodedsamples->m_data);     voipfree((void**)&decodedsamples); }  while (void* tmp_buffer = m_ocirculartempoutputbuffer->readdatafrombuffer(m_ibuffersizebytes)) {     outputaudioqueue->pushitem(tmp_buffer, m_ibuffersizebytes); } 

inputaudioqueue queue recorded data audio unit’s callback.
outputaudioqueue queue used audio unit’s callback play sound.
m_imaxpacketsize same m_ibuffersizebytes.


questions are:
wondering, calculations correct?
, if not, how can improve them?
see mistake code?
have suggestion fixing crash bug on opus_encode method when sampling rate set 16000?

thank in advance.

ps. made tests sampling rate on 16000 , found this:
if use formula: frame_duration = frame_size / sample rate, , if set frame_duration preferediobufferduration:
120 / 16000 = 0.0075 //avaudiosession sets 0.008000 —— crashes
240 / 16000 = 0.015 //avaudiosession sets 0.016000 —— crashes
480 / 16000 = 0.03 //avaudiosession sets 0.032000 —— crashes
960 / 16000 = 0.06 //avaudiosession sets 0.064000 —— crashes
1920 / 16000 = 0.12 //avaudiosession sets 0.128000 —— works
2880 / 16000 = 0.18 //avaudiosession sets 0.128000 —— crashes
then found there no encoder crash sampling rate 16000 , preferrediobufferduration 0.12(1920), avaudiosession sets 0.128000. works in case.

ideas ?


Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -