How to: Pan a Sound

This topic shows you how you can set the output matrix of a mono source voice that outputs to a stereo mastering voice in order to achieve panning between the left and right speakers.

To setup panning

  1. Retrieve the speaker configuration using IXAudio2MasteringVoice::GetChannelMask.

    DWORD dwChannelMask;       
    pMasteringVoice->GetChannelMask( &dwChannelMask );       
    
  2. Create an array to hold the output matrix. The minimum size of the output matrix is the number of channels in the source voice times the number of channels in the output voice. In this case an eight element array will handle a mono voice outputting to any output format up to 7.1 surround sound.

    float outputMatrix[ 8 ];
    for (int i=0; i<8; i++) outputMatrix[i] = 0;
    
  3. Calculate the send levels based on the desired panning between the left and right speakers. In this example, pan values will range from -1 to 1 with -1 indicating all sound to the left speaker and 1 indicating all sound to the right speaker.

    // pan of -1.0 indicates all left speaker, 
    // 1.0 is all right speaker, 0.0 is split between left and right
    float left = 0.5f - pan / 2;
    float right = 0.5f + pan / 2; 
    
  4. Set the output matrix indices corresponding to the left and right speakers with the values calculated in the previous step. The left and right speakers are determined by looking at the channel mask returned by IXAudio2MasteringVoice::GetChannelMask. Since the channels must always be encoded in the order specified on the WAVEFORMATEXTENSIBLE reference page, it is possible to determine the array index corresponding to an individual speaker.

    switch (dwChannelMask)
    {
    case SPEAKER_MONO:
        outputMatrix[0] = 1.0;
        break;
    case SPEAKER_STEREO:
    case SPEAKER_2POINT1:
    case SPEAKER_SURROUND:
        outputMatrix[0] = left;
        outputMatrix[1] = right;
        break;
    case SPEAKER_QUAD:
        outputMatrix[0] = outputMatrix[2] = left;
        outputMatrix[1] = outputMatrix[3] = right;
        break;
    case SPEAKER_4POINT1:
        outputMatrix[ 0 ] = outputMatrix[ 3 ] = left;
        outputMatrix[ 1 ] = outputMatrix[ 4 ] = right;
        break;
    case SPEAKER_5POINT1:
    case SPEAKER_7POINT1:
    case SPEAKER_5POINT1_SURROUND:
        outputMatrix[ 0 ] = outputMatrix[ 4 ] = left;
        outputMatrix[ 1 ] = outputMatrix[ 5 ] = right;
        break;
    case SPEAKER_7POINT1_SURROUND:
        outputMatrix[ 0 ] = outputMatrix[ 4 ] = outputMatrix[ 6 ] = left;
        outputMatrix[ 1 ] = outputMatrix[ 5 ] = outputMatrix[ 7 ] = right;
        break;
    }
    
  5. Apply the output matrix to the originating voice by using IXAudio2Voice::SetOutputMatrix. The originating voice will be either a source voice or a submix voice sending to either a submix voice or a mastering voice. You can get info about the originating and destination voices, like their number of channels, by using IXAudio2Voice::GetVoiceDetails.

    // Assuming pVoice sends to pMasteringVoice
    
    XAUDIO2_VOICE_DETAILS VoiceDetails;
    pVoice->GetVoiceDetails(&VoiceDetails);
    
    XAUDIO2_VOICE_DETAILS MasterVoiceDetails;
    pMasteringVoice->GetVoiceDetails(&MasterVoiceDetails);
    
    pVoice->SetOutputMatrix( NULL, VoiceDetails.InputChannels, MasterVoiceDetails.InputChannels, outputMatrix );
    

XAudio2 Programming Guide

How to: Build a Basic Audio Processing Graph

XAudio2 Volume and Pitch Control