ASX Version4.20.14

dual_mono_play/main.c

This is an example of how to set up channel mode controls for dual mono playback.All play streams on AudioScience audio adapters play, at a minimum, either mono or stereo files on the same device. Mono playback always converts mono or stereo to a stereo stream of audio. So to play to the right channel, for example, the stereo stream should be converted to have only right channel audio output.

Configuration Steps

The following steps should be performed to set up playback of 4 independent mono streams. We are going to play in the following configuration:

Play 1 -> Line Out 1 Left
Play 2 -> Line Out 1 Right
Play 3 -> Line Out 2 Left
Play 4 -> Line Out 2 Right

Find and set the channel mode controls on Play nodes as follows:

Play 1, Channel Mode = "stereo to left"  -> Line Out 1 Left
Play 2, Channel Mode = "stereo to right" -> Line Out 1 Right
Play 3, Channel Mode = "stereo to left" -> Line Out 2 Left
Play 4, Channel Mode = "stereo to right" -> Line Out 3 Right

The mixer also needs to be adjusted so that Play 1 -> Line Out 1 is set to full volume and Play 2 to Line Out 1 is also set to full volume.

These instructions remain the same whether the functionality is implemented with Microsoft Multimedia waveXXXX() and mixerXXX() calls, HPI or ASX calls.

/* $Header: /home/eliot/asi/repo/cvsrepo/Repository/apps/asx/examples/dual_mono_play/main.c,v 1.2 2009/02/18 20:37:56 as-tfe Exp $ */

/* This examples sets up the playback channel mode controls to support dual mono playback.
*/
#include "stdio.h"
#include "stdlib.h"
#include "asx.h"
#include "asxstring.h"

#define MAX_PLAYS 32

ASX_HANDLE hSystem=0;

int CheckError(ASX_HANDLE hObj, int nLine);
void PrintControlName(ASX_HANDLE hControl);

int main(int argc, char* argv[])
{
    char *pszName;
    ASX_HANDLE hAdapter;
    ASX_HANDLE hMixer;
    ASX_HANDLE hChannelMode[MAX_PLAYS];
    ASX_HANDLE hVolume;
    int nAdapterToUse=0;
    int i,nLen;
    float fVolume[2];

    // create the system
    ASX_System_Create(ASX_SYSTEM_TYPE_HPI,&hSystem);
    CheckError(hSystem, __LINE__);

    // get the adapter
    ASX_System_GetAdapter(hSystem,nAdapterToUse,&hAdapter);
    CheckError(hAdapter, __LINE__);

    ASX_Adapter_GetName(hAdapter,0,0,&nLen);
    CheckError(hAdapter, __LINE__);
    pszName = (char *)malloc(nLen);
    ASX_Adapter_GetName(hAdapter,pszName,nLen,&nLen);
    CheckError(hAdapter, __LINE__);
    printf("Adapter [%d] is %s \n", nAdapterToUse,pszName);

    // get the mixer handle
    ASX_Adapter_GetMixer( hAdapter, &hMixer );
    CheckError(hAdapter, __LINE__);

    // Grab a player's channel mode
    for(i=0; i<MAX_PLAYS; i++)
    {
        // get channel mode object
        ASX_ERROR err = ASX_Mixer_GetControlByNodeTypeAndIndex(
            hMixer,
            asxNODE_PLAYER,i,
            0,0,
            asxCONTROL_CHANNEL_MODE,
            &hChannelMode[i]);
        if(err)     // error will be returned when i > number of plays.
            break;

        CheckError(hMixer, __LINE__);

        // set the channel mode
        if((i&1)==0)
        {   // even
            ASX_ChannelMode_Set( hChannelMode[i], asxCHANNELMODE_STEREOTOLEFT);
            CheckError(hChannelMode[i], __LINE__);
        }
        else
        {   // odd
            ASX_ChannelMode_Set( hChannelMode[i], asxCHANNELMODE_STEREOTORIGHT);
            CheckError(hChannelMode[i], __LINE__);

        }

        // get volume object
        err = ASX_Mixer_GetControlByNodeTypeAndIndex(
            hMixer,
            asxNODE_PLAYER,i,
            asxNODE_LINE_OUT,i/2,
            asxCONTROL_VOLUME,
            &hVolume);
        if(err)     // error will be returned when i > number of plays.
            break;

        CheckError(hMixer, __LINE__);

        ASX_Volume_GetGain( hVolume, fVolume, 2);
        CheckError(hVolume, __LINE__);
        fVolume[i&1] = 0.0;
        ASX_Volume_SetGain( hVolume, fVolume, 2);
        CheckError(hVolume, __LINE__);
    }

    printf("Press ENTER to exit\n");
    getchar();
    ASX_System_Delete(hSystem);
    return 0;
}

void PrintControlName(ASX_HANDLE hControl)
{
    char *pszName;
    int nLen;
    enum asxCONTROL eControl;

    ASX_Control_GetType(hControl, &eControl);
    ASXSTRING_EnumToString(eControl,0,0,&nLen);
    pszName=(char *)malloc(nLen);
    ASXSTRING_EnumToString(eControl,pszName,nLen,&nLen);
    printf("Control : %s\n",pszName);

    free(pszName);
}

int CheckError(ASX_HANDLE hObj, int nLine)
{
    int nError;
    int asxSubSystemErrorCode=0;
    char *pszAsxErrorString;
    char *pszAsxSubSystemErrorString;
    int nLen1,nLen2;

    ASX_Error_GetLast( hObj, &nError, &asxSubSystemErrorCode);
    if(!nError)
        return 0;
    ASX_Error_GetLastString( hObj, 0,0,&nLen1,0,0,&nLen2);
    pszAsxErrorString = (char *)malloc(nLen1);
    pszAsxSubSystemErrorString = (char *)malloc(nLen2);
    ASX_Error_GetLastString( hObj, pszAsxErrorString,nLen1,&nLen1,pszAsxSubSystemErrorString,nLen2,&nLen2);
    printf("Error: #%d, %s - Subsystem Error: #%ld, %s \n",
        nError,
        pszAsxErrorString,
        asxSubSystemErrorCode,
        pszAsxSubSystemErrorString );
    printf("When called from source %s line %d\n",__FILE__,nLine);

    printf("Press ENTER to exit\n");
    getchar();
    free(pszAsxErrorString);
    free(pszAsxSubSystemErrorString);
    ASX_System_Delete(hSystem);
    exit(1);
    return 1;
}