Using the iPodTime audio unit for playing audio books
Q: What properties can be set for AUiPodTime and how do I configure it?
A: What properties can be set for AUiPodTime and how do I configure it?
AUiPodTime is a time-stretching audio unit able to perform rate changes from 0.5x to 2x. This unit is designed to be used with audio books and speech recordings such as a recorded lecture allowing playback speed changes without affecting pitch.
The AUiPodTime audio unit is described by the kAudioUnitType_FormatConverter
type and kAudioUnitSubType_AUiPodTime
subtype. The input and output stream format must be the canonical audio unit data format and may contain one or two channels. Both formats must have the same number of channels and the same sample rate; all common sample rates are supported.
When using this audio unit in an audio unit graph, remember to set the output stream format -- each nodes output stream format (including sample rate) must be set explicitly. This stream format is then propagated to its destination's input stream format.
Listing 1 Typical example of setting up an audio unit graph.
- (void)initializeAUGraph:(Float64)inSampleRate { printf("initializeAUGraph\n"); AUNode outputNode; AUNode iPodTimeNode; AUNode mixerNode; AUNode converterNode; AudioUnit converterAU; printf("create client format ASBD\n"); // client format audio going into the converter mClientFormat.SetCanonical(2, true); mClientFormat.mSampleRate = 22050.0; mClientFormat.Print(); printf("create output format ASBD\n"); // output format mOutputFormat.SetAUCanonical(2, false); mOutputFormat.mSampleRate = inSampleRate; mOutputFormat.Print(); OSStatus result = noErr; printf("-----------\n"); printf("new AUGraph\n"); // create a new AUGraph result = NewAUGraph(&mGraph); if (result) { printf("NewAUGraph result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } // create three CAComponentDescription for the AUs we want in the graph // output unit CAComponentDescription output_desc(kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple); // iPodTime unit CAComponentDescription iPodTime_desc(kAudioUnitType_FormatConverter, kAudioUnitSubType_AUiPodTime, kAudioUnitManufacturer_Apple); // multichannel mixer unit CAComponentDescription mixer_desc(kAudioUnitType_Mixer, kAudioUnitSubType_MultiChannelMixer, kAudioUnitManufacturer_Apple); // AU Converter CAComponentDescription converter_desc(kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple); printf("add nodes\n"); // create a node in the graph that is an AudioUnit, using the supplied // AudioComponentDescription to find and open that unit result = AUGraphAddNode(mGraph, &output_desc, &outputNode); if (result) { printf("AUGraphNewNode 1 result %lu %4.4s\n", result, (char*)&result); return; } result = AUGraphAddNode(mGraph, &iPodTime_desc, &iPodTimeNode); if (result) { printf("AUGraphNewNode 2 result %lu %4.4s\n", result, (char*)&result); return; } result = AUGraphAddNode(mGraph, &mixer_desc, &mixerNode); if (result) { printf("AUGraphNewNode 3 result %lu %4.4s\n", result, (char*)&result); return; } result = AUGraphAddNode(mGraph, &converter_desc, &converterNode); if (result) { printf("AUGraphNewNode 3 result %lu %4.4s\n", result, (char*)&result); return; } // connect a node's output to a node's input // converter -> mixer -> iPodTime -> output result = AUGraphConnectNodeInput(mGraph, converterNode, 0, mixerNode, 0); if (result) { printf("AUGraphConnectNodeInput result %lu %4.4s\n", result, (char*)&result); return; } result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, iPodTimeNode, 0); if (result) { printf("AUGraphConnectNodeInput result %lu %4.4s\n", result, (char*)&result); return; } result = AUGraphConnectNodeInput(mGraph, iPodTimeNode, 0, outputNode, 0); if (result) { printf("AUGraphConnectNodeInput result %lu %4.4s\n", result, (char*)&result); return; } // open the graph -- AudioUnits are open but not initialized // (no resource allocation occurs here) result = AUGraphOpen(mGraph); if (result) { printf("AUGraphOpen result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } // grab audio unit instances from the nodes result = AUGraphNodeInfo(mGraph, converterNode, NULL, &converterAU); if (result) { printf("AUGraphNodeInfo result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } result = AUGraphNodeInfo(mGraph, mixerNode, NULL, &mMixer); if (result) { printf("AUGraphNodeInfo result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } result = AUGraphNodeInfo(mGraph, iPodTimeNode, NULL, &mIPodTime); if (result) { printf("AUGraphNodeInfo result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } // set bus count UInt32 numbuses = 1; printf("set input bus count %lu\n", numbuses); result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses, sizeof(numbuses)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } // setup render callback struct AURenderCallbackStruct rcbs; rcbs.inputProc = &renderInput; rcbs.inputProcRefCon = &mUserData; printf("set AUGraphSetNodeInputCallback\n"); // set a callback for the specified node's specified input bus (bus 1) result = AUGraphSetNodeInputCallback(mGraph, converterNode, 0, &rcbs); if (result) { printf("AUGraphSetNodeInputCallback result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } printf("set converter input bus %d client kAudioUnitProperty_StreamFormat\n", 0); // set the input stream format, this is the format of the audio // for the converter input bus (bus 1) result = AudioUnitSetProperty(converterAU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &mClientFormat, sizeof(mClientFormat)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } // in an au graph, each nodes output stream format (including sample rate) // needs to be set explicitly this stream format is propagated to its // destination's input stream format printf("set converter output kAudioUnitProperty_StreamFormat\n"); // set the output stream format of the converter result = AudioUnitSetProperty(converterAU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &mOutputFormat, sizeof(mOutputFormat)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } printf("set mixer output kAudioUnitProperty_StreamFormat\n"); // set the output stream format of the mixer result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &mOutputFormat, sizeof(mOutputFormat)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } printf("set iPodTime output kAudioUnitProperty_StreamFormat\n"); // set the output stream format of the iPodTime unit result = AudioUnitSetProperty(mIPodTime, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &mOutputFormat, sizeof(mOutputFormat)); if (result) { printf("AudioUnitSetProperty result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } printf("AUGraphInitialize\n"); // now that we've set everything up we can initialize the graph, this will also // validate the connections result = AUGraphInitialize(mGraph); if (result) { printf("AUGraphInitialize result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } CAShow(mGraph); } |
The kTimePitchParam_Rate
parameter declared in AudioUnitParameters.h
is used to control audio playback rate from 0.5x to 2.0x speed. AudioUnitParameterValue
is a Float32
rounded by the unit to whichever of the following is closest: 0.5, 0.66667, 0.8, 1.0, 1.25, 1.5, 2. A playback rate of 1.0 is the default.
Listing 2 Method setting the AUiPodTime rate.
// sets the rate of the iPodTime Audio Unit - (void)setIPodTimeRate:(AudioUnitParameterValue)value { OSStatus result = AudioUnitSetParameter(mIPodTime, kTimePitchParam_Rate, kAudioUnitScope_Global, 0, value, 0); if (result) { printf("AudioUnitSetParameter kTimePitchParam_Rate Global result %ld %08X %4.4s\n", result, (unsigned int)result, (char*)&result); return; } } |
Document Revision History
Date | Notes |
---|---|
2010-09-03 | New document that describes the usage of the AUiPodTime unit which is useful when playing back audio books at different rates without changing pitch. |
Copyright © 2010 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2010-09-03