Re: MusicDevice confusion
Re: MusicDevice confusion
- Subject: Re: MusicDevice confusion
- From: Chris Reed <email@hidden>
- Date: Sat, 22 Mar 2003 13:16:15 -0600
First of all, before going any further you should thoroughly examine
the sample code Apple has provided in /Developer/Examples/CoreAudio.
Most useful are Services/AudioUnitHosting and PlayEffect. These
examples are very, very helpful.
On Saturday, Mar 22, 2003, at 09:12 US/Central, Kenneth Welch wrote:
Hi guys...
My app uses CoreMIDI to talk to external synthesizer hardware. This
much has been up and running for some time now. However a while back,
one user requested support for whatever software synths might be
installed on the host computer as well, and I finally got around to
looking into that the other day. Here's a chunk straight out of the
/Developer/Documentation/CoreAudio/AudioUnits/ section:
ComponentDescription desc;
desc.componentType = kAudioUnitType_MusicDevice;
desc.componentSubType = 0;
desc.componentManufacturer = 0;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
printf("Found %ld Audio Units\n", CountComponents(&desc));
Component comp = FindNextComponent(NULL, &desc);
if (comp == NULL) ExitToShell();
The third-to-last line prints the value 1, which I assume refers to the
standard QuickTime software synth (since that is all I have installed
on my system at the moment).
This would be the Apple DLS Synth. Not quite the QT synth; that is not
directly available via CoreAudio.
I tried to verify this by calling
GetComponentInfo() on comp, but it returns the component name in a
passed argument of type Handle, and I don't know what kind of handle
they mean so I couldn't resolve it into a name. It was also not
possible to access the deviceNameLength and deviceName fields of the
ComponentDescription struct that GetComponentInfo() can optionally
return. Blarg.
The Handle contains the text of the component name.
Here's some code to print the name (bad code, but you get the idea):
Handle name;
char nameBuffer[100];
int length = GetHandleSize(name);
HLock(name);
memcpy(nameBuffer, *name, length);
nameBuffer[length] = 0;
printf("Component name: %s\n", nameBuffer);
Be sure to pass in a handle of size 0 (created with NewHandle) to the
GetComponentInfo() function.
MusicDeviceComponent synth;
OSErr result = OpenAComponent(comp, &synth);
if (result != 0) ExitToShell();
So far so good, I guess. The AudioUnits documenation used an AudioUnit
instead of a MusicDeviceComponent for the variable synth, but they are
both defined as "typedef ComponentInstance" so it should be fine.
Yes, AudioUnit, MusicDeviceComponent, Component, and ComponentInstance
values can all be substituted for each other.
// MusicDevicePrepareInstrument(synth, 0);
// MusicDeviceMIDIEvent(synth, 176, 0, 0, 0);
// MusicDeviceMIDIEvent(synth, 176, 32, 0, 0);
MusicDeviceMIDIEvent(synth, 192, 0, 0, 0);
MusicDeviceMIDIEvent(synth, 144, 60, 127, 0);
I have no idea whether the first line is necessary or not, since it's
listed as part of the "extended" API. The second and third lines
theoretically send MSB and LSB bank select commands of value 0. The
fourth line sends a program select command of value 0, which should be
the piano instrument. And the last line sends a Note On message, pitch
60, full volume. All of these of course are referring to MIDI Channel
1. I tried it both with all the lines active, and with just the last
two active in case the QuickTime software synth uses non-zero bank
values. (With external hardware synths it's easy; the paper instruction
manual tells you what MSB/LSB value pairs identify each bank, heh.)
Unfortunately... nothing happens.
I'm also somewhat confused, in addition to not getting any sound from
the above code, about the timing aspect. The last parameter in those
calls is labeled inOffsetSampleFrame. I don't even know if that *is* a
timing parameter, but if it is I have no idea what it means. I assume
passing a value of zero tells it to do the action "now" just like with
the CoreMIDI routines.
Ideally, you will call the functions that accept an
inBufferOffsetInFrames only for events that will happen in the buffer
that is about to be rendered.
This is determined in two basic ways: 1) you can AudioUnitRender()
yourself, so you know exactly when the buffer is going to be rendered,
2) you can install a render notification callback that is called
optionally before and after a given buffer is rendered. This is useful
when you use a MusicDevice in a graph, and so are not calling
AudioUnitRender() yourself.
Passing a buffer offset of 0 means "start the event immediately".
Take a look at the AUMIDIController API in the AudioToolbox framework
for a way to avoid having to be concerned with buffer offsets and such.
In short, I would like to be able to, first, get an enumeration of all
the installed software synthesizers on the host, which the
CountComponents/FindNextComponent stuff appears to do. Then, second,
use those software synths interchangeably with external hardware-based
ones. My application generates MIDI packets that go out for playback;
this means, ideally, I would need to be able to use MIDISend(), or an
equivalent function with the same nanosecond/millisecond based timing,
going out to a software synth target.
Look at the AudioUnitHosting example. It shows how to do basically
this--construct a simple AUGraph and use an AUMIDIController to route a
MIDI source to a MusicDevice.
It is not clear to me yet whether MusicDevice will be sufficient for
this task. Unfortunately all the sample code I've seen uses AUGraphs
(which I don't really understand, and am not using at all in my
existing CoreMIDI code), and mucking through the list archives hasn't
helped much either (though in a number of unrelated past cases it has,
hehe). So, thanks in advance for any help/suggestions, and apologies
for the relatively-newbie-ish nature of these questions; as always, I
am still learning.
Unless you really way control over every aspect of the audio, which I
doubt you will need because it seems your app seems to be focused on
MIDI, you should use an AUGraph. This lets CoreAudio take care of the
hard work and leaves all the fun stuff up to you :)
Cheers
-chris
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.