ComponentResult AUInstrumentBase::Render( AudioUnitRenderActionFlags & ioActionFlags, const AudioTimeStamp & inTimeStamp, UInt32 inNumberFrames) { PerformEvents(inTimeStamp); UInt32 numOutputs = Outputs().GetNumberOfElements(); for (UInt32 j = 0; j < numOutputs; ++j) { AudioBufferList& bufferList = GetOutput(j)->GetBufferList(); for (UInt32 k = 0; k < bufferList.mNumberBuffers; ++k) { memset(bufferList.mBuffers[k].mData, 0, bufferList.mBuffers[k].mDataByteSize); } } UInt32 numGroups = Groups().GetNumberOfElements(); for (UInt32 j = 0; j < numGroups; ++j) { SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j); OSStatus err = group->Render(inNumberFrames); if (err) return err; } mAbsoluteSampleFrame += inNumberFrames; return noErr; }
ComponentResult AUInstrumentBase::Reset( AudioUnitScope inScope, AudioUnitElement inElement) { #if DEBUG_PRINT printf("AUInstrumentBase::Reset\n"); #endif if (inScope == kAudioUnitScope_Global) { // kill all notes.. mFreeNotes.Empty(); for (UInt32 i=0; i<mNumNotes; ++i) { SynthNote *note = GetNote(i); if (note->IsSounding()) note->Kill(0); note->ListRemove(); mFreeNotes.AddNote(note); } mNumActiveNotes = 0; mAbsoluteSampleFrame = 0; // empty lists. UInt32 numGroups = Groups().GetNumberOfElements(); for (UInt32 j = 0; j < numGroups; ++j) { SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j); group->Reset(); } } return noErr; }
OSStatus AUInstrumentBase::HandleControlChange( UInt8 inChannel, UInt8 inController, UInt8 inValue, UInt32 inStartFrame) { #if DEBUG_PRINT printf("AUInstrumentBase::HandleControlChange ch %u ctlr: %u val: %u frm: %u\n", inChannel, inController, inValue, inStartFrame); #endif SynthGroupElement *gp = GetElForGroupID(inChannel); if (gp) { gp->ChannelMessage(inController, inValue); } else return kAudioUnitErr_InvalidElement; switch (inController) { case kMidiController_Sustain : if (inValue >= 64) SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOn, inStartFrame); else SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOff, inStartFrame); break; case kMidiController_Sostenuto : if (inValue >= 64) SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOn, inStartFrame); else SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOff, inStartFrame); break; } return noErr; }
OSStatus AUInstrumentBase::Render( AudioUnitRenderActionFlags & ioActionFlags, const AudioTimeStamp & inTimeStamp, UInt32 inNumberFrames) { PerformEvents(inTimeStamp); AUScope &outputs = Outputs(); UInt32 numOutputs = outputs.GetNumberOfElements(); for (UInt32 j = 0; j < numOutputs; ++j) { GetOutput(j)->PrepareBuffer(inNumberFrames); // AUBase::DoRenderBus() only does this for the first output element AudioBufferList& bufferList = GetOutput(j)->GetBufferList(); for (UInt32 k = 0; k < bufferList.mNumberBuffers; ++k) { memset(bufferList.mBuffers[k].mData, 0, bufferList.mBuffers[k].mDataByteSize); } } UInt32 numGroups = Groups().GetNumberOfElements(); for (UInt32 j = 0; j < numGroups; ++j) { SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j); OSStatus err = group->Render((SInt64)inTimeStamp.mSampleTime, inNumberFrames, outputs); if (err) return err; } mAbsoluteSampleFrame += inNumberFrames; return noErr; }
OSStatus AUInstrumentBase::HandleChannelPressure(UInt8 inChannel, UInt8 inValue, UInt32 inStartFrame) { SynthGroupElement *gp = GetElForGroupID(inChannel); if (gp) { gp->ChannelMessage(kMidiMessage_ChannelPressure, inValue); return noErr; } else return kAudioUnitErr_InvalidElement; }
OSStatus AUInstrumentBase::HandlePitchWheel( UInt8 inChannel, UInt8 inPitch1, // LSB UInt8 inPitch2, // MSB UInt32 inStartFrame) { SynthGroupElement *gp = GetElForGroupID(inChannel); if (gp) { gp->ChannelMessage(kMidiMessage_PitchWheel, (inPitch2 << 7) | inPitch1); return noErr; } else return kAudioUnitErr_InvalidElement; }
OSStatus AUInstrumentBase::HandlePolyPressure( UInt8 inChannel, UInt8 inKey, UInt8 inValue, UInt32 inStartFrame) { SynthGroupElement *gp = GetElForGroupID(inChannel); if (gp) { // Combine key and value into single argument. UGLY! gp->ChannelMessage(kMidiMessage_PolyPressure, (inKey << 7) | inValue); return noErr; } else return kAudioUnitErr_InvalidElement; }
OSStatus AUInstrumentBase::HandleProgramChange( UInt8 inChannel, UInt8 inValue) { #if DEBUG_PRINT printf("AUInstrumentBase::HandleProgramChange %u %u\n", inChannel, inValue); #endif SynthGroupElement *gp = GetElForGroupID(inChannel); if (gp) { gp->ChannelMessage(kMidiMessage_ProgramChange, inValue); return noErr; } else return kAudioUnitErr_InvalidElement; }
SynthGroupElement * AUInstrumentBase::GetElForNoteID (NoteInstanceID inNoteID) { #if DEBUG_PRINT printf("GetElForNoteID id %u\n", inNoteID); #endif AUScope & groups = Groups(); unsigned int numEls = groups.GetNumberOfElements(); for (unsigned int i = 0; i < numEls; ++i) { SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i)); if (el->GetNote(inNoteID) != NULL) // searches for any note state return el; } throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement); }
void AUInstrumentBase::PerformEvents(const AudioTimeStamp& inTimeStamp) { #if DEBUG_PRINT_RENDER printf("AUInstrumentBase::PerformEvents\n"); #endif SynthEvent *event; SynthGroupElement *group; while ((event = mEventQueue.ReadItem()) != NULL) { #if DEBUG_PRINT_RENDER printf("event %08X %d\n", event, event->GetEventType()); #endif switch(event->GetEventType()) { case SynthEvent::kEventType_NoteOn : RealTimeStartNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(), event->GetOffsetSampleFrame(), *event->GetParams()); break; case SynthEvent::kEventType_NoteOff : RealTimeStopNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(), event->GetOffsetSampleFrame()); break; case SynthEvent::kEventType_SustainOn : group = GetElForGroupID (event->GetGroupID()); group->SustainOn(event->GetOffsetSampleFrame()); break; case SynthEvent::kEventType_SustainOff : group = GetElForGroupID (event->GetGroupID()); group->SustainOff(event->GetOffsetSampleFrame()); break; case SynthEvent::kEventType_SostenutoOn : group = GetElForGroupID (event->GetGroupID()); group->SostenutoOn(event->GetOffsetSampleFrame()); break; case SynthEvent::kEventType_SostenutoOff : group = GetElForGroupID (event->GetGroupID()); group->SostenutoOff(event->GetOffsetSampleFrame()); break; case SynthEvent::kEventType_AllNotesOff : group = GetElForGroupID (event->GetGroupID()); group->AllNotesOff(event->GetOffsetSampleFrame()); break; case SynthEvent::kEventType_AllSoundOff : group = GetElForGroupID (event->GetGroupID()); group->AllSoundOff(event->GetOffsetSampleFrame()); break; case SynthEvent::kEventType_ResetAllControllers : group = GetElForGroupID (event->GetGroupID()); group->ResetAllControllers(event->GetOffsetSampleFrame()); break; } mEventQueue.AdvanceReadPtr(); } }
OSStatus AUInstrumentBase::RealTimeStopNote( MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame) { #if DEBUG_PRINT printf("AUInstrumentBase::RealTimeStopNote ch %d id %d\n", inGroupID, inNoteInstanceID); #endif SynthGroupElement *gp = (inGroupID == kMusicNoteEvent_Unused ? GetElForNoteID (inNoteInstanceID) : GetElForGroupID(inGroupID)); if (gp) { gp->NoteOff (inNoteInstanceID, inOffsetSampleFrame); } return noErr; }
SynthGroupElement * AUInstrumentBase::GetElForGroupID (MusicDeviceGroupID inGroupID) { AUScope & groups = Groups(); unsigned int numEls = groups.GetNumberOfElements(); SynthGroupElement* unassignedEl = NULL; for (unsigned int i = 0; i < numEls; ++i) { SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i)); if (el->GroupID() == inGroupID) return el; if (el->GroupID() == SynthGroupElement::kUnassignedGroup) { unassignedEl = el; break; // we fill this up from the start of the group scope vector } } if (unassignedEl) { unassignedEl->SetGroupID(inGroupID); return unassignedEl; } throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement); }
OSStatus AUInstrumentBase::SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame) { if (InRenderThread ()) { SynthGroupElement *group = GetElForGroupID(inGroupID); if (!group) return kAudioUnitErr_InvalidElement; switch (inEventType) { case SynthEvent::kEventType_SustainOn : group->SustainOn(inOffsetSampleFrame); break; case SynthEvent::kEventType_SustainOff : group->SustainOff(inOffsetSampleFrame); break; case SynthEvent::kEventType_SostenutoOn : group->SostenutoOn(inOffsetSampleFrame); break; case SynthEvent::kEventType_SostenutoOff : group->SostenutoOff(inOffsetSampleFrame); break; case SynthEvent::kEventType_AllNotesOff : group->AllNotesOff(inOffsetSampleFrame); mNumActiveNotes = CountActiveNotes(); break; case SynthEvent::kEventType_AllSoundOff : group->AllSoundOff(inOffsetSampleFrame); mNumActiveNotes = CountActiveNotes(); break; case SynthEvent::kEventType_ResetAllControllers : group->ResetAllControllers(inOffsetSampleFrame); break; } } else { SynthEvent *event = mEventQueue.WriteItem(); if (!event) return -1; // queue full event->Set(inEventType, inGroupID, 0, 0, NULL); mEventQueue.AdvanceWritePtr(); } return noErr; }