Cinder Forum ARCHIVE
the showUI()'s are really cool! Too bad they require carbon (how many do?), but I guess that is how old the CoreAudioSDK is.Thanks! Very few require Carbon, really. I just felt like I couldn't claim to have GUI support if it didn't support that last 5% or so (and it's always that last 5% or so that you really need :/). Off the top of my head, I believe there's a handful of Native Instruments UIs that still use Carbon (Massive) and the free soundhack ones as well.
the block source files in your samples are broken links - all red.Ah. I have a feeling that's because you cloned the repo directly into the blocks/ folder as Cinder-AudioUnit instead of just AudioUnit? I generated the projects thinking I'd just be calling it "AudioUnit" but figured Cinder-AudioUnit would be more of a descriptive title (e.g. on Github). Bad Idea :(. I've fixed the linkage now, so you can pull it down and it'll hopefully fix it (and it won't matter what you've called the folder).
True, I fear that's showing it's roots as a bunch of code I've written for myself. A proper API probably shouldn't let you make that mistake so I'll have to think about how to handle that. I do want to extend it to do a bit of device selection and management, as there's an issue right now if you try to use the Input unit without having your hardware input device set to 32-bit float at 44100hz (which you can change in AudioMidiSetup.app). If you get a ton of errors and no sound running the AUInput that's almost certainly why.
- Unit's are stored as values in the class, which at first looked scary to me considering the underlining resources, but the way you've done it with a pimpl really works out nicely. Still might be worth noting the gravity of copying an Output unit (only one can exist per device)
- on the topic of devices, any chance you'll do device selection on OS X? If not, kAudioUnitSubType_DefaultOutput should suffice instead of HAL.
What is that sweet looking UI in the bottom right of your screenshot?That's the Apple-supplied Distortion unit (which also functions as a bitcrusher and ring modulator). Fun toy :)
input.inputProc = inputProc;
input.inputProcRefCon = this;
OSStatus result = AudioUnitSetProperty(m_outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &input, sizeof(input));
and for input callbacks I used this -
// configure the callback AURenderCallbackStruct callback; callback.inputProc = inputCallback; callback.inputProcRefCon = this; result = AudioUnitSetProperty(m_inputUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(AURenderCallbackStruct)); ASSERT(!result); Whereas you are using AUGraphSetNodeInputCallback which I'm not using.
// configure the callback
callback.inputProc = inputCallback;
callback.inputProcRefCon = this;
result = AudioUnitSetProperty(m_inputUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(AURenderCallbackStruct));
Whereas you are using AUGraphSetNodeInputCallback which I'm not using.
cd.componentType = kAudioUnitType_MusicDevice;
cd.componentSubType = kAudioUnitSubType_DLSSynth;
If it'd be useful, in the next couple of days I could try hooking a callback to it and see what happens.
Which in layman terms means that a Generator basically "just makes sound" whereas a Music Device takes MIDI input. You can see what all of the Audio Units are if you check out the header <AudioUnit.framework/AUComponent.h>. Aside: the headers in that framework are better documentation than anything you can find through more sane means like Google. Reading AUComponent.h, AudioComponent.h, AudioUnitParameters.h and AudioUnitProperties.h will make you a Core Audio pro in no time :)A generator unit provides audio output but has no audio input. This audio unit type is appropriate for a tone generator. Unlike an instrument unit, a generator unit does not have a control input.
One thing came up, but it may have just been Xcode acting up: for about 10 tries in a row, the app was exc_bad_access'ing at startup. Don't know if it could be because the units are initialized form stack objects.Interesting, could I get a gist of the code / stack trace or an open issue with a code sample? If the case is that you have a handful of units that are being destructed because they went out of scope, the issue may be that there's a data race where an output unit is pulling through units on the render thread while they're being destructed. The quick workaround for that would be to call stop() on the output unit before they all go out of scope.
Is there any particular reason why you didn't go the AUGraph route?My first attempt at this code used AUGraphs, actually. What I started with was an API sketch (unit.connectTo(unit), etc) and worked down from there. This ended up getting unwieldily very quickly though, due to the fact that there's this monolithic chunk of state that needs to get passed around. Also, the AUGraph API is fairly opaque and doesn't really bend well IMO (such that another API can comfortably sit on top of it, especially a C++ one instead of a C one). Things like AUGraph[Open()/Initialize()] working on the entire graph are an example of that. It's not that I think that AUGraphs are a bad idea, just that they're actually fairly complete things and are very "C".