1 /* 2 Copyright (C) 2016 Apple Inc. All Rights Reserved. 3 See LICENSE.txt for this sample’s licensing information 4 5 Abstract: 6 Part of Core Audio AUInstrument Base Classes 7 */ 8 9 #ifndef __AUInstrumentBase__ 10 #define __AUInstrumentBase__ 11 12 #include <vector> 13 #include <stdexcept> 14 #include <AudioUnit/AudioUnit.h> 15 #include <CoreAudio/CoreAudio.h> 16 #include <libkern/OSAtomic.h> 17 #include "MusicDeviceBase.h" 18 #include "LockFreeFIFO.h" 19 #include "SynthEvent.h" 20 #include "SynthNote.h" 21 #include "SynthElement.h" 22 23 //////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 25 typedef LockFreeFIFOWithFree<SynthEvent> SynthEventQueue; 26 27 class AUInstrumentBase : public MusicDeviceBase 28 { 29 public: 30 AUInstrumentBase( 31 AudioComponentInstance inInstance, 32 UInt32 numInputs, 33 UInt32 numOutputs, 34 UInt32 numGroups = 16, 35 UInt32 numParts = 1); 36 virtual ~AUInstrumentBase(); 37 38 virtual OSStatus Initialize(); 39 40 /*! @method Parts */ Parts()41 AUScope & Parts() { return mPartScope; } 42 43 /*! @method GetPart */ GetPart(AudioUnitElement inElement)44 AUElement * GetPart( AudioUnitElement inElement) 45 { 46 return mPartScope.SafeGetElement(inElement); 47 } 48 49 virtual AUScope * GetScopeExtended (AudioUnitScope inScope); 50 51 virtual AUElement * CreateElement( AudioUnitScope inScope, 52 AudioUnitElement inElement); 53 54 virtual void CreateExtendedElements(); 55 56 virtual void Cleanup(); 57 58 virtual OSStatus Reset( AudioUnitScope inScope, 59 AudioUnitElement inElement); 60 61 virtual bool ValidFormat( AudioUnitScope inScope, 62 AudioUnitElement inElement, 63 const CAStreamBasicDescription & inNewFormat); 64 65 virtual bool StreamFormatWritable( AudioUnitScope scope, 66 AudioUnitElement element); 67 CanScheduleParameters()68 virtual bool CanScheduleParameters() const { return false; } 69 70 virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags, 71 const AudioTimeStamp & inTimeStamp, 72 UInt32 inNumberFrames); 73 74 virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument, 75 MusicDeviceGroupID inGroupID, 76 NoteInstanceID * outNoteInstanceID, 77 UInt32 inOffsetSampleFrame, 78 const MusicDeviceNoteParams &inParams); 79 80 virtual OSStatus StopNote( MusicDeviceGroupID inGroupID, 81 NoteInstanceID inNoteInstanceID, 82 UInt32 inOffsetSampleFrame); 83 84 virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup, 85 NoteInstanceID inNoteInstanceID, 86 UInt32 inOffsetSampleFrame, 87 const MusicDeviceNoteParams &inParams); 88 89 virtual OSStatus RealTimeStopNote( MusicDeviceGroupID inGroupID, 90 NoteInstanceID inNoteInstanceID, 91 UInt32 inOffsetSampleFrame); 92 93 virtual OSStatus HandleControlChange( UInt8 inChannel, 94 UInt8 inController, 95 UInt8 inValue, 96 UInt32 inStartFrame); 97 98 virtual OSStatus HandlePitchWheel( UInt8 inChannel, 99 UInt8 inPitch1, 100 UInt8 inPitch2, 101 UInt32 inStartFrame); 102 103 virtual OSStatus HandleChannelPressure( UInt8 inChannel, 104 UInt8 inValue, 105 UInt32 inStartFrame); 106 107 virtual OSStatus HandleProgramChange( UInt8 inChannel, 108 UInt8 inValue); 109 110 virtual OSStatus HandlePolyPressure( UInt8 inChannel, 111 UInt8 inKey, 112 UInt8 inValue, 113 UInt32 inStartFrame); 114 115 virtual OSStatus HandleResetAllControllers( UInt8 inChannel); 116 117 virtual OSStatus HandleAllNotesOff( UInt8 inChannel); 118 119 virtual OSStatus HandleAllSoundOff( UInt8 inChannel); 120 GetNote(UInt32 inIndex)121 SynthNote* GetNote(UInt32 inIndex) 122 { 123 if (!mNotes) 124 throw std::runtime_error("no notes"); 125 return (SynthNote*)((char*)mNotes + inIndex * mNoteSize); 126 } 127 128 SynthNote* GetAFreeNote(UInt32 inFrame); 129 void AddFreeNote(SynthNote* inNote); 130 131 friend class SynthGroupElement; 132 protected: 133 NextNoteID()134 UInt32 NextNoteID() { return OSAtomicIncrement32((int32_t *)&mNoteIDCounter); } 135 136 137 // call SetNotes in your Initialize() method to give the base class your note structures and to set the maximum 138 // number of active notes. inNoteData should be an array of size inMaxActiveNotes. 139 void SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteSize); 140 141 void PerformEvents( const AudioTimeStamp & inTimeStamp); 142 OSStatus SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame); 143 virtual SynthNote* VoiceStealing(UInt32 inFrame, bool inKillIt); MaxActiveNotes()144 UInt32 MaxActiveNotes() const { return mMaxActiveNotes; } NumActiveNotes()145 UInt32 NumActiveNotes() const { return mNumActiveNotes; } IncNumActiveNotes()146 void IncNumActiveNotes() { ++mNumActiveNotes; } DecNumActiveNotes()147 void DecNumActiveNotes() { --mNumActiveNotes; } 148 UInt32 CountActiveNotes(); 149 150 SynthPartElement * GetPartElement (AudioUnitElement inPartElement); 151 152 // this call throws if there's no assigned element for the group ID 153 virtual SynthGroupElement * GetElForGroupID (MusicDeviceGroupID inGroupID); 154 virtual SynthGroupElement * GetElForNoteID (NoteInstanceID inNoteID); 155 156 SInt64 mAbsoluteSampleFrame; 157 158 159 private: 160 161 SInt32 mNoteIDCounter; 162 163 SynthEventQueue mEventQueue; 164 165 UInt32 mNumNotes; 166 UInt32 mNumActiveNotes; 167 UInt32 mMaxActiveNotes; 168 SynthNote* mNotes; 169 SynthNoteList mFreeNotes; 170 UInt32 mNoteSize; 171 172 AUScope mPartScope; 173 const UInt32 mInitNumPartEls; 174 }; 175 176 //////////////////////////////////////////////////////////////////////////////////////////////////////////// 177 178 class AUMonotimbralInstrumentBase : public AUInstrumentBase 179 { 180 public: 181 AUMonotimbralInstrumentBase( 182 AudioComponentInstance inInstance, 183 UInt32 numInputs, 184 UInt32 numOutputs, 185 UInt32 numGroups = 16, 186 UInt32 numParts = 1); 187 188 virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup, 189 NoteInstanceID inNoteInstanceID, 190 UInt32 inOffsetSampleFrame, 191 const MusicDeviceNoteParams &inParams); 192 }; 193 194 //////////////////////////////////////////////////////////////////////////////////////////////////////////// 195 196 // this is a work in progress! The mono-timbral one is finished though! 197 class AUMultitimbralInstrumentBase : public AUInstrumentBase 198 { 199 public: 200 AUMultitimbralInstrumentBase( 201 AudioComponentInstance inInstance, 202 UInt32 numInputs, 203 UInt32 numOutputs, 204 UInt32 numGroups, 205 UInt32 numParts); 206 207 virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID, 208 AudioUnitScope inScope, 209 AudioUnitElement inElement, 210 UInt32 & outDataSize, 211 Boolean & outWritable); 212 213 virtual OSStatus GetProperty( AudioUnitPropertyID inID, 214 AudioUnitScope inScope, 215 AudioUnitElement inElement, 216 void * outData); 217 218 virtual OSStatus SetProperty( AudioUnitPropertyID inID, 219 AudioUnitScope inScope, 220 AudioUnitElement inElement, 221 const void * inData, 222 UInt32 inDataSize); 223 224 private: 225 226 }; 227 228 //////////////////////////////////////////////////////////////////////////////////////////////////////////// 229 230 #endif 231 232