41 #include "AUInstrumentBase.h"
45 #define DEBUG_PRINT_RENDER 0
50 const UInt32 kEventQueueSize = 1024;
52 AUInstrumentBase::AUInstrumentBase(
53 ComponentInstance inInstance,
58 : MusicDeviceBase(inInstance, numInputs, numOutputs, numGroups, numParts),
59 mAbsoluteSampleFrame(0),
60 mEventQueue(kEventQueueSize),
68 printf(
"new AUInstrumentBase\n");
70 mFreeNotes.mState = kNoteState_Free;
74 AUInstrumentBase::~AUInstrumentBase()
77 printf(
"delete AUInstrumentBase\n");
81 AUElement* AUInstrumentBase::CreateElement( AudioUnitScope scope,
82 AudioUnitElement element)
85 printf(
"AUInstrumentBase::CreateElement %d %d\n", scope, element);
89 case kAudioUnitScope_Group :
90 return new SynthGroupElement(
this, element);
91 case kAudioUnitScope_Part :
92 return new SynthPartElement(
this, element);
94 return AUBase::CreateElement(scope, element);
99 void AUInstrumentBase::SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteDataSize)
102 printf(
"AUInstrumentBase::SetNotes %d %d %08X %d\n", inNumNotes, inMaxActiveNotes, inNotes, inNoteDataSize);
104 mNumNotes = inNumNotes;
105 mMaxActiveNotes = inMaxActiveNotes;
106 mNoteSize = inNoteDataSize;
109 for (UInt32 i=0; i<mNumNotes; ++i)
111 SynthNote *note = GetNote(i);
113 mFreeNotes.AddNote(note);
117 UInt32 AUInstrumentBase::CountActiveNotes()
121 for (UInt32 i=0; i<mNumNotes; ++i)
123 SynthNote *note = GetNote(i);
124 if (note->mState <= kNoteState_Released)
130 void AUInstrumentBase::AddFreeNote(SynthNote* inNote)
132 if (inNote->mState != kNoteState_FastReleased)
135 printf(
"AUInstrumentBase::AddFreeNote mNumActiveNotes %lu\n", mNumActiveNotes);
137 mFreeNotes.AddNote(inNote);
140 OSStatus AUInstrumentBase::Initialize()
156 mNoteIDCounter = 128;
157 mAbsoluteSampleFrame = 0;
161 void AUInstrumentBase::Cleanup()
166 OSStatus AUInstrumentBase::Reset( AudioUnitScope inScope,
167 AudioUnitElement inElement)
170 printf(
"AUInstrumentBase::Reset\n");
172 if (inScope == kAudioUnitScope_Global)
176 for (UInt32 i=0; i<mNumNotes; ++i)
178 SynthNote *note = GetNote(i);
179 if (note->IsSounding())
182 mFreeNotes.AddNote(note);
185 mAbsoluteSampleFrame = 0;
188 UInt32 numGroups = Groups().GetNumberOfElements();
189 for (UInt32 j = 0; j < numGroups; ++j)
191 SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
195 return MusicDeviceBase::Reset(inScope, inElement);
198 void AUInstrumentBase::PerformEvents(
const AudioTimeStamp& inTimeStamp)
200 #if DEBUG_PRINT_RENDER
201 printf(
"AUInstrumentBase::PerformEvents\n");
204 SynthGroupElement *group;
206 while ((event = mEventQueue.ReadItem()) != NULL)
208 #if DEBUG_PRINT_RENDER
209 printf(
"event %08X %d\n", event, event->GetEventType());
211 switch(event->GetEventType())
213 case SynthEvent::kEventType_NoteOn :
214 RealTimeStartNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(),
215 event->GetOffsetSampleFrame(), *
event->GetParams());
217 case SynthEvent::kEventType_NoteOff :
218 RealTimeStopNote(event->GetGroupID(),
event->GetNoteID(),
219 event->GetOffsetSampleFrame());
221 case SynthEvent::kEventType_SustainOn :
222 group = GetElForGroupID (event->GetGroupID());
223 group->SustainOn(event->GetOffsetSampleFrame());
225 case SynthEvent::kEventType_SustainOff :
226 group = GetElForGroupID (event->GetGroupID());
227 group->SustainOff(event->GetOffsetSampleFrame());
229 case SynthEvent::kEventType_SostenutoOn :
230 group = GetElForGroupID (event->GetGroupID());
231 group->SostenutoOn(event->GetOffsetSampleFrame());
233 case SynthEvent::kEventType_SostenutoOff :
234 group = GetElForGroupID (event->GetGroupID());
235 group->SostenutoOff(event->GetOffsetSampleFrame());
237 case SynthEvent::kEventType_AllNotesOff :
238 group = GetElForGroupID (event->GetGroupID());
239 group->AllNotesOff(event->GetOffsetSampleFrame());
241 case SynthEvent::kEventType_AllSoundOff :
242 group = GetElForGroupID (event->GetGroupID());
243 group->AllSoundOff(event->GetOffsetSampleFrame());
245 case SynthEvent::kEventType_ResetAllControllers :
246 group = GetElForGroupID (event->GetGroupID());
247 group->ResetAllControllers(event->GetOffsetSampleFrame());
251 mEventQueue.AdvanceReadPtr();
256 OSStatus AUInstrumentBase::Render( AudioUnitRenderActionFlags & ioActionFlags,
257 const AudioTimeStamp & inTimeStamp,
258 UInt32 inNumberFrames)
260 PerformEvents(inTimeStamp);
262 UInt32 numOutputs = Outputs().GetNumberOfElements();
263 for (UInt32 j = 0; j < numOutputs; ++j)
265 AudioBufferList& bufferList = GetOutput(j)->GetBufferList();
266 for (UInt32 k = 0; k < bufferList.mNumberBuffers; ++k)
268 memset(bufferList.mBuffers[k].mData, 0, bufferList.mBuffers[k].mDataByteSize);
272 UInt32 numGroups = Groups().GetNumberOfElements();
273 for (UInt32 j = 0; j < numGroups; ++j)
275 SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
276 OSStatus err = group->Render(inNumberFrames);
279 mAbsoluteSampleFrame += inNumberFrames;
287 bool AUInstrumentBase::ValidFormat( AudioUnitScope inScope,
288 AudioUnitElement inElement,
289 const CAStreamBasicDescription & inNewFormat)
292 if (SupportedNumChannels (NULL))
293 return MusicDeviceBase::ValidFormat(inScope, inElement, inNewFormat);
295 bool isGood = MusicDeviceBase::ValidFormat (inScope, inElement, inNewFormat);
296 if (!isGood)
return false;
300 AUIOElement *el = GetIOElement (inScope, inElement);
301 return (el->GetStreamFormat().NumberChannels() == inNewFormat.NumberChannels());
305 bool AUInstrumentBase::StreamFormatWritable( AudioUnitScope scope,
306 AudioUnitElement element)
308 return IsInitialized() ?
false :
true;
311 OSStatus AUInstrumentBase::RealTimeStartNote( SynthGroupElement *inGroup,
312 NoteInstanceID inNoteInstanceID,
313 UInt32 inOffsetSampleFrame,
314 const MusicDeviceNoteParams &inParams)
319 SynthGroupElement * AUInstrumentBase::GetElForGroupID (MusicDeviceGroupID inGroupID)
321 AUScope & groups = Groups();
322 unsigned int numEls = groups.GetNumberOfElements();
323 SynthGroupElement* unassignedEl = NULL;
325 for (
unsigned int i = 0; i < numEls; ++i) {
326 SynthGroupElement* el =
reinterpret_cast<SynthGroupElement*
>(groups.GetElement(i));
327 if (el->GroupID() == inGroupID)
329 if (el->GroupID() == SynthGroupElement::kUnassignedGroup) {
335 unassignedEl->SetGroupID(inGroupID);
338 throw static_cast<OSStatus
>(kAudioUnitErr_InvalidElement);
341 OSStatus AUInstrumentBase::RealTimeStopNote(
342 MusicDeviceGroupID inGroupID,
343 NoteInstanceID inNoteInstanceID,
344 UInt32 inOffsetSampleFrame)
347 printf(
"AUInstrumentBase::RealTimeStopNote %d %d\n", inGroupID, inNoteInstanceID);
350 SynthGroupElement *gp = (inGroupID == kMusicNoteEvent_Unused
351 ? GetElForNoteID (inNoteInstanceID)
352 : GetElForGroupID(inGroupID));
354 gp->NoteOff (inNoteInstanceID, inOffsetSampleFrame);
359 SynthGroupElement * AUInstrumentBase::GetElForNoteID (NoteInstanceID inNoteID)
362 printf(
"GetElForNoteID id %d\n", (
int)inNoteID);
364 if (!mNotes)
throw std::runtime_error(
"no notes");
366 for (
unsigned int i = 0; i < mNumNotes; ++i) {
367 if (inNoteID == mNotes[i].GetNoteID()) {
368 return mNotes[i].GetGroup();
371 throw static_cast<OSStatus
>(kAudioUnitErr_InvalidElement);
374 OSStatus AUInstrumentBase::StartNote( MusicDeviceInstrumentID inInstrument,
375 MusicDeviceGroupID inGroupID,
376 NoteInstanceID * outNoteInstanceID,
377 UInt32 inOffsetSampleFrame,
378 const MusicDeviceNoteParams &inParams)
381 printf(
"AUInstrumentBase::StartNote %d\n", inGroupID);
383 OSStatus err = noErr;
385 NoteInstanceID noteID;
386 if (outNoteInstanceID) {
387 noteID = NextNoteID();
388 *outNoteInstanceID = noteID;
390 noteID = (UInt32)inParams.mPitch;
392 if (InRenderThread ())
394 err = RealTimeStartNote(
395 GetElForGroupID(inGroupID),
402 SynthEvent *
event = mEventQueue.WriteItem();
403 if (!event)
return -1;
406 SynthEvent::kEventType_NoteOn,
413 mEventQueue.AdvanceWritePtr();
418 OSStatus AUInstrumentBase::StopNote( MusicDeviceGroupID inGroupID,
419 NoteInstanceID inNoteInstanceID,
420 UInt32 inOffsetSampleFrame)
423 printf(
"AUInstrumentBase::StopNote %d %d\n", inGroupID, inNoteInstanceID);
425 OSStatus err = noErr;
427 if (InRenderThread ())
429 err = RealTimeStopNote(
432 inOffsetSampleFrame);
436 SynthEvent *
event = mEventQueue.WriteItem();
437 if (!event)
return -1;
440 SynthEvent::kEventType_NoteOff,
447 mEventQueue.AdvanceWritePtr();
452 OSStatus AUInstrumentBase::SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame)
455 if (InRenderThread ())
457 SynthGroupElement *group = GetElForGroupID(inGroupID);
460 case SynthEvent::kEventType_SustainOn :
461 group->SustainOn(inOffsetSampleFrame);
463 case SynthEvent::kEventType_SustainOff :
464 group->SustainOff(inOffsetSampleFrame);
466 case SynthEvent::kEventType_SostenutoOn :
467 group->SostenutoOn(inOffsetSampleFrame);
469 case SynthEvent::kEventType_SostenutoOff :
470 group->SostenutoOff(inOffsetSampleFrame);
472 case SynthEvent::kEventType_AllNotesOff :
473 group->AllNotesOff(inOffsetSampleFrame);
474 mNumActiveNotes = CountActiveNotes();
476 case SynthEvent::kEventType_AllSoundOff :
477 group->AllSoundOff(inOffsetSampleFrame);
478 mNumActiveNotes = CountActiveNotes();
480 case SynthEvent::kEventType_ResetAllControllers :
481 group->ResetAllControllers(inOffsetSampleFrame);
487 SynthEvent *
event = mEventQueue.WriteItem();
488 if (!event)
return -1;
490 event->Set(inEventType, inGroupID, 0, 0, NULL);
492 mEventQueue.AdvanceWritePtr();
497 OSStatus AUInstrumentBase::HandleControlChange( UInt8 inChannel,
502 GetControls(inChannel)->mControls[inController] = inValue;
503 switch (inController)
505 case kMidiController_Sustain :
507 SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOn, inStartFrame);
509 SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOff, inStartFrame);
511 case kMidiController_Sostenuto :
513 SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOn, inStartFrame);
515 SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOff, inStartFrame);
521 OSStatus AUInstrumentBase::HandlePitchWheel( UInt8 inChannel,
526 MidiControls* controls = GetControls(inChannel);
527 controls->mPitchBend = (inPitch2 << 7) | inPitch1;
528 controls->mFPitchBend = (float)((SInt16)controls->mPitchBend - 8192) / 8192.;
533 OSStatus AUInstrumentBase::HandleChannelPressure(UInt8 inChannel,
537 GetControls(inChannel)->mMonoPressure = inValue;
542 OSStatus AUInstrumentBase::HandleProgramChange( UInt8 inChannel,
545 GetControls(inChannel)->mMonoPressure = inValue;
550 OSStatus AUInstrumentBase::HandlePolyPressure( UInt8 inChannel,
555 GetControls(inChannel)->mPolyPressure[inKey] = inValue;
560 OSStatus AUInstrumentBase::HandleResetAllControllers( UInt8 inChannel)
562 SendPedalEvent (inChannel, SynthEvent::kEventType_ResetAllControllers, 0);
567 OSStatus AUInstrumentBase::HandleAllNotesOff( UInt8 inChannel)
569 SendPedalEvent (inChannel, SynthEvent::kEventType_AllNotesOff, 0);
574 OSStatus AUInstrumentBase::HandleAllSoundOff( UInt8 inChannel)
576 SendPedalEvent (inChannel, SynthEvent::kEventType_AllSoundOff, 0);
580 SynthNote* AUInstrumentBase::GetAFreeNote(UInt32 inFrame)
583 printf(
"GetAFreeNote size %d\n", mFreeNotes.Length());
585 SynthNote *note = mFreeNotes.mHead;
588 mFreeNotes.RemoveNote(note);
592 return VoiceStealing(inFrame,
true);
595 SynthNote* AUInstrumentBase::VoiceStealing(UInt32 inFrame,
bool inKillIt)
599 printf(
"enter voice stealing\n");
602 UInt32 startState = inKillIt ? kNoteState_FastReleased : kNoteState_Released;
603 for (UInt32 i = startState; i <= startState; --i)
606 printf(
" steal state %d\n", i);
608 UInt32 numGroups = Groups().GetNumberOfElements();
609 for (UInt32 j = 0; j < numGroups; ++j)
611 SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
613 printf(
" steal group %d size %d\n", j, group->mNoteList[i].Length());
615 if (group->mNoteList[i].NotEmpty()) {
617 printf(
"not empty %d %d\n", i, j);
619 SynthNote *note = group->mNoteList[i].FindMostQuietNote();
622 printf(
"--=== KILL ===---\n");
624 note->mRelativeKillFrame = inFrame;
626 group->mNoteList[i].RemoveNote(note);
627 if (i != kNoteState_FastReleased)
632 printf(
"--=== FAST RELEASE ===---\n");
634 group->mNoteList[i].RemoveNote(note);
635 note->FastRelease(inFrame);
636 group->mNoteList[kNoteState_FastReleased].AddNote(note);
644 printf(
"no notes to steal????\n");
652 AUMonotimbralInstrumentBase::AUMonotimbralInstrumentBase(
653 ComponentInstance inInstance,
658 : AUInstrumentBase(inInstance, numInputs, numOutputs, numGroups, numParts)
662 OSStatus AUMonotimbralInstrumentBase::RealTimeStartNote(
663 SynthGroupElement *inGroup,
664 NoteInstanceID inNoteInstanceID,
665 UInt32 inOffsetSampleFrame,
666 const MusicDeviceNoteParams &inParams)
668 #if DEBUG_PRINT_RENDER
669 printf(
"AUMonotimbralInstrumentBase::RealTimeStartNote %d\n", inNoteInstanceID);
672 if (NumActiveNotes() + 1 > MaxActiveNotes())
674 VoiceStealing(inOffsetSampleFrame,
false);
676 SynthNote *note = GetAFreeNote(inOffsetSampleFrame);
677 if (!note)
return -1;
680 note->AttackNote(NULL, inGroup, inNoteInstanceID,
681 mAbsoluteSampleFrame + inOffsetSampleFrame, inOffsetSampleFrame, inParams);
683 inGroup->mNoteList[kNoteState_Attacked].AddNote(note);
690 OSStatus AUMultitimbralInstrumentBase::GetPropertyInfo(AudioUnitPropertyID inID,
691 AudioUnitScope inScope,
692 AudioUnitElement inElement,
693 UInt32 & outDataSize,
694 Boolean & outWritable)
696 OSStatus result = noErr;
700 case kMusicDeviceProperty_PartGroup:
701 if (inScope != kAudioUnitScope_Part)
return kAudioUnitErr_InvalidScope;
702 outDataSize =
sizeof(UInt32);
707 result = AUInstrumentBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
712 OSStatus AUMultitimbralInstrumentBase::GetProperty( AudioUnitPropertyID inID,
713 AudioUnitScope inScope,
714 AudioUnitElement inElement,
717 OSStatus result = noErr;
721 case kMusicDeviceProperty_PartGroup:
722 if (inScope != kAudioUnitScope_Group)
return kAudioUnitErr_InvalidScope;
728 result = AUInstrumentBase::GetProperty (inID, inScope, inElement, outData);
736 OSStatus AUMultitimbralInstrumentBase::SetProperty( AudioUnitPropertyID inID,
737 AudioUnitScope inScope,
738 AudioUnitElement inElement,
742 OSStatus result = noErr;
746 case kMusicDeviceProperty_PartGroup:
747 if (inScope != kAudioUnitScope_Group)
return kAudioUnitErr_InvalidScope;
753 result = MusicDeviceBase::SetProperty (inID, inScope, inElement, inData, inDataSize);