Note that there are some explanatory texts on larger screens.

plurals
  1. POrecord sounds played by my iPhone app with audio units
    primarykey
    data
    text
    <p>I have red a lot of interesting stuff today about <strong>iOS &amp; Audio Units</strong> and have found a lot of usefull resources (SO included).</p> <p><strong>First of all</strong>, i am confused with something : Is it really necessary to create an <em>audio graph</em> with <em>mixer unit</em> to record sounds played by an app ? </p> <p>Or is it sufficient to play sounds with <a href="https://github.com/kstenerud/ObjectAL-for-iPhone" rel="nofollow" title="ObjectAL, luv it !">ObjectAL</a> (or more simply AVAudioPlayer calls) and create a single <em>remote io unit</em> adressed on the correct bus with a recording callback ?</p> <p><strong>Second</strong>, a more programmatically issue ! As i'm not already comfortable with <em>Audio Units</em> concepts, i try to adapt the <a href="http://developer.apple.com/library/ios/#samplecode/MixerHost/Introduction/Intro.html" rel="nofollow">apple Mixer Host project</a> with the ability to record the resulting mix. Obviously, i try to do this with the <a href="http://atastypixel.com/blog/using-remoteio-audio-unit/" rel="nofollow">Michael Tyson RemoteIO post</a>.</p> <p>And I get a EXC_BAD_ACCESS on my callback function :</p> <pre><code>static OSStatus recordingCallback (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { AudioBufferList *bufferList; // &lt;- Fill this up with buffers (you will want to malloc it, as it's a dynamic-length list) EffectState *effectState = (EffectState *)inRefCon; AudioUnit rioUnit = effectState-&gt;rioUnit; OSStatus status; // BELOW I GET THE ERROR status = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, bufferList); if (noErr != status) { NSLog(@"AudioUnitRender error"); return noErr;} // Now, we have the samples we just read sitting in buffers in bufferList //ExtAudioFileWriteAsync(effectState-&gt;audioFileRef, inNumberFrames, bufferList); return noErr; } </code></pre> <p>Before using the callback function i did in <strong>MixerHostAudio.h</strong></p> <pre><code>typedef struct { AudioUnit rioUnit; ExtAudioFileRef audioFileRef; } EffectState; </code></pre> <p>And create in the interface :</p> <pre><code>AudioUnit iOUnit; EffectState effectState; AudioStreamBasicDescription iOStreamFormat; ... @property AudioUnit iOUnit; @property (readwrite) AudioStreamBasicDescription iOStreamFormat; </code></pre> <p>Then in the implementation file <strong>MixerHostAudio.h</strong> :</p> <pre><code>#define kOutputBus 0 #define kInputBus 1 ... @synthesize iOUnit; // the Remote IO unit ... result = AUGraphNodeInfo ( processingGraph, iONode, NULL, &amp;iOUnit ); if (noErr != result) {[self printErrorMessage: @"AUGraphNodeInfo" withStatus: result]; return;} // Enable IO for recording UInt32 flag = 1; result = AudioUnitSetProperty(iOUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &amp;flag, sizeof(flag)); if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;} // Describe format iOStreamFormat.mSampleRate = 44100.00; iOStreamFormat.mFormatID = kAudioFormatLinearPCM; iOStreamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; iOStreamFormat.mFramesPerPacket = 1; iOStreamFormat.mChannelsPerFrame = 1; iOStreamFormat.mBitsPerChannel = 16; iOStreamFormat.mBytesPerPacket = 2; iOStreamFormat.mBytesPerFrame = 2; // Apply format result = AudioUnitSetProperty(iOUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &amp;iOStreamFormat, sizeof(iOStreamFormat)); if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;} result = AudioUnitSetProperty(iOUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &amp;iOStreamFormat, sizeof(iOStreamFormat)); if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;} effectState.rioUnit = iOUnit; // Set input callback ----&gt; RECORDING AURenderCallbackStruct callbackStruct; callbackStruct.inputProc = recordingCallback; callbackStruct.inputProcRefCon = self; result = AudioUnitSetProperty(iOUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &amp;callbackStruct, sizeof(callbackStruct)); if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;} </code></pre> <p>But I don't know what's wrong and don't know how to digg. Note : The <em>EffectState</em> struct is present because I also try to integrate the <a href="https://github.com/brennon/BioAudio" rel="nofollow">BioAudio project</a> ability to write file from buffers.</p> <p><strong>And Third</strong>, I wonder if there something easier to do to record sounds played by my iPhone app (ie microphone excluded) ?</p>
    singulars
    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