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.