ComponentResult SooperLooperAU::Render( AudioUnitRenderActionFlags &ioActionFlags, const AudioTimeStamp & inTimeStamp, UInt32 nFrames) { // save the timestamp _curr_stamp = inTimeStamp; if (_last_rendered_frames != nFrames) { _last_rendered_frames = nFrames; ConnectionsChanged(); // emit } // if we're bypassed we need to passthru the other buses if (ShouldBypassEffect()) { for (size_t n=1; n < SL_MAXLOOPS; ++n) { try { AUOutputElement *theOutput = GetOutput(n); // throws if error AUInputElement *theInput = GetInput(n); if (theOutput && theInput) { OSStatus result = theInput->PullInput(ioActionFlags, _curr_stamp, 0 /* element */, nFrames); if (result == noErr) { if(ProcessesInPlace() ) { theOutput->SetBufferList(theInput->GetBufferList() ); } else { theOutput->PrepareBuffer(nFrames); } // leave silence bit alone if(!ProcessesInPlace() ) { theInput->CopyBufferContentsTo (theOutput->GetBufferList()); } } } } catch (...) { //cerr << "got exception: " << endl; } } } return AUMIDIEffectBase::Render (ioActionFlags, inTimeStamp, nFrames); }
ComponentResult AUInlineEffectBase::RenderBus(AudioUnitRenderActionFlags & flags, const AudioTimeStamp & timestamp, UInt32 bus, UInt32 frames) { if ((bus != 0) || (! HasInput(0))) { return kAudioUnitErr_NoConnection; } ComponentResult result; AUInputElement *theInput = GetInput(0); result = theInput->PullInput(flags, timestamp, 0, frames); if (result == noErr) { AudioBufferList & inputbuffers = theInput->GetBufferList(); if (! IsBypassEffect()) { result = ProcessBufferLists(flags, inputbuffers, inputbuffers, frames); } GetOutput(0)->SetBufferList(inputbuffers); } return result; }
OSStatus Talkbox::Render(AudioUnitRenderActionFlags & ioActionFlags, const AudioTimeStamp & inTimeStamp, UInt32 inFramesToProcess) { if (! HasInput(0) ) { //fprintf(stderr, "no input bus 0 connection\n"); return kAudioUnitErr_NoConnection; } OSStatus status = noErr; AUOutputElement * theOutput = GetOutput(0); // throws if error AUInputElement * theInput = GetInput(0); status = theInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, inFramesToProcess); if (status != noErr) return status; if (status == noErr) { if ( ProcessesInPlace() ) { theOutput->SetBufferList( theInput->GetBufferList() ); } AUInputElement * theInput2 = NULL; try { if ( HasInput(1) ) theInput2 = GetInput(1); } catch (...) { theInput2 = NULL; } if (theInput2 != NULL) { bool mainInputSilentFlag = (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) ? true : false; status = theInput2->PullInput(ioActionFlags, inTimeStamp, 1 /* element */, inFramesToProcess); //if (result != noErr) fprintf(stderr, "PullInput(bus 1) error %ld\n", result); if ( !mainInputSilentFlag && (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) ) ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence; } else { status = kAudioUnitErr_NoConnection; //fprintf(stderr, "could not access input bus 1 connection\n"); } if ( ShouldBypassEffect() || (status != noErr) ) { status = noErr; // leave silence bit alone if (! ProcessesInPlace() ) { theInput->CopyBufferContentsTo( theOutput->GetBufferList() ); } } else { for (UInt32 i=0; i < numAllocatedChannels; i++) { dspKernels[i]->Process(theInput->GetChannelData(i), theInput2->GetChannelData(i), theOutput->GetChannelData(i), inFramesToProcess); } } } return status; }
OSStatus SooperLooperAU::ProcessBufferLists( AudioUnitRenderActionFlags & ioActionFlags, const AudioBufferList & inBuffer, AudioBufferList & outBuffer, UInt32 inFramesToProcess ) { // deinterleaved //const AudioBuffer *srcBuffer = inBuffer.mBuffers; //AudioBuffer *destBuffer = outBuffer.mBuffers; if (inBuffer.mNumberBuffers == 1) { if (_chancnt > 1) { //cerr << "interleaved " << _chancnt << endl; ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence; return kAudioUnitErr_InvalidParameter; } } _in_buflist[0] = (AudioBufferList *) &inBuffer; _out_buflist[0] = &outBuffer; //cerr << "main bus: " << _out_buflist[0] << " count: " << outBuffer.mNumberBuffers << endl; // this is called with the main bus (0) buffers // we really should subclass Render here, but instead // we'll just get the other busses data too for (size_t n=1; n < SL_MAXLOOPS; ++n) { try { AUOutputElement *theOutput = GetOutput(n); // throws if error AUInputElement *theInput = GetInput(n); if (theOutput && theInput) { OSStatus result = theInput->PullInput(ioActionFlags, _curr_stamp, 0 /* element */, inFramesToProcess); if (result == noErr) { if(ProcessesInPlace() ) { theOutput->SetBufferList(theInput->GetBufferList() ); } else { theOutput->PrepareBuffer(inFramesToProcess); } _in_buflist[n] = &theInput->GetBufferList(); } else { // no input, just do output theOutput->PrepareBuffer(inFramesToProcess); } if (n > _engine->loop_count()) { // zero the buffer AUBufferList::ZeroBuffer(theOutput->GetBufferList()); } else if (_engine->get_loop_channel_count(n-1, true) == 1) { // for the sidechain outputs that are mono, set the 2nd channel to be == to the first //theOutput->SetBuffer(1, theOutput->GetBufferList().mBuffers[0]); } _out_buflist[n] = &theOutput->GetBufferList(); //cerr << "got bus output: " << n << " " << _out_buflist[n] << " count: " << theOutput->GetBufferList().mNumberBuffers << endl; } else { //cerr << "don't have both in and out for: " << n << endl; } } catch (...) { //cerr << "got exception: with bus " << n << endl; } } // actually do the work _engine->process (inFramesToProcess); _in_buflist[0] = 0; _out_buflist[0] = 0; for (size_t n=1; n <= _engine->loop_count() && n < SL_MAXLOOPS; ++n) { if (_engine->get_loop_channel_count(n-1, true) == 1) { memcpy(_out_buflist[n]->mBuffers[1].mData, _out_buflist[n]->mBuffers[0].mData, sizeof(float) * inFramesToProcess); } _in_buflist[n] = 0; _out_buflist[n] = 0; } // force output to be something ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence; return noErr; }