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 AUBase Classes
7 */
8
9 #include "MusicDeviceBase.h"
10
11 // compatibility with older OS SDK releases
12 typedef OSStatus
13 (*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
14 UInt32 inStatus,
15 UInt32 inData1,
16 UInt32 inData2,
17 UInt32 inOffsetSampleFrame);
18
19 typedef OSStatus
20 (*TEMP_MusicDeviceStartNoteProc)( void * inComponentStorage,
21 MusicDeviceInstrumentID inInstrument,
22 MusicDeviceGroupID inGroupID,
23 NoteInstanceID * outNoteInstanceID,
24 UInt32 inOffsetSampleFrame,
25 const MusicDeviceNoteParams * inParams);
26
27 typedef OSStatus
28 (*TEMP_MusicDeviceStopNoteProc)(void * inComponentStorage,
29 MusicDeviceGroupID inGroupID,
30 NoteInstanceID inNoteInstanceID,
31 UInt32 inOffsetSampleFrame);
32
33 #if !CA_USE_AUDIO_PLUGIN_ONLY
34
35 static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
36 UInt32 inStatus,
37 UInt32 inData1,
38 UInt32 inData2,
39 UInt32 inOffsetSampleFrame);
40
41 static OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
42 MusicDeviceInstrumentID inInstrument,
43 MusicDeviceGroupID inGroupID,
44 NoteInstanceID * outNoteInstanceID,
45 UInt32 inOffsetSampleFrame,
46 const MusicDeviceNoteParams * inParams);
47
48 static OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
49 MusicDeviceGroupID inGroupID,
50 NoteInstanceID inNoteInstanceID,
51 UInt32 inOffsetSampleFrame);
52
53 #endif
54
MusicDeviceBase(AudioComponentInstance inInstance,UInt32 numInputs,UInt32 numOutputs,UInt32 numGroups)55 MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
56 UInt32 numInputs,
57 UInt32 numOutputs,
58 UInt32 numGroups)
59 : AUBase(inInstance, numInputs, numOutputs, numGroups),
60 AUMIDIBase(this)
61 {
62 }
63
GetPropertyInfo(AudioUnitPropertyID inID,AudioUnitScope inScope,AudioUnitElement inElement,UInt32 & outDataSize,Boolean & outWritable)64 OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
65 AudioUnitScope inScope,
66 AudioUnitElement inElement,
67 UInt32 & outDataSize,
68 Boolean & outWritable)
69 {
70 OSStatus result;
71
72 switch (inID)
73 {
74 #if !TARGET_OS_IPHONE
75 case kMusicDeviceProperty_InstrumentCount:
76 if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
77 outDataSize = sizeof(UInt32);
78 outWritable = false;
79 result = noErr;
80 break;
81 #endif
82 default:
83 result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
84
85 if (result == kAudioUnitErr_InvalidProperty)
86 result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
87 break;
88 }
89 return result;
90 }
91
GetProperty(AudioUnitPropertyID inID,AudioUnitScope inScope,AudioUnitElement inElement,void * outData)92 OSStatus MusicDeviceBase::GetProperty( AudioUnitPropertyID inID,
93 AudioUnitScope inScope,
94 AudioUnitElement inElement,
95 void * outData)
96 {
97 OSStatus result;
98
99 switch (inID)
100 {
101 #if !CA_USE_AUDIO_PLUGIN_ONLY
102 case kAudioUnitProperty_FastDispatch:
103 if (!IsCMgrObject()) return kAudioUnitErr_InvalidProperty;
104 if (inElement == kMusicDeviceMIDIEventSelect) {
105 *(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
106 return noErr;
107 }
108 else if (inElement == kMusicDeviceStartNoteSelect) {
109 *(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
110 return noErr;
111 }
112 else if (inElement == kMusicDeviceStopNoteSelect) {
113 *(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
114 return noErr;
115 }
116 return kAudioUnitErr_InvalidElement;
117 #endif
118
119 #if !TARGET_OS_IPHONE
120 case kMusicDeviceProperty_InstrumentCount:
121 if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
122 return GetInstrumentCount (*(UInt32*)outData);
123 #endif
124 default:
125 result = AUBase::GetProperty (inID, inScope, inElement, outData);
126
127 if (result == kAudioUnitErr_InvalidProperty)
128 result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
129 }
130
131 return result;
132 }
133
134
SetProperty(AudioUnitPropertyID inID,AudioUnitScope inScope,AudioUnitElement inElement,const void * inData,UInt32 inDataSize)135 OSStatus MusicDeviceBase::SetProperty( AudioUnitPropertyID inID,
136 AudioUnitScope inScope,
137 AudioUnitElement inElement,
138 const void * inData,
139 UInt32 inDataSize)
140
141 {
142
143 OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
144
145 if (result == kAudioUnitErr_InvalidProperty)
146 result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
147
148 return result;
149 }
150
151 // For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
152 // then this call should return an instrument count of zero and noErr
GetInstrumentCount(UInt32 & outInstCount) const153 OSStatus MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
154 {
155 outInstCount = 0;
156 return noErr;
157 }
158
HandleNoteOn(UInt8 inChannel,UInt8 inNoteNumber,UInt8 inVelocity,UInt32 inStartFrame)159 OSStatus MusicDeviceBase::HandleNoteOn( UInt8 inChannel,
160 UInt8 inNoteNumber,
161 UInt8 inVelocity,
162 UInt32 inStartFrame)
163 {
164 MusicDeviceNoteParams params;
165 params.argCount = 2;
166 params.mPitch = inNoteNumber;
167 params.mVelocity = inVelocity;
168 return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
169 }
170
HandleNoteOff(UInt8 inChannel,UInt8 inNoteNumber,UInt8 inVelocity,UInt32 inStartFrame)171 OSStatus MusicDeviceBase::HandleNoteOff( UInt8 inChannel,
172 UInt8 inNoteNumber,
173 UInt8 inVelocity,
174 UInt32 inStartFrame)
175 {
176 return StopNote (inChannel, inNoteNumber, inStartFrame);
177 }
178
179 OSStatus
HandleStartNoteMessage(MusicDeviceInstrumentID inInstrument,MusicDeviceGroupID inGroupID,NoteInstanceID * outNoteInstanceID,UInt32 inOffsetSampleFrame,const MusicDeviceNoteParams * inParams)180 MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument,
181 MusicDeviceGroupID inGroupID,
182 NoteInstanceID * outNoteInstanceID,
183 UInt32 inOffsetSampleFrame,
184 const MusicDeviceNoteParams * inParams)
185 {
186 if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
187
188 if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
189
190 return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
191 }
192
193 #if TARGET_OS_MAC
194 #if __LP64__
195 // comp instance, parameters in forward order
196 #define PARAM(_typ, _name, _index, _nparams) \
197 _typ _name = *(_typ *)¶ms->params[_index + 1];
198 #else
199 // parameters in reverse order, then comp instance
200 #define PARAM(_typ, _name, _index, _nparams) \
201 _typ _name = *(_typ *)¶ms->params[_nparams - 1 - _index];
202 #endif
203 #elif TARGET_OS_WIN32
204 // (no comp instance), parameters in forward order
205 #define PARAM(_typ, _name, _index, _nparams) \
206 _typ _name = *(_typ *)¶ms->params[_index];
207 #endif
208
209 #if !CA_USE_AUDIO_PLUGIN_ONLY
ComponentEntryDispatch(ComponentParameters * params,MusicDeviceBase * This)210 OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
211 MusicDeviceBase * This)
212 {
213 if (This == NULL) return kAudio_ParamError;
214
215 OSStatus result;
216
217 switch (params->what) {
218 case kMusicDeviceMIDIEventSelect:
219 case kMusicDeviceSysExSelect:
220 {
221 result = AUMIDIBase::ComponentEntryDispatch (params, This);
222 }
223 break;
224 case kMusicDevicePrepareInstrumentSelect:
225 {
226 PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
227 result = This->PrepareInstrument(inInstrument);
228 }
229 break;
230 case kMusicDeviceReleaseInstrumentSelect:
231 {
232 PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
233 result = This->ReleaseInstrument(inInstrument);
234 }
235 break;
236 case kMusicDeviceStartNoteSelect:
237 {
238 PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
239 PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
240 PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
241 PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
242 PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
243 result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
244 }
245 break;
246 case kMusicDeviceStopNoteSelect:
247 {
248 PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
249 PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
250 PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
251 result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
252 }
253 break;
254
255 default:
256 result = AUBase::ComponentEntryDispatch(params, This);
257 break;
258 }
259
260 return result;
261 }
262 #endif
263
264 #if !CA_USE_AUDIO_PLUGIN_ONLY
265
266 // fast dispatch
MusicDeviceBaseMIDIEvent(void * inComponentStorage,UInt32 inStatus,UInt32 inData1,UInt32 inData2,UInt32 inOffsetSampleFrame)267 static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
268 UInt32 inStatus,
269 UInt32 inData1,
270 UInt32 inData2,
271 UInt32 inOffsetSampleFrame)
272 {
273 OSStatus result = noErr;
274 try {
275 MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
276 if (This == NULL) return kAudio_ParamError;
277 result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
278 }
279 COMPONENT_CATCH
280 return result;
281 }
282
MusicDeviceBaseStartNote(void * inComponentStorage,MusicDeviceInstrumentID inInstrument,MusicDeviceGroupID inGroupID,NoteInstanceID * outNoteInstanceID,UInt32 inOffsetSampleFrame,const MusicDeviceNoteParams * inParams)283 OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
284 MusicDeviceInstrumentID inInstrument,
285 MusicDeviceGroupID inGroupID,
286 NoteInstanceID * outNoteInstanceID,
287 UInt32 inOffsetSampleFrame,
288 const MusicDeviceNoteParams * inParams)
289 {
290 OSStatus result = noErr;
291 try {
292 if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
293 MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
294 if (This == NULL) return kAudio_ParamError;
295 result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
296 }
297 COMPONENT_CATCH
298 return result;
299 }
300
MusicDeviceBaseStopNote(void * inComponentStorage,MusicDeviceGroupID inGroupID,NoteInstanceID inNoteInstanceID,UInt32 inOffsetSampleFrame)301 OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
302 MusicDeviceGroupID inGroupID,
303 NoteInstanceID inNoteInstanceID,
304 UInt32 inOffsetSampleFrame)
305 {
306 OSStatus result = noErr;
307 try {
308 MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
309 if (This == NULL) return kAudio_ParamError;
310 result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
311 }
312 COMPONENT_CATCH
313 return result;
314 }
315
316 #endif
317