objective c - Using ExtAudioFileWriteAsync() in callback function. Can't get to run -


just can't seem far in core audio. goal write captured audio data instrument unit file. have set call callback function on instrument unit this:

checkerror(audiounitaddrendernotify(player->instrumentunit,                                     myrenderproc,                                     &player),            "audiounitaddrendernotify failed"); 

i set file , audiostreambasicdescription this:

#define filename @"output_iv.aif"  nsstring *filename = filename; // [nsstring stringwithformat:filename_format, hz]; nsstring *filepath = [[[nsfilemanager defaultmanager] currentdirectorypath] stringbyappendingpathcomponent: filename]; nsurl *fileurl = [nsurl fileurlwithpath: filepath]; nslog (@"path: %@", fileurl);  audiostreambasicdescription asbd; memset(&asbd, 0, sizeof(asbd)); asbd.msamplerate = 44100.0; asbd.mformatid = kaudioformatlinearpcm; asbd.mformatflags = kaudioformatflagisbigendian | kaudioformatflagissignedinteger | kaudioformatflagispacked; asbd.mchannelsperframe = 2; // changed 1 (stereo) asbd.mframesperpacket = 1; asbd.mbitsperchannel = 16; asbd.mbytesperframe = 4; asbd.mbytesperpacket = 4;  checkerror(extaudiofilecreatewithurl((__bridge cfurlref)fileurl, kaudiofileaifftype, &asbd, null, kaudiofileflags_erasefile, &testrecordfile), "extaudiofilecreatewithurl failed");  checkerror(extaudiofilesetproperty(testrecordfile, kextaudiofileproperty_clientdataformat, (uint32)sizeof(asbd), &asbd), "extaudiofilesetproperty failed");  checkerror(extaudiofilewriteasync(testrecordfile, 0, null), "extaudiofilewriteasync 1st time failed"); 

i verified file created. testrecordfile defined globally (it's way things run @ moment):

extaudiofileref testrecordfile; 

my callback function is:

osstatus myrenderproc(void *inrefcon,                   audiounitrenderactionflags *ioactionflags,                   const audiotimestamp *intimestamp,                   uint32 inbusnumber,                   uint32 innumberframes,                   audiobufferlist * iodata) {     if (*ioactionflags & kaudiounitrenderaction_postrender){     static int temp_kaudiounitrenderaction_postrendererror = (1 << 8);         if (!(*ioactionflags & temp_kaudiounitrenderaction_postrendererror)){             checkerror(extaudiofilewriteasync(testrecordfile, innumberframes, iodata), "extaudiofilewriteasync failed");         }     } return noerr; } 

when run program pinwheels , goes debugger mode (lldb) on extaudiofilewriteasync call. innumberframes = 512 , have verified getting stereo channels of float32 audio data in iodata.

what missing here?

first, code still complicated, , including of "dark corners" of coreaudio , obj-c. safer bet first making sure works intended in plain-c, on real-time thread. have debugged part of code can add obj-c elegance needed.

if ignoring possible endianness , file format conversion issues simplicity, there still one issue either have resolve automatically, using api utilities, or "manually":

afaik, data format extaudiofilewriteasync() must interleaved, while stream format augraph not. assuming don't deal endiannes , format conversion here, how can fix manually (single-channel example). in case asbd stream format non-interleaved stereo, interleave data in buffer this: lrlrlrlrlr...

osstatus myrenderproc(void *inrefcon,                    audiounitrenderactionflags *ioactionflags,                   const audiotimestamp *intimestamp,                   uint32 inbusnumber,                   uint32 innumberframes,                   audiobufferlist * iodata)  { audiobufferlist bufferlist; float32 samples[innumberframes+innumberframes];  bufferlist.mnumberbuffers = 1; bufferlist.mbuffers[0].mdata = samples; bufferlist.mbuffers[0].mnumberchannels = 1; bufferlist.mbuffers[0].mdatabytesize = (innumberframes+innumberframes)*sizeof(float32); float32 *data = (float32 *)iodata->mbuffers[0].mdata;  if (*ioactionflags & kaudiounitrenderaction_postrender){     static int temp_kaudiounitrenderaction_postrendererror = (1 << 8);     if (!(*ioactionflags & temp_kaudiounitrenderaction_postrendererror) {           for(uint32 = 0; < innumberframes; i++)             samples[i+i] = samples [i+i+1] = data[i];//copy buffer[0] l & r                     extaudiofilewriteasync(testrecordfile, innumberframes, &bufferlist);     } } return noerr; } 

this 1 example show how works. studying asbd.mformatflags , setting proper format in:

extaudiofilesetproperty(testrecordfile,                         kextaudiofileproperty_clientdataformat,                         s,                         &asbd); 

you can achieve more elegantly, exceeds scope post far.