Esempio n. 1
0
void IOAudioPort::deactivateAudioControls()
{
    OSCollectionIterator *iterator;

    if (!audioControls) {
        return;
    }

    iterator = OSCollectionIterator::withCollection(audioControls);

    if (iterator) {
        IOAudioControl *control;

        while ( (control = (IOAudioControl *)iterator->getNextObject()) ) {
            // Should we check to see if we're the provider?
            if (!isInactive()) {
                control->terminate();
            }
        }

        iterator->release();
    }

    audioControls->flushCollection();
}
Esempio n. 2
0
void IOAudioPort::registerService(IOOptionBits options)
{
    super::registerService(options);

    if (audioControls && !isRegistered) {
        OSCollectionIterator *iterator;

        iterator = OSCollectionIterator::withCollection(audioControls);
	if (iterator) {
            IOAudioControl *control;
    
            while ( (control = (IOAudioControl *)iterator->getNextObject()) ) {
                if (control->getProvider() == this) {
                    control->registerService();
                }
            }
            iterator->release();
	}
    }

    isRegistered = true;
}
Esempio n. 3
0
void	AREngine::CreateControls(UInt32 inNumberChannels)
{
	for(UInt32 theChannelID = 0; theChannelID <= inNumberChannels; ++theChannelID)
	{
		IOAudioControl* theControl;
		IOAudioSelectorControl* theSelectorControl;
		char theChannelName[32];
		if(theChannelID > 0)
		{
			snprintf(theChannelName, 32, "Channel %lu", theChannelID);
		}
		else
		{
			strncpy(theChannelName, kIOAudioControlChannelNameAll, 32);
		}
		
		//	clock source selector
		if(theChannelID == 0)
		{
			theSelectorControl = IOAudioSelectorControl::create(0, theChannelID, theChannelName, 0, kIOAudioSelectorControlSubTypeClockSource, kIOAudioControlUsageInput);
			if(theSelectorControl != NULL)
			{
				theSelectorControl->addAvailableSelection(0, "Internal");
				theSelectorControl->addAvailableSelection(1, "External 1");
				theSelectorControl->addAvailableSelection(2, "External 2");
				theSelectorControl->addAvailableSelection(3, "External 3");
				theSelectorControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theSelectorControl);
				theSelectorControl->release();
				theSelectorControl = NULL;
			}
		}
		
		//	output volume
		theControl = IOAudioLevelControl::createVolumeControl(65535, 0, 65535, (-22 << 16) + (32768), 0, theChannelID, theChannelName, 0, kIOAudioControlUsageOutput);
		if(theControl != NULL)
		{
			theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
			addDefaultAudioControl(theControl);
			theControl->release();
			theControl = NULL;
		}
		
		//	output mute
		theControl = IOAudioToggleControl::createMuteControl(false, theChannelID, theChannelName, 0, kIOAudioControlUsageOutput);
		if(theControl != NULL)
		{
			theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
			addDefaultAudioControl(theControl);
			theControl->release();
			theControl = NULL;
		}
		
		//	output solo
		if(theChannelID != 0)
		{
			theControl = IOAudioToggleControl::create(false, theChannelID, theChannelName, 0, kIOAudioToggleControlSubTypeSolo, kIOAudioControlUsageOutput);
			if(theControl != NULL)
			{
				theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theControl);
				theControl->release();
				theControl = NULL;
			}
		}
		
		//	output data source
		if(theChannelID != 0)
		{
			theSelectorControl = IOAudioSelectorControl::create(0, theChannelID, theChannelName, 0, kIOAudioSelectorControlSubTypeOutput, kIOAudioControlUsageOutput);
			if(theSelectorControl != NULL)
			{
				theSelectorControl->addAvailableSelection(0, "Source 1");
				theSelectorControl->addAvailableSelection(1, "Source 2");
				theSelectorControl->addAvailableSelection(2, "Source 3");
				theSelectorControl->addAvailableSelection(3, "Source 4");
				theSelectorControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theSelectorControl);
				theSelectorControl->release();
				theSelectorControl = NULL;
			}
		}

		//	output line level
		if(theChannelID != 0)
		{
			theSelectorControl = IOAudioSelectorControl::create(kIOAudioSelectorControlSubTypeChannelLevelMinus10dBV, theChannelID, theChannelName, 0, kIOAudioSelectorControlSubTypeChannelNominalLineLevel, kIOAudioControlUsageOutput);
			if(theSelectorControl != NULL)
			{
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelPlus4dBu, "+4dBu");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelMinus10dBV, "-10dBV");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelMinus20dBV, "-20dBV");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelMicLevel, "Mic");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelInstrumentLevel, "Instrument");
				theSelectorControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theSelectorControl);
				theSelectorControl->release();
				theSelectorControl = NULL;
			}
		}
		
		//	input volume
		theControl = IOAudioLevelControl::createVolumeControl(65535, 0, 65535, (-22 << 16) + (32768), 0, theChannelID, theChannelName, 0, kIOAudioControlUsageInput);
		if(theControl != NULL)
		{
			theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
			addDefaultAudioControl(theControl);
			theControl->release();
			theControl = NULL;
		}

		//	input mute
		theControl = IOAudioToggleControl::createMuteControl(false, theChannelID, theChannelName, 0, kIOAudioControlUsageInput);
		if(theControl != NULL)
		{
			theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
			addDefaultAudioControl(theControl);
			theControl->release();
			theControl = NULL;
		}
		
		//	input solo
		if(theChannelID != 0)
		{
			theControl = IOAudioToggleControl::create(false, theChannelID, theChannelName, 0, kIOAudioToggleControlSubTypeSolo, kIOAudioControlUsageInput);
			if(theControl != NULL)
			{
				theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theControl);
				theControl->release();
				theControl = NULL;
			}
		}
		
		//	input data source
		if(theChannelID != 0)
		{
			theSelectorControl = IOAudioSelectorControl::create(0, theChannelID, theChannelName, 0, kIOAudioSelectorControlSubTypeInput, kIOAudioControlUsageInput);
			if(theSelectorControl != NULL)
			{
				theSelectorControl->addAvailableSelection(0, "Source 1");
				theSelectorControl->addAvailableSelection(1, "Source 2");
				theSelectorControl->addAvailableSelection(2, "Source 3");
				theSelectorControl->addAvailableSelection(3, "Source 4");
				theSelectorControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theSelectorControl);
				theSelectorControl->release();
				theSelectorControl = NULL;
			}
		}

		//	input line level
		if(theChannelID != 0)
		{
			theSelectorControl = IOAudioSelectorControl::create(kIOAudioSelectorControlSubTypeChannelLevelMinus10dBV, theChannelID, theChannelName, 0, kIOAudioSelectorControlSubTypeChannelNominalLineLevel, kIOAudioControlUsageInput);
			if(theSelectorControl != NULL)
			{
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelPlus4dBu, "+4dBu");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelMinus10dBV, "-10dBV");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelMinus20dBV, "-20dBV");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelMicLevel, "Mic");
				theSelectorControl->addAvailableSelection(kIOAudioSelectorControlSubTypeChannelLevelInstrumentLevel, "Instrument");
				theSelectorControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theSelectorControl);
				theSelectorControl->release();
				theSelectorControl = NULL;
			}
		}

		//	play through volume
		theControl = IOAudioLevelControl::createVolumeControl(65535, 0, 65535, (-22 << 16) + (32768), 0, theChannelID, theChannelName, 0, kIOAudioControlUsagePassThru);
		if(theControl != NULL)
		{
			theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
			addDefaultAudioControl(theControl);
			theControl->release();
			theControl = NULL;
		}

		//	play through on/off
		theControl = IOAudioToggleControl::createMuteControl(true, theChannelID, theChannelName, 0, kIOAudioControlUsagePassThru);
		if(theControl != NULL)
		{
			theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
			addDefaultAudioControl(theControl);
			theControl->release();
			theControl = NULL;
		}
		
		//	play through solo
		if(theChannelID != 0)
		{
			theControl = IOAudioToggleControl::create(false, theChannelID, theChannelName, 0, kIOAudioToggleControlSubTypeSolo, kIOAudioControlUsagePassThru);
			if(theControl != NULL)
			{
				theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theControl);
				theControl->release();
				theControl = NULL;
			}
		}
		
		//	play through data destination
		if(theChannelID != 0)
		{
			theSelectorControl = IOAudioSelectorControl::create(0, theChannelID, theChannelName, 0, kIOAudioSelectorControlSubTypeDestination, kIOAudioControlUsagePassThru);
			if(theSelectorControl != NULL)
			{
				theSelectorControl->addAvailableSelection(0, "Destination 1");
				theSelectorControl->addAvailableSelection(1, "Destination 2");
				theSelectorControl->addAvailableSelection(2, "Destination 3");
				theSelectorControl->addAvailableSelection(3, "Destination 4");
				theSelectorControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theSelectorControl);
				theSelectorControl->release();
				theSelectorControl = NULL;
			}
		}

		//	play through stereo pan
		if((inNumberChannels > 2) && (theChannelID != 0))
		{
			theControl = ARStereoPanControl::create(0, -128, 0, 128, 1, 2, theChannelID, theChannelName, 0, ARStereoPanControl::kIOAudioControlSubTypeStereoPan, kIOAudioControlUsagePassThru);
			if(theControl != NULL)
			{
				theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theControl);
				theControl->release();
				theControl = NULL;
			}
		}

		//	LFE volume
		if(theChannelID == 0)
		{
			theControl = IOAudioLevelControl::create(65535, 0, 65535, (-22 << 16) + (32768), 0, theChannelID, theChannelName, 0, kIOAudioLevelControlSubTypeLFEVolume, kIOAudioControlUsageOutput);
			if(theControl != NULL)
			{
				theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theControl);
				theControl->release();
				theControl = NULL;
			}
		}

		//	LFE mute
		if(theChannelID == 0)
		{
			theControl = IOAudioToggleControl::create(false, theChannelID, theChannelName, 0, kIOAudioToggleControlSubTypeLFEMute, kIOAudioControlUsageOutput);
			if(theControl != NULL)
			{
				theControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)IntegerControlChangeHandler, this);
				addDefaultAudioControl(theControl);
				theControl->release();
				theControl = NULL;
			}
		}
	}
}
Esempio n. 4
0
bool
PNetAudioDevice::createAudioEngine ()
{
  bool res = false;
  IOAudioControl *ctl = 0;

  PNetAudioEngine *engine = new PNetAudioEngine;
  if (!engine || !engine->init())
    goto end;

  // left output
  ctl = IOAudioLevelControl::createVolumeControl(65535,			// default
						 0,			// min
						 65535,			// max
						 -22 << 16 + 1 << 15,	// min -22.5 dB
						 0,			// max 0.0 dB
						 kIOAudioControlChannelIDDefaultLeft,
						 kIOAudioControlChannelNameLeft,
						 0,			// output id
						 kIOAudioControlUsageOutput);
  if (!ctl)
    goto end;
  ctl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)controlValueChangeHandler, this);
  engine->addDefaultAudioControl(ctl);
  ctl->release();

  // right output
  ctl = IOAudioLevelControl::createVolumeControl(65535,
						 0,
						 65535,
						 -22 << 16 + 1 << 15,
						 0,
						 kIOAudioControlChannelIDDefaultRight,
						 kIOAudioControlChannelNameRight,
						 0,
						 kIOAudioControlUsageOutput);
  if (!ctl)
    goto end;
  ctl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)controlValueChangeHandler, this);
  engine->addDefaultAudioControl(ctl);
  ctl->release();

  // mute output
  ctl = IOAudioToggleControl::createMuteControl(false,	// default not mute
						kIOAudioControlChannelIDAll,
						kIOAudioControlChannelNameAll,
						0,
						kIOAudioControlUsageOutput);
  if (!ctl)
    goto end;
  ctl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)controlValueChangeHandler, this);
  engine->addDefaultAudioControl(ctl);
  ctl->release();

  // left input
  ctl = IOAudioLevelControl::createVolumeControl(65535,
						 0,
						 65535,
						 -22 << 16 + 1 << 15,
						 0,
						 kIOAudioControlChannelIDDefaultLeft,
						 kIOAudioControlChannelNameLeft,
						 0,
						 kIOAudioControlUsageInput);
  if (!ctl)
    goto end;
  ctl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)controlValueChangeHandler, this);
  engine->addDefaultAudioControl(ctl);
  ctl->release();

  // right input
  ctl = IOAudioLevelControl::createVolumeControl(65535,
						 0,
						 65535,
						 -22 << 16 + 1 << 15,
						 0,
						 kIOAudioControlChannelIDDefaultRight,
						 kIOAudioControlChannelNameRight,
						 0,
						 kIOAudioControlUsageInput);
  if (!ctl)
    goto end;
  ctl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)controlValueChangeHandler, this);
  engine->addDefaultAudioControl(ctl);
  ctl->release();

  // mute input
  ctl = IOAudioToggleControl::createMuteControl(false,
						kIOAudioControlChannelIDAll,
						kIOAudioControlChannelNameAll,
						0,
						kIOAudioControlUsageInput);
  if (!ctl)
    goto end;
  ctl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)controlValueChangeHandler, this);
  engine->addDefaultAudioControl(ctl);
  ctl->release();

  activateAudioEngine(engine);

  res = true;
 end:
  if (engine)
    engine->release();
  if (ctl)
    ctl->release();
  return res;
}
Esempio n. 5
0
bool PhantomAudioEngine::createAudioStreams(IOAudioSampleRate *initialSampleRate)
{
    bool result = false;
    OSNumber *number;
    UInt32 numStreams, streamNum;
    OSArray *formatArray, *sampleRateArray;
    UInt32 startingChannelID = 1;
    IOAudioControl *control;
    OSString *desc;
    OSBoolean *boolean;
    bool separateStreamBuffers = FALSE, separateInputBuffers = FALSE;
    
    desc = OSDynamicCast(OSString, getProperty(DESCRIPTION_KEY));
    if (desc) {
        setDescription(desc->getCStringNoCopy());
    }
    
    number = OSDynamicCast(OSNumber, getProperty(NUM_STREAMS_KEY));
    if (number) {
        numStreams = number->unsigned32BitValue();
    } else {
        numStreams = NUM_STREAMS;
    }
    
    formatArray = OSDynamicCast(OSArray, getProperty(FORMATS_KEY));
    if (formatArray == NULL) {
        goto Done;
    }
    
    sampleRateArray = OSDynamicCast(OSArray, getProperty(SAMPLE_RATES_KEY));
    if (sampleRateArray == NULL) {
        goto Done;
    }
    
    boolean = OSDynamicCast(OSBoolean, getProperty(SEPARATE_STREAM_BUFFERS_KEY));
    if (boolean != NULL) {
        separateStreamBuffers = boolean->getValue();
    }
    
    boolean = OSDynamicCast(OSBoolean, getProperty(SEPARATE_INPUT_BUFFERS_KEY));
    if (boolean != NULL) {
        separateInputBuffers = boolean->getValue();
    }
    
    if (separateStreamBuffers) {
        IOLog("PhantomAudioEngine::createAudioStreams() - Creating a separate buffer for each stream.\n");
    } else {
        IOLog("PhantomAudioEngine::createAudioStreams() - Sharing one buffer among all streams.\n");
    }
    
    if (separateInputBuffers) {
        IOLog("PhantomAudioEngine::createAudioStreams() - Creating separate buffers for input and output.\n");
    } else {
        IOLog("PhantomAudioEngine::createAudioStreams() - Sharing input and output buffers.\n");
    }
    
    for (streamNum = 0; streamNum < numStreams; streamNum++) {
        IOAudioStream *inputStream = NULL, *outputStream = NULL;
        UInt32 maxBitWidth = 0;
        UInt32 maxNumChannels = 0;
        OSCollectionIterator *formatIterator = NULL, *sampleRateIterator = NULL;
        OSDictionary *formatDict;
        IOAudioSampleRate sampleRate;
        IOAudioStreamFormat initialFormat;
        bool initialFormatSet;
        UInt32 channelID;
        char outputStreamName[20], inputStreamName[20];
        UInt32 streamBufferSize;
        
        initialFormatSet = false;
        
        sampleRate.whole = 0;
        sampleRate.fraction = 0;
                
        inputStream = new IOAudioStream;
        if (inputStream == NULL) {
            goto Error;
        }
        
        outputStream = new IOAudioStream;
        if (outputStream == NULL) {
            goto Error;
        }
        
        sprintf(inputStreamName, "Input Stream #%ld", streamNum + 1);
        sprintf(outputStreamName, "Output Stream #%ld", streamNum + 1);

        if (!inputStream->initWithAudioEngine(this, kIOAudioStreamDirectionInput, startingChannelID, inputStreamName) ||
            !outputStream->initWithAudioEngine(this, kIOAudioStreamDirectionOutput, startingChannelID, outputStreamName)) {
            goto Error;
        }
        
        formatIterator = OSCollectionIterator::withCollection(formatArray);
        if (!formatIterator) {
            goto Error;
        }
        
        sampleRateIterator = OSCollectionIterator::withCollection(sampleRateArray);
        if (!sampleRateIterator) {
            goto Error;
        }
        
        formatIterator->reset();
        while (formatDict = (OSDictionary *)formatIterator->getNextObject()) {
            IOAudioStreamFormat format;
            
            if (OSDynamicCast(OSDictionary, formatDict) == NULL) {
                goto Error;
            }
            
            if (IOAudioStream::createFormatFromDictionary(formatDict, &format) == NULL) {
                goto Error;
            }
            
            if (!initialFormatSet) {
                initialFormat = format;
            }
            
            sampleRateIterator->reset();
            while (number = (OSNumber *)sampleRateIterator->getNextObject()) {
                if (!OSDynamicCast(OSNumber, number)) {
                    goto Error;
                }
                
                sampleRate.whole = number->unsigned32BitValue();
                
                inputStream->addAvailableFormat(&format, &sampleRate, &sampleRate);
                if (format.fBitDepth == 24) {
                    IOAudioStream::AudioIOFunction functions[2];
                    functions[0] = process24BitSamples;
                    functions[1] = clip24BitSamples;
                    //outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate, functions, 2);
                    outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate, (IOAudioStream::AudioIOFunction)clip24BitSamples);
					if (format.fNumericRepresentation == kIOAudioStreamSampleFormatLinearPCM && format.fIsMixable == TRUE) {
						format.fIsMixable = FALSE;
						outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate, (IOAudioStream::AudioIOFunction)clip24BitSamples);
					}
                } else if (format.fBitDepth == 16) {
                    IOAudioStream::AudioIOFunction functions[2];
                    functions[0] = process16BitSamples;
                    functions[1] = clip16BitSamples;
                    //outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate, functions, 2);
                    outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate, (IOAudioStream::AudioIOFunction)clip16BitSamples);
					if (format.fNumericRepresentation == kIOAudioStreamSampleFormatLinearPCM && format.fIsMixable == TRUE) {
						format.fIsMixable = FALSE;
						outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate, (IOAudioStream::AudioIOFunction)clip24BitSamples);
					}
                } else {
                    outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate);
					if (format.fNumericRepresentation == kIOAudioStreamSampleFormatLinearPCM && format.fIsMixable == TRUE) {
						format.fIsMixable = FALSE;
						outputStream->addAvailableFormat(&format, &sampleRate, &sampleRate, (IOAudioStream::AudioIOFunction)clip24BitSamples);
					}
                }
                
                if (format.fNumChannels > maxNumChannels) {
                    maxNumChannels = format.fNumChannels;
                }
                
                if (format.fBitWidth > maxBitWidth) {
                    maxBitWidth = format.fBitWidth;
                }
                
                if (initialSampleRate->whole == 0) {
                    initialSampleRate->whole = sampleRate.whole;
                }
            }
        }
        
        streamBufferSize = blockSize * numBlocks * maxNumChannels * maxBitWidth / 8;
        
        if (outputBuffer == NULL) {
            if (separateStreamBuffers) {
                outputBufferSize = streamBufferSize * numStreams;
            } else {
                outputBufferSize = streamBufferSize;
            }

            outputBuffer = (void *)IOMalloc(outputBufferSize);
            if (!outputBuffer) {
                IOLog("Error allocating output buffer - %lu bytes.\n", outputBufferSize);
                goto Error;
            }
            
            inputBufferSize = outputBufferSize;
            
            if (separateInputBuffers) {
                inputBuffer = (void *)IOMalloc(inputBufferSize);
                if (!inputBuffer) {
                    IOLog("Error allocating input buffer - %lu bytes.\n", inputBufferSize);
                    goto Error;
                }
            } else {
                inputBuffer = outputBuffer;
            }
        }
        
        inputStream->setFormat(&initialFormat);
        outputStream->setFormat(&initialFormat);
        
        if (separateStreamBuffers) {
            inputStream->setSampleBuffer(&((UInt8 *)inputBuffer)[streamBufferSize * streamNum], streamBufferSize);
            outputStream->setSampleBuffer(&((UInt8 *)outputBuffer)[streamBufferSize * streamNum], streamBufferSize);
        } else {
            inputStream->setSampleBuffer(inputBuffer, streamBufferSize);
            outputStream->setSampleBuffer(outputBuffer, streamBufferSize);
        }
        addAudioStream(inputStream);
        inputStream->release();
        
        addAudioStream(outputStream);
        outputStream->release();
        
        formatIterator->release();
        sampleRateIterator->release();
        
        for (channelID = startingChannelID; channelID < (startingChannelID + maxNumChannels); channelID++) {
            char channelName[20];
            
            sprintf(channelName, "Channel %lu", channelID);
            
            control = IOAudioLevelControl::createVolumeControl(65535,
                                                                0,
                                                                65535,
                                                                (-22 << 16) + (32768),
                                                                0,
                                                                channelID,
                                                                channelName,
                                                                0,
                                                                kIOAudioControlUsageOutput);
            if (!control) {
                goto Error;
            }
            
            control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::volumeChangeHandler, audioDevice);
            addDefaultAudioControl(control);
            control->release();
            
            control = IOAudioToggleControl::createMuteControl(false,
                                                                channelID,
                                                                channelName,
                                                                0,
                                                                kIOAudioControlUsageOutput);
            if (!control) {
                goto Error;
            }
            
            control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::outputMuteChangeHandler, audioDevice);
            addDefaultAudioControl(control);
            control->release();
                                                                
            control = IOAudioLevelControl::createVolumeControl(65535,
                                                                0,
                                                                65535,
                                                                (-22 << 16) + (32768),
                                                                0,
                                                                channelID,
                                                                channelName,
                                                                0,
                                                                kIOAudioControlUsageInput);
            if (!control) {
                goto Error;
            }
            
            control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::gainChangeHandler, audioDevice);
            addDefaultAudioControl(control);
            control->release();
            
            control = IOAudioToggleControl::createMuteControl(false,
                                                                channelID,
                                                                channelName,
                                                                0,
                                                                kIOAudioControlUsageInput);
            if (!control) {
                goto Error;
            }
            
            control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::inputMuteChangeHandler, audioDevice);
            addDefaultAudioControl(control);
            control->release();
            
            control = IOAudioToggleControl::createMuteControl(true,
                                                                channelID,
                                                                channelName,
                                                                0,
                                                                kIOAudioControlUsagePassThru);
            if (!control) {
                goto Error;
            }
            
            control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::passThruChangeHandler, audioDevice);
            addDefaultAudioControl(control);
            control->release();
        }
        
        startingChannelID += maxNumChannels;
        
        continue;

Error:

        IOLog("PhantomAudioEngine[%p]::createAudioStreams() - ERROR\n", this);
    
        if (inputStream) {
            inputStream->release();
        }
        
        if (outputStream) {
            outputStream->release();
        }
        
        if (formatIterator) {
            formatIterator->release();
        }
        
        if (sampleRateIterator) {
            sampleRateIterator->release();
        }
        
        goto Done;
    }
    
    control = IOAudioLevelControl::createVolumeControl(65535,
                                                        0,
                                                        65535,
                                                        (-22 << 16) + (32768),
                                                        0,
                                                        kIOAudioControlChannelIDAll,
                                                        kIOAudioControlChannelNameAll,
                                                        0,
                                                        kIOAudioControlUsageOutput);
    if (!control) {
        goto Done;
    }
    
    control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::volumeChangeHandler, audioDevice);
    addDefaultAudioControl(control);
    control->release();
    
    control = IOAudioToggleControl::createMuteControl(false,
                                                        kIOAudioControlChannelIDAll,
                                                        kIOAudioControlChannelNameAll,
                                                        0,
                                                        kIOAudioControlUsageOutput);
    if (!control) {
        goto Done;
    }
    
    control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::outputMuteChangeHandler, audioDevice);
    addDefaultAudioControl(control);
    control->release();
                                                        
    control = IOAudioLevelControl::createVolumeControl(65535,
                                                        0,
                                                        65535,
                                                        (-22 << 16) + (32768),
                                                        0,
                                                        kIOAudioControlChannelIDAll,
                                                        kIOAudioControlChannelNameAll,
                                                        0,
                                                        kIOAudioControlUsageInput);
    if (!control) {
        goto Done;
    }
    
    control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::gainChangeHandler, audioDevice);
    addDefaultAudioControl(control);
    control->release();
    
    control = IOAudioToggleControl::createMuteControl(false,
                                                        kIOAudioControlChannelIDAll,
                                                        kIOAudioControlChannelNameAll,
                                                        0,
                                                        kIOAudioControlUsageInput);
    if (!control) {
        goto Done;
    }
    
    control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::inputMuteChangeHandler, audioDevice);
    addDefaultAudioControl(control);
    control->release();
    
    control = IOAudioToggleControl::createMuteControl(true,
                                                        kIOAudioControlChannelIDAll,
                                                        kIOAudioControlChannelNameAll,
                                                        0,
                                                        kIOAudioControlUsagePassThru);
    if (!control) {
        goto Done;
    }
    
    control->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)PhantomAudioDevice::passThruChangeHandler, audioDevice);
    addDefaultAudioControl(control);
    control->release();

    result = true;
    
Done:

    if (!result) {
        IOLog("PhantomAudioEngine[%p]::createAudioStreams() - failed!\n", this);
    }

    return result;
}