• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: How to route channels from SynthUnit to a multi-channel device? <solved>
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to route channels from SynthUnit to a multi-channel device? <solved>


  • Subject: Re: How to route channels from SynthUnit to a multi-channel device? <solved>
  • From: michael markert <email@hidden>
  • Date: Thu, 22 Sep 2005 15:49:32 +0200

Hello to all,

first of all: thanks for your answers.

After struggeling for a (much too long) time with the matrixMixer, I wanted to post my current code-snippets to this list, because there is really not much documentation available...

I use the MatrixMixer to route my synth-output channels to different device-channels.
The main difference to the MatrixMixerTest.xcodeproj is the fact, that I don't use any Line-In-Audiostream (like all the examples I could find) but rather a Synth/EffectNode.
Therefore all the render-calls in the MatrixMixer example are unnecessarily for this case.


Synth Node
         ||
         ||
Effect Node
         ||
MatrixMixer
    ||   ||   ||
    ||   ||   ||
    ||   ||   ||
Output Node (CH 0/1 -OR- CH 2/3 -OR- CH 4/5)


The first thing I struggled with, was to use the Public Utilities in CA-SDK:


I tried the MatrixMixerExample from the CoreAudioSDK, but it needs "CAStreamBasicDescription.h" ...and whenever I add these two files to my project, it doesn't compile anymore with a bunch of errors:

Doug Wyatt pointed me to the right direction: Changing the fileType of my controller-source to "sourcecode.cpp.objcpp" (in the info- panel) or renaming the controllerObject to *.mm (instead of *.m) solved this problem.



The next thing I struggled upon were the volume-values.
I still don't really understand why I have to use an Float32 with an integer "1". All other values (like "1.0" or "0.8" result in a distorted audioSignal. But nevertheless, here is the code which is behaving like expected. I am no super-programmer, so if there are errors (and I'm sure there are plenty :) – feel free to emend!
This is really just to provide some more infos on this topic and maybe help someone struggeling like me finding the solution a bit faster...





@interface: { AudioDeviceID deviceID; UInt32 outChannels; int outChannelPair;

AUGraph graph;
AUNode synthNode, effectNode, mixerNode, outputNode;


    ComponentDescription    selectedEffect;
    ComponentDescription    selectedSynth;
}



const Float64 kGraphSampleRate = 44100.;


@implementation:

-(void)setupAudio {
    OSStatus result = noErr;
    UInt32 size = sizeof(UInt32);

NewAUGraph(&graph);
// select default synth and effect
// leaving some things out here... setup synth & effect component...


// synth node
AUGraphNewNode(graph, [self synthComponentDescription], 0, NULL, &synthNode);
// effect node
AUGraphNewNode(graph, [self effectComponentDescription], 0, NULL, &effectNode);
ComponentDescription desc;
// mixer node
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentType = kAudioUnitType_Mixer;
desc.componentSubType = kAudioUnitSubType_MatrixMixer;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
AUGraphNewNode(graph, &desc, 0, NULL, &mixerNode);
// output node
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
AUGraphNewNode(graph, &desc, 0, NULL, &outputNode);


    // open graph
    AUGraphOpen(graph);

// get outputUnit
AudioUnit outputUnit;
AUGraphGetNodeInfo(graph, outputNode, NULL, NULL, NULL, &outputUnit);
// get current output device id (deviceID)
size = sizeof(deviceID);
AudioUnitGetProperty(outputUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Output,
1, &deviceID, &size);
// get available output channels (UInt32 outChannels)
result = AudioDeviceGetPropertyInfo(deviceID, 0, false,
kAudioDevicePropertyPreferredChannelLayout,
&size, NULL);
if(result != noErr) {
outChannels = 2; // default to first two busses
} else {
AudioChannelLayout *layout = NULL;
layout = (AudioChannelLayout *)calloc(1, size);
if(layout != NULL) {
result = AudioDeviceGetProperty(deviceID, 0, false,
kAudioDevicePropertyPreferredChannelLayout,
&size, layout);
if(layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
// no channel layout tag is returned, so iterate through chDescriptions
if(layout->mNumberChannelDescriptions == 2) {
outChannels = 2;
} else {
outChannels = 0;
UInt32 i;
for(i=0; i<layout->mNumberChannelDescriptions; i+ +) {
if(layout->mChannelDescriptions [i].mChannelLabel != kAudioChannelLabel_Unknown) {
outChannels ++;
}
}
}
} else {
switch (layout->mChannelLayoutTag) {
case kAudioChannelLayoutTag_AudioUnit_5_0:
case kAudioChannelLayoutTag_AudioUnit_5_1:
case kAudioChannelLayoutTag_AudioUnit_6:
outChannels = 5;
break;
case kAudioChannelLayoutTag_AudioUnit_4:
outChannels = 4;
default:
outChannels = 2;
}
}
free(layout);
}
}
if(debugMode) NSLog(@"found %i channels", outChannels);


    // setup MatrixMixer
    AudioUnit mixerUnit;
    AUGraphGetNodeInfo(graph, mixerNode, NULL, NULL, NULL, &mixerUnit);
    CAStreamBasicDescription streamDesc;

    // set BusCount
    UInt32 inChannels = 2;
    UInt32 numbusses = inChannels / 2;
    result = AudioUnitSetProperty(mixerUnit,
                                  kAudioUnitProperty_BusCount,
                                  kAudioUnitScope_Input,
                                  0, &numbusses, sizeof(UInt32));
    numbusses = outChannels / 2;
    result = AudioUnitSetProperty(mixerUnit,
                                  kAudioUnitProperty_BusCount,
                                  kAudioUnitScope_Output,
                                  0, &numbusses, sizeof(UInt32));

    // set input stream format
    size = sizeof(streamDesc);
    result = AudioUnitGetProperty(outputUnit,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Output,
                                  0, &streamDesc, &size);
    streamDesc.SetCanonical(2,false);
    streamDesc.mSampleRate = kGraphSampleRate;
    size = sizeof(streamDesc);
    result = AudioUnitSetProperty(mixerUnit,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Input,
                                  0, &streamDesc, sizeof(streamDesc));
    streamDesc.SetCanonical(outChannels,false);
    result = AudioUnitSetProperty(mixerUnit,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Output,
                                  0, &streamDesc, sizeof(streamDesc));

    // connect nodes
    AUGraphConnectNodeInput(graph, synthNode, 0, effectNode, 0);
    AUGraphConnectNodeInput(graph, effectNode, 0, mixerNode, 0);
    AUGraphConnectNodeInput(graph, mixerNode, 0, outputNode, 0);

// initialize graph
AUGraphInitialize(graph);
// leaving the MIDI synth connections out for clearifying reasons...


    // map to output bus #1
    [self mapOutputToChannels:0];
}




-(IBAction)outputChannelsSelected:(id)sender {
[self mapOutputToChannels:(int)[sender indexOfItem:[sender selectedItem]]];
}




-(void)mapOutputToChannels:(int)pairIndex {
    CAStreamBasicDescription desc;
    OSStatus result = noErr;
    UInt32 inChannels = 2;
    UInt32 i,j;

    AudioUnit mixerUnit;
    AUGraphGetNodeInfo(graph, mixerNode, NULL, NULL, NULL, &mixerUnit);

    // set volumes
    UInt32 element;
    Float32 mixVolume = 1;
    // set input volumes
    for(i=0; i<inChannels; ++i) {
        element = i;
        result = AudioUnitSetParameter(mixerUnit,
                                       kMatrixMixerParam_Volume,
                                       kAudioUnitScope_Input,
                                       element, mixVolume, 0);
    }
    // set output volumes
    for(i=0; i<outChannels; ++i) {
        element = i;
        result = AudioUnitSetParameter(mixerUnit,
                                       kMatrixMixerParam_Volume,
                                       kAudioUnitScope_Output,
                                       element, mixVolume, 0);
    }
    // set crosspoint volume
    i = 0;
    j = 0;
    for(j=0; j<outChannels; j=j+2) {
        // we assume to have a stereo input (0/1) only
        if(j == pairIndex * 2) {
            mixVolume = 1;
        } else {
            mixVolume = 0;
        }
        // set left channel
        element = 0 << 16 | j & 0x0000FFFF;
        result = AudioUnitSetParameter(mixerUnit,
                                       kMatrixMixerParam_Volume,
                                       kAudioUnitScope_Global,
                                       element, mixVolume, 0);
        // set right channel
        element = 1 << 16 | (j+1) & 0x0000FFFF;
        result = AudioUnitSetParameter(mixerUnit,
                                       kMatrixMixerParam_Volume,
                                       kAudioUnitScope_Global,
                                       element, mixVolume, 0);
    }
    // set master volume
    result = AudioUnitSetParameter(mixerUnit,
                                   kMatrixMixerParam_Volume,
                                   kAudioUnitScope_Global,
                                   0xFFFFFFFF, 1, 0);

if(debugMode) {
NSLog(@"---- channel info for AU %@ ----", [self name]);
PrintMatrixMixerVolumes(NULL,mixerUnit); // i found it useful to change the "MatrixMixerVolumes.h" from the PublicUtility to print it's contents to the RunLog than writing into a file
NSLog(@"-------------------------------------");
}
// select menuItem
[outputChannelsPopup selectItemAtIndex:outChannelPair];
}


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >How to route channels from SynthUnit to a multi-channel device? (From: michael markert <email@hidden>)
 >Re: How to route channels from SynthUnit to a multi-channel device? (From: William Stewart <email@hidden>)

  • Prev by Date: Re: AudioConverterConvertBuffer() and interleaved data
  • Next by Date: Re: Which Audio Formats are supported directly by CoreAudio
  • Previous by thread: Re: How to route channels from SynthUnit to a multi-channel device?
  • Next by thread: Re: How to route channels from SynthUnit to a multi-channel device?
  • Index(es):
    • Date
    • Thread