|
Q: How can we specify a specific pair of channels (speakers) to use for playback of a QuickTime audio movie through a multi-channel speaker system?A: For a given QuickTime movie audio track, use the The channel layout describes the playback roles for the channels in an audio recording. For example, in a stereo recording, channel 1 has the role of “left front” and channel 2 has the role of “right front.” When using Here's the typedef struct AudioChannelLayout { AudioChannelLayoutTag mChannelLayoutTag; UInt32 mChannelBitmap; UInt32 mNumberChannelDescriptions; AudioChannelDescription mChannelDescriptions[1]; } AudioChannelLayout; A “Channel Layout Tags” value, stored in A value of A value of A value greater than 0x10000 indicates one of the pre-defined layout tags such as
For example, the tag Each typedef struct AudioChannelDescription { AudioChannelLabel mChannelLabel; UInt32 mChannelFlags; Float32 mCoordinates[3]; } AudioChannelDescription; The The The code in Listing 1 shows how to use the Note: If the chosen output device does not support the channel layout, sampling rate, or sample size of the movie audio, mix-down and resampling are performed automatically. #define fieldOffset(type, field) ((size_t) &((type *) 0)->field) const int kNumChannelDescriptions = 2; #include <Carbon/Carbon.h> #include <QuickTime/QuickTime.h> #include <AudioToolbox/AudioToolbox.h> #include <assert> // Set the channel layout of the movie audio for playback to the device. // We assume a movie with a single stereo stream (two channels) of audio. // The first channel of audio is set to play to LeftSurround, and the // second channel of audio is set to play to RightSurround. void setAudioTrackChannelLayout(Track inTrack) { UInt32 trackChannelLayoutSize; AudioChannelLayout* trackChannelLayout = NULL; // Allocate a layout of the required size. trackChannelLayoutSize = fieldOffset(AudioChannelLayout, mChannelDescriptions[kNumChannelDescriptions]); // Allocate buffer to hold the layout, initialize all bits to 0. trackChannelLayout = (AudioChannelLayout*)calloc(1, trackChannelLayoutSize); assert(trackChannelLayout != nil); // A tag that indicates the type of layout used. // Our channel layout is described using audio channel descriptions -- see // AudioChannelLayout.mChannelDescriptions below. trackChannelLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions ; // A bitmap that describes which channels are present. // We are not using channel bitmaps to describe our layout, we are using // the array of AudioChannelDescriptions to define the mapping. trackChannelLayout->mChannelBitmap = 0; // The number of channel descriptions in the mChannelDescriptionsarray. // We are using 2 channel descriptions -- one description for Left Surround, // the other for Right Surround. trackChannelLayout->mNumberChannelDescriptions = kNumChannelDescriptions ; // A label that describes the role of the channel. In common cases, such as // “Left” or “Right,” role implies location. In such cases, mChannelFlags // and mCoordinates can be set to 0. // In this example, we set the first channel to play to Left Surround, and // the second channel to play to Right Surround. trackChannelLayout->mChannelDescriptions[0].mChannelLabel = kAudioChannelLabel_LeftSurround ; trackChannelLayout->mChannelDescriptions[1].mChannelLabel = kAudioChannelLabel_RightSurround ; // Flags that indicate how to interpret the data in the mCoordinates field. // If the audio channel does not require this information, set this field to 0. trackChannelLayout->mChannelDescriptions[0].mChannelFlags = kAudioChannelFlags_AllOff ; trackChannelLayout->mChannelDescriptions[1].mChannelFlags = kAudioChannelFlags_AllOff ; // A set of three coordinates that specify the placement of the sound source for the // channel in three dimensions, according to the mChannelFlags information. // If the audio channel does not require this information, set this field to 0. trackChannelLayout->mChannelDescriptions[0].mCoordinates[0] = 0; trackChannelLayout->mChannelDescriptions[0].mCoordinates[1] = 0; trackChannelLayout->mChannelDescriptions[0].mCoordinates[2] = 0; trackChannelLayout->mChannelDescriptions[1].mCoordinates[0] = 0; trackChannelLayout->mChannelDescriptions[1].mCoordinates[1] = 0; trackChannelLayout->mChannelDescriptions[1].mCoordinates[2] = 0; // Set the channel layout properties on the audio track OSErr err = QTSetTrackProperty(inTrack, kQTPropertyClass_Audio, kQTAudioPropertyID_ChannelLayout, trackChannelLayoutSize, trackChannelLayout ); assert(err == noErr); free((void *)trackChannelLayout); } Using Discrete ChannelsAnother option for setting the channel layout is to use discrete channels, meaning channels without any layout imposed on them. Discrete channels remove any kind of confusion by eliminating the spatial assignments on the speakers, so instead of using one of the standard layouts you mark your content with discrete layouts. For example, given a 2-channel audio source you can assign the first channel to play out to the first speaker, and the second channel to play out to the second speaker. The code in Listing 2 demonstrates the use of discrete channels. In this example, the first stereo stream (first 2 channels) is marked as discrete-0, discrete-1, so that it will play to the first two speakers, and the second stereo stream is marked discrete-2, discrete-3, to play to the third and fourth speakers. #define fieldOffset(type, field) ((size_t) &((type *) 0)->field) const int kNumChannelDescr = 4; #include <Carbon/Carbon.h> #include <QuickTime/QuickTime.h> #include <AudioToolbox/AudioToolbox.h> #include <assert> // Set the channel layout of the movie audio for playback to the device. // We assume a movie with 2 stereo streams (four channels) of audio. // The first stereo stream is set to play out the first two speakers, and // the second stereo stream is set to play out the third and fourth speakers. void setAudioTrackChannelLayoutDiscrete(Track inTrack) { UInt32 trackChannelLayoutSize; AudioChannelLayout* trackChannelLayout = NULL; // Allocate a layout of the required size trackChannelLayoutSize = fieldOffset(AudioChannelLayout, mChannelDescriptions[kNumChannelDescr]); // Allocate buffer to hold the layout, initialize all bits to 0 trackChannelLayout = (AudioChannelLayout*)calloc(1, trackChannelLayoutSize); assert(trackChannelLayout != nil); // A tag that indicates the type of layout used. // Our channel layout is described using audio channel descriptions -- see // AudioChannelLayout.mChannelDescriptions below. trackChannelLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; // A bitmap that describes which channels are present. // We are not using channel bitmaps to describe our layout, we are using // the array of AudioChannelDescriptions to define the mapping. trackChannelLayout->mChannelBitmap = 0 ; // The number of channel descriptions in the mChannelDescriptionsarray. // We are using 4 channel descriptions, one each for: Discrete 0, Discrete 1, // Discrete 2 and Discrete 3. trackChannelLayout->mNumberChannelDescriptions = kNumChannelDescr ; // mChannelLabel = A label that describes the role of the channel. In common cases, // such as “Left” or “Right,” role implies location. In such cases, mChannelFlags // and mCoordinates can be set to 0. // // This example sets the following channel roles: // // first channel -> play to the first speaker trackChannelLayout->mChannelDescriptions[0].mChannelLabel = kAudioChannelLabel_Discrete_0; // second channel -> play to the second speaker trackChannelLayout->mChannelDescriptions[1].mChannelLabel = kAudioChannelLabel_Discrete_1; // third channel -> play to the third speaker trackChannelLayout->mChannelDescriptions[2].mChannelLabel = kAudioChannelLabel_Discrete_2; // fourth channel -> play to the fourth speaker trackChannelLayout->mChannelDescriptions[3].mChannelLabel = kAudioChannelLabel_Discrete_3; // Flags that indicate how to interpret the data in the mCoordinates field. // If the audio channel does not require this information, set this field to 0. trackChannelLayout->mChannelDescriptions[0].mChannelFlags = trackChannelLayout->mChannelDescriptions[1].mChannelFlags = trackChannelLayout->mChannelDescriptions[2].mChannelFlags = trackChannelLayout->mChannelDescriptions[3].mChannelFlags = kAudioChannelFlags_AllOff ; // Set the channel layout properties on the track OSErr err = QTSetTrackProperty(inTrack, kQTPropertyClass_Audio, kQTAudioPropertyID_ChannelLayout, trackChannelLayoutSize, trackChannelLayout ); assert(err == noErr); free((void *)trackChannelLayout); } My Speaker Assignments Do Not WorkIf you've followed the above steps but your channel & speaker assignments still do not work correctly you should verify the actual speaker assignments on your computer. For example, if you have a 5.1 audio speaker system check to see that your audio device is set up such that the speaker assignments are really L, R, C, LFE, Ls, Rs. To configure audio input and output devices on Macintosh, use the Audio Midi Setup application (see /Applications/Utilities/Audio MIDI Setup). To configure audio input and output devices on Windows, use the Sounds and Audio Devices Control Panel. ReferencesCore Audio Data Types Reference QTAudioExtractionPanel sample code Document Revision History
Posted: 2008-11-05 |
|