16 #include <CoreServices/CoreServices.h>
17 #include <AudioToolbox/AudioToolBox.h>
18 #include <AudioUnit/AudioUnit.h>
21 #define thisTTClass TTAudioUnit
26 OSStatus TTAudioUnitGetInputSamples(
void* inRefCon,
27 AudioUnitRenderActionFlags* ioActionFlags,
28 const AudioTimeStamp* inTimeStamp,
30 UInt32 inNumberFrames,
31 AudioBufferList* ioData);
39 AudioBufferList* mInputBufferList;
40 AudioBufferList* mOutputBufferList;
41 AudioTimeStamp mTimeStamp;
50 mInputBufferList(NULL),
51 mOutputBufferList(NULL),
69 mParameterNames =
new TTHash;
70 mTimeStamp.mSampleTime = 0;
71 mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
84 AudioUnitUninitialize(mAudioUnit);
85 CloseComponent(mAudioUnit);
88 free(mInputBufferList);
89 free(mOutputBufferList);
97 free(mInputBufferList);
98 if (mOutputBufferList)
99 free(mOutputBufferList);
103 mInputBufferList = (AudioBufferList*)malloc(offsetof(AudioBufferList, mBuffers) + (
mMaxNumChannels *
sizeof(AudioBuffer)));
104 mOutputBufferList = (AudioBufferList*)malloc(offsetof(AudioBufferList, mBuffers) + (
mMaxNumChannels *
sizeof(AudioBuffer)));
107 mInputBufferList->mBuffers[channel].mNumberChannels = 1;
108 mInputBufferList->mBuffers[channel].mData = NULL;
109 mInputBufferList->mBuffers[channel].mDataByteSize = 0;
110 mOutputBufferList->mBuffers[channel].mNumberChannels = 1;
111 mOutputBufferList->mBuffers[channel].mData = NULL;
112 mOutputBufferList->mBuffers[channel].mDataByteSize = 0;
122 if (newInputCount != mInputCount) {
123 mInputCount = newInputCount;
134 if (newOutputCount != mOutputCount) {
135 mOutputCount = newOutputCount;
144 ComponentDescription searchDesc;
145 Component comp = NULL;
146 ComponentDescription compDesc;
153 searchDesc.componentType = kAudioUnitType_Effect;
154 searchDesc.componentSubType = 0;
155 searchDesc.componentManufacturer = 0;
156 searchDesc.componentFlags = 0;
157 searchDesc.componentFlagsMask = 0;
159 while (comp = FindNextComponent(comp, &searchDesc)) {
160 compName = NewHandle(0);
161 GetComponentInfo(comp, &compDesc, compName, NULL, NULL);
163 compNameStr = *compName;
164 compNameLen = *compNameStr++;
165 compNameStr[compNameLen] = 0;
166 compNameStr = strchr(compNameStr,
':');
170 pluginNames.
append(
TT(compNameStr));
173 DisposeHandle(compName);
181 ComponentDescription searchDesc;
182 Component comp = NULL;
183 ComponentDescription compDesc;
187 TTSymbol pluginName = newPluginName;
189 AudioStreamBasicDescription audioStreamBasicDescription;
193 AudioUnitUninitialize(mAudioUnit);
194 CloseComponent(mAudioUnit);
198 searchDesc.componentType = kAudioUnitType_Effect;
199 searchDesc.componentSubType = 0;
200 searchDesc.componentManufacturer = 0;
201 searchDesc.componentFlags = 0;
202 searchDesc.componentFlagsMask = 0;
204 while (comp = FindNextComponent(comp, &searchDesc)) {
205 compName = NewHandle(0);
206 GetComponentInfo(comp, &compDesc, compName, NULL, NULL);
208 compNameStr = *compName;
209 compNameLen = *compNameStr++;
210 compNameStr[compNameLen] = 0;
211 compNameStr = strchr(compNameStr,
':');
215 if (!strcmp(compNameStr, pluginName)) {
216 AURenderCallbackStruct callbackStruct;
218 mAudioUnit = OpenComponent(comp);
219 mPlugin = pluginName;
221 stuffParameterNamesIntoHash();
224 DisposeHandle(compName);
227 callbackStruct.inputProc = &TTAudioUnitGetInputSamples;
228 callbackStruct.inputProcRefCon =
this;
229 AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackStruct,
sizeof(AURenderCallbackStruct));
230 AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Global, 0, &
sr,
sizeof(
sr));
234 dataSizeDontCare =
sizeof(audioStreamBasicDescription);
235 result = AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &audioStreamBasicDescription, &dataSizeDontCare);
237 audioStreamBasicDescription.mChannelsPerFrame = mInputCount;
238 result = AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &audioStreamBasicDescription,
sizeof(audioStreamBasicDescription));
240 dataSizeDontCare =
sizeof(audioStreamBasicDescription);
241 result = AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &audioStreamBasicDescription, &dataSizeDontCare);
243 audioStreamBasicDescription.mChannelsPerFrame = mOutputCount;
244 result = AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &audioStreamBasicDescription,
sizeof(audioStreamBasicDescription));
248 AudioUnitInitialize(mAudioUnit);
254 DisposeHandle(compName);
260 void stuffParameterNamesIntoHash()
263 Boolean writable =
false;
264 OSStatus err = noErr;
265 AudioUnitParameterID* parameterArray = NULL;
267 mParameterNames->
clear();
269 err = AudioUnitGetPropertyInfo(mAudioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, &size, &writable);
270 if (err || size == 0)
273 parameterArray = (AudioUnitParameterID*)malloc(size);
274 err = AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, parameterArray, &size);
278 for (UInt32 paramNumber = 0; paramNumber < size/
sizeof(AudioUnitParameterID); paramNumber++) {
279 AudioUnitParameterInfo info;
280 UInt32 infoSize =
sizeof(AudioUnitParameterInfo);
281 char parameterName[256];
283 err = AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameterArray[paramNumber], &info, &infoSize);
285 CFStringGetCString(info.cfNameString, parameterName, 256, kCFStringEncodingUTF8);
286 mParameterNames->
append(
TT(parameterName), paramNumber);
291 free(parameterArray);
297 return mParameterNames->
getKeys(returnedParameterNames);
308 if (nameAndValue.
getSize() != 2) {
309 logError(
"Bad arguments for setParameter()");
313 nameAndValue.
get(0, parameterName);
314 nameAndValue.
get(1, parameterValue);
315 err = mParameterNames->
lookup(parameterName, v);
317 AudioUnitSetParameter(mAudioUnit, v, kAudioUnitScope_Global, 0, parameterValue, 0);
327 long parameterID = -1;
328 Float32 parameterValue = 0.0;
330 err = mParameterNames->
lookup(parameterName, v);
333 AudioUnitGetParameter(mAudioUnit, parameterID, kAudioUnitScope_Global, 0, ¶meterValue);
334 valueOut = parameterValue;
342 CFArrayRef factoryPresets = NULL;
343 UInt32 size =
sizeof(CFArrayRef);
344 OSStatus err = noErr;
347 returnedPresetNames.
clear();
349 err = AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, &factoryPresets, &size);
353 count = CFArrayGetCount(factoryPresets);
354 for (
int i=0; i<count; i++) {
355 const AUPreset* preset = (
const AUPreset*)CFArrayGetValueAtIndex(factoryPresets, i);
356 char presetName[256];
358 CFStringGetCString(preset->presetName, presetName, 256, kCFStringEncodingUTF8);
359 returnedPresetNames.
append(
TT(presetName));
361 CFRelease(factoryPresets);
370 OSStatus err = noErr;
372 presetInfo.presetNumber = presetNumber;
373 err = AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0, &presetInfo,
sizeof(AUPreset));
384 TTUInt16 vs = in.getVectorSizeAsInt();
385 TTUInt16 numInputChannels = in.getNumChannelsAsInt();
386 TTUInt16 numOutputChannels = out.getNumChannelsAsInt();
389 AudioUnitRenderActionFlags ioActionFlags = 0;
392 for (
TTUInt16 channel=0; channel<numInputChannels; channel++) {
395 if (mInputBufferList->mBuffers[channel].mDataByteSize != dataByteSize) {
396 if (mInputBufferList->mBuffers[channel].mDataByteSize)
397 TTFree16(mInputBufferList->mBuffers[channel].mData);
398 mInputBufferList->mBuffers[channel].mData =
TTMalloc16(dataByteSize);
399 mInputBufferList->mBuffers[channel].mDataByteSize = dataByteSize;
402 in.getVector(channel, vs, (
TTFloat32*)mInputBufferList->mBuffers[channel].mData);
404 mOutputBufferList->mBuffers[channel].mDataByteSize =
sizeof(
TTFloat32) * vs;
406 mInputBufferList->mNumberBuffers = numInputChannels;
407 mOutputBufferList->mNumberBuffers = numOutputChannels;
410 AudioUnitRender(mAudioUnit, &ioActionFlags, &mTimeStamp, 0, vs, mOutputBufferList);
413 numOutputChannels = mOutputBufferList->mNumberBuffers;
414 for (
TTUInt16 channel=0; channel<numOutputChannels; channel++) {
415 auOutput = (
TTFloat32*)mOutputBufferList->mBuffers[channel].mData;
419 mTimeStamp.mSampleTime += vs;
428 OSStatus TTAudioUnitGetInputSamples(
void* inRefCon,
429 AudioUnitRenderActionFlags* ioActionFlags,
430 const AudioTimeStamp* inTimeStamp,
432 UInt32 inNumberFrames,
433 AudioBufferList* ioData)
437 for (
TTUInt16 channel=0; channel < ioData->mNumberBuffers; channel++)
438 memcpy(ioData->mBuffers[channel].mData, ttAudioUnit->mInputBufferList->mBuffers[channel].mData,
sizeof(
TTFloat32) * inNumberFrames);
~TTAudioUnit()
Destructor.
std::uint16_t TTUInt16
16 bit unsigned integer
void TTFOUNDATION_EXPORT TTFree16(TTPtr ptr)
Free memory allocated using TTMalloc16().
TTUInt16 getSize() const
DEPRECATED.
TTErr lookup(const TTSymbol key, TTValue &value)
Find the value for the given key.
TTAudioObjectBase is the base class for all audio generating and processing objects in Jamoma DSP...
TTChannelCount mMaxNumChannels
This is the maximum number of channels that can be guaranteed to work.
TTAudioUnit(TTValue &arguments)
Constructor.
TTErr logError(TTImmutableCString fmtstring,...)
Log errors scoped to this object instance.
TTPtr TTFOUNDATION_EXPORT TTMalloc16(size_t numBytes)
Allocate memory from the heap aligned to 16-byte boundaries.
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTErr getKeys(TTValue &hashKeys)
Get an array of all of the keys for the hash table.
AudioUnit mAudioUnit
the actual plugin
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
Maintain a collection of TTValue objects indexed by TTSymbol pointers.
TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
Audio Processing Method.
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
TTErr setVector(const TTChannelCount channel, const TTUInt16 vectorSize, const TTSampleValuePtr newVector)
[doxygenAppendixC_methodExample]
TTHashPtr mParameterNames
parameter names -> parameter ids
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
float TTFloat32
32 bit floating point number
void get(const TTUInt16 index, T &returnedElementValue) const
DEPRECATED.
The TTAudioSignal class represents N vectors of audio samples for M channels.
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
TTErr clear()
Remove all items from the hash table.
A simple container for an array of TTAudioSignal pointers.
void clear()
Clear all values from the vector, leaving with size of 0.
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
std::uint32_t TTUInt32
32 bit unsigned integer
TTSymbol mPlugin
Attribute: the name of the current plugin.
#define addAttributeWithSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom setter...
32-bit unsigned integer, range is 0 through 4,294,967,295.
[doxygenAppendixC_copyExample]
#define TT_AUDIO_CLASS_SETUP(strname, tags, className)
A macro for setting up the class binding to the library in extension classes.
#define addUpdates(updateName)
An 'update' is a message sent to a subclass instance from its parent class.
TTUInt32 sr
Current sample rate being used by this object.