/'===============================================================================================
 Multi Speaker Output Example
 Copyright (c), Firelight Technologies Pty, Ltd 2004-2011.

 This example shows how to play sounds in multiple speakers, and also how to even assign 
 sound subchannels, such as those in a stereo sound to different individual speakers.
==============================================================================================='/
#include "windows.bi"
#include "crt.bi"

#include "fmodex/fmodex.bi"
#include "fmodex/fmod_errors.bi"

sub ERRCHECK(byval result as FMOD_RESULT)
    if (result <> FMOD_OK) then
        printf(!"FMOD error! (%d) %s\n", result, FMOD_ErrorString(result))
        end -1
end if
end sub

' program start
    dim as FMOD_SYSTEM      ptr fsystem = any
    dim as FMOD_SOUND       ptr sound1 = any, sound2 = any
    dim as FMOD_CHANNEL     ptr channel = 0
    dim as FMOD_RESULT       result = any
    dim as FMOD_SPEAKERMODE  speakermode = any
    dim as string               key
    dim as uint      version = any

    /'
        Create a System object and initialize.
    '/
    result = FMOD_System_Create(@fsystem)
    ERRCHECK(result)

    result = FMOD_System_GetVersion(fsystem, @version)
    ERRCHECK(result)

    if (version < FMOD_VERSION) then
        printf(!"Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION)
        end 0
    end if

    /' 
       Choose the speaker mode selected by the Windows control panel.
    '/
    result = FMOD_System_GetDriverCaps(fsystem, 0, 0, 0, @speakermode)
    ERRCHECK(result)

    result = FMOD_System_SetSpeakerMode(fsystem, speakermode)
    ERRCHECK(result)

    result = FMOD_System_Init(fsystem, 32, FMOD_INIT_NORMAL, NULL)
    ERRCHECK(result)

    result = FMOD_System_CreateSound(fsystem, "media/drumloop.wav", FMOD_SOFTWARE or FMOD_2D, 0, @sound1)
    ERRCHECK(result)
    result = FMOD_Sound_SetMode(sound1, FMOD_LOOP_OFF)
    ERRCHECK(result)

    result = FMOD_System_CreateSound(fsystem, "media/stereo.ogg", FMOD_SOFTWARE or FMOD_2D, 0,  @sound2)
    ERRCHECK(result)

    printf(!"==============================================================================\n")
    printf(!"Multi Speaker Output Example.  Copyright (c) Firelight Technologies 2004-2011.\n")
    printf(!"==============================================================================\n")
    printf(!"\n")
    select case speakermode
        case FMOD_SPEAKERMODE_MONO    :
            printf(!"Using control panel speaker mode : MONO.\n")
            printf(!"\n")
            printf(!"Note! This output mode is very limited in its capability.\n")
            printf(!"Most functionality of this demo is only realized with at least FMOD_SPEAKERMODE_QUAD\n")
            printf(!"and above.\n")
        case FMOD_SPEAKERMODE_STEREO  :
            printf(!"Using control panel speaker mode : STEREO.\n")
            printf(!"\n")
            printf(!"Note! This output mode is very limited in its capability.\n")
            printf(!"Most functionality of this demo is only realized with FMOD_SPEAKERMODE_QUAD\n")
            printf(!"and above.\n")
        case FMOD_SPEAKERMODE_QUAD :
            printf(!"Using control panel speaker mode : QUAD.\n")
            printf(!"Side left, side right, center and subwoofer mix will be disabled.\n")
        case FMOD_SPEAKERMODE_SURROUND :
            printf(!"Using control panel speaker mode : SURROUND.\n")
            printf(!"Side left, side right, and subwoofer mix will be disabled.\n")
        case FMOD_SPEAKERMODE_5POINT1 :
            printf(!"Using control panel speaker mode : 5.1 surround.\n")
            printf(!"Side left and right mix will be disabled..\n")
        case FMOD_SPEAKERMODE_7POINT1 :
            printf(!"Using control panel speaker mode : 7.1 surround.\n")
            printf(!"Full capability.\n")
    end select
    printf(!"\n")

    printf(!"Press '1' to play a mono sound on the FRONT LEFT speaker.\n")
    printf(!"Press '2' to play a mono sound on the FRONT RIGHT speaker.\n")

    if (speakermode >= FMOD_SPEAKERMODE_SURROUND) then
        printf(!"Press '3' to play a mono sound on the CENTER speaker.\n")
    else
        printf(!"- CENTER Disabled\n")
    end if

    if (speakermode >= FMOD_SPEAKERMODE_QUAD) then
        printf(!"Press '4' to play a mono sound on the REAR LEFT speaker.\n")
        printf(!"Press '5' to play a mono sound on the REAR RIGHT speaker.\n")
    else
        printf(!"- REAR LEFT Disabled\n")
        printf(!"- REAR RIGHT Disabled\n")
    end if
    if (speakermode >= FMOD_SPEAKERMODE_7POINT1) then
        printf(!"Press '6' to play a mono sound on the SIDE LEFT speaker.\n")
        printf(!"Press '7' to play a mono sound on the SIDE RIGHT speaker.\n")
    else
        printf(!"- SIDE LEFT Disabled\n")
        printf(!"- SIDE RIGHT Disabled\n")
    end if

    printf(!"\n")
    printf(!"Press '8' to play a stereo sound on the front speakers.\n")
    printf(!"Press '9' to play a stereo sound on the front speakers but channel swapped.\n")

    if (speakermode >= FMOD_SPEAKERMODE_SURROUND) then
        printf(!"Press '0' to play the right part of a stereo sound on the CENTER speaker.\n")
    end if

    printf(!"Press 'Esc' to quit\n")
    printf(!"\n")

    /'
        Main loop.
    '/
    do
            key = inkey

            select case key
                case "1" :
                    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound1, TRUE, @channel)
                    ERRCHECK(result)

                    result = FMOD_Channel_SetSpeakerMix(channel, 1.0f, 0, 0, 0, 0, 0, 0, 0)
                    ERRCHECK(result)

                    result = FMOD_Channel_SetPaused(channel, FALSE)
                    ERRCHECK(result)
                case "2" :
                    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound1, TRUE, @channel)
                    ERRCHECK(result)

                    result = FMOD_Channel_SetSpeakerMix(channel, 0, 1.0f, 0, 0, 0, 0, 0, 0)
                    ERRCHECK(result)

                    result = FMOD_Channel_SetPaused(channel, FALSE)
                    ERRCHECK(result)
                case "3" :
                    if (speakermode >= FMOD_SPEAKERMODE_QUAD) then
                        result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound1, TRUE, @channel)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetSpeakerMix(channel, 0, 0, 1.0f, 0, 0, 0, 0, 0)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetPaused(channel, FALSE)
                        ERRCHECK(result)
                    end if
                case "4" :
                    if (speakermode >= FMOD_SPEAKERMODE_QUAD) then
                        result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound1, TRUE, @channel)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetSpeakerMix(channel, 0, 0, 0, 0, 1.0f, 0, 0, 0)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetPaused(channel, FALSE)
                        ERRCHECK(result)
                    end if
                case "5" :
                    if (speakermode >= FMOD_SPEAKERMODE_QUAD) then
                        result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound1, TRUE, @channel)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetSpeakerMix(channel, 0, 0, 0, 0, 0, 1.0f, 0, 0)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetPaused(channel, FALSE)
                        ERRCHECK(result)
                    end if
               case "6" :
                    if (speakermode >= FMOD_SPEAKERMODE_7POINT1) then
                        result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound1, TRUE, @channel)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetSpeakerMix(channel, 0, 0, 0, 0, 0, 0, 1.0f, 0)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetPaused(channel, FALSE)
                        ERRCHECK(result)
                    end if
                case "7" :
                    if (speakermode >= FMOD_SPEAKERMODE_7POINT1) then
                        result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound1, TRUE, @channel)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetSpeakerMix(channel, 0, 0, 0, 0, 0, 0, 0, 1.0f)
                        ERRCHECK(result)

                        result = FMOD_Channel_SetPaused(channel, FALSE)
                        ERRCHECK(result)
                    end if
                case "8" :
                    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound2, TRUE, @channel)
                    ERRCHECK(result)

                    /'
                        By default a stereo sound would play in all right and all left speakers, so this forces it to just the front.
                    '/
                    result = FMOD_Channel_SetSpeakerMix(channel, 1.0f, 1.0f, 0, 0, 0, 0, 0, 0)
                    ERRCHECK(result)

                    result = FMOD_Channel_SetPaused(channel, FALSE)
                    ERRCHECK(result)

                case "9" :
                    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound2, TRUE, @channel)
                    ERRCHECK(result)

                    /'
                        Clear out all speakers first.
                    '/
                    result = FMOD_Channel_SetSpeakerMix(channel, 0, 0, 0, 0, 0, 0, 0, 0)
                    ERRCHECK(result)

                    /'
                        Put the left channel of the sound in the right speaker.
                    '/
                    scope
                        dim as float  levels(2-1) = { 0, 1.0f }    /' This array represents the source stereo sound.  l/r '/

                        result = FMOD_Channel_SetSpeakerLevels(channel, FMOD_SPEAKER_FRONT_LEFT, @levels(0), 2)
                        ERRCHECK(result)
                    end scope
                    /'
                        Put the right channel of the sound in the left speaker.
                    '/
                    scope
                        dim as float  levels(2-1) = { 1.0f, 0 }    /' This array represents the source stereo sound.  l/r '/

                        result = FMOD_Channel_SetSpeakerLevels(channel, FMOD_SPEAKER_FRONT_RIGHT, @levels(0), 2)
                        ERRCHECK(result)
                    end scope

                    result = FMOD_Channel_SetPaused(channel, FALSE)
                    ERRCHECK(result)

                case "0" :
                    if (speakermode >= FMOD_SPEAKERMODE_SURROUND) then  /' All formats that have a center speaker. '/
                        result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound2, TRUE, @channel)
                        ERRCHECK(result)

                        /'
                            Clear out all speakers first.
                        '/
                        result = FMOD_Channel_SetSpeakerMix(channel, 0, 0, 0, 0, 0, 0, 0, 0)
                        ERRCHECK(result)

                        /'
                            Put the right channel of the sound in the center speaker.
                        '/
                        scope
                            dim as float  levels(2-1) = { 0, 1.0f }    /' This array represents the source stereo sound.  l/r '/

                            result = FMOD_Channel_SetSpeakerLevels(channel, FMOD_SPEAKER_FRONT_CENTER, @levels(0), 2)
                            ERRCHECK(result)
                        end scope

                        result = FMOD_Channel_SetPaused(channel, FALSE)
                        ERRCHECK(result)
                    end if
        end select

        FMOD_System_Update(fsystem)

        scope
            dim as uinteger ms = 0
            dim as uinteger lenms = 0
            dim as integer          playing = FALSE
            dim as integer          paused = FALSE
            dim as integer          channelsplaying = 0

            if (channel) then
                dim as FMOD_SOUND ptr currentsound = 0

                result = FMOD_Channel_IsPlaying(channel, @playing)
                if ((result <> FMOD_OK) and (result <> FMOD_ERR_INVALID_HANDLE) and (result <> FMOD_ERR_CHANNEL_STOLEN)) then
                    ERRCHECK(result)
                end if

                result = FMOD_Channel_GetPaused(channel, @paused)
                if ((result <> FMOD_OK) and (result <> FMOD_ERR_INVALID_HANDLE) and (result <> FMOD_ERR_CHANNEL_STOLEN)) then
                    ERRCHECK(result)
                end if

                result = FMOD_Channel_GetPosition(channel, @ms, FMOD_TIMEUNIT_MS)
                if ((result <> FMOD_OK) and (result <> FMOD_ERR_INVALID_HANDLE) and (result <> FMOD_ERR_CHANNEL_STOLEN)) then
                    ERRCHECK(result)
                end if
               
                FMOD_Channel_GetCurrentSound(channel, @currentsound)
                if (currentsound) then
                    result = FMOD_Sound_GetLength(currentsound, @lenms, FMOD_TIMEUNIT_MS)
                    if ((result <> FMOD_OK) and (result <> FMOD_ERR_INVALID_HANDLE) and (result <> FMOD_ERR_CHANNEL_STOLEN)) then
                        ERRCHECK(result)
                    end if
                end if
            end if

            FMOD_System_GetChannelsPlaying(fsystem, @channelsplaying)

            printf(!"Time %02d:%02d:%02d/%02d:%02d:%02d : %s : Channels Playing %2d\r", _
ms \ 1000 \ 60, ms \ 1000 mod 60, ms \ 10 mod 100, lenms \ 1000 \ 60, lenms \ 1000 mod 60, lenms \ 10 mod 100, _
iif(paused,@"Paused ",iif(playing,@"Playing",@"Stopped")), channelsplaying)
        end scope

        Sleep(10)

    loop while (key <> chr(27))

    printf(!"\n")

    /'
        Shut down
    '/
    result = FMOD_Sound_Release(sound1)
    ERRCHECK(result)
    result = FMOD_Sound_Release(sound2)
    ERRCHECK(result)
    result = FMOD_System_Close(fsystem)
    ERRCHECK(result)
    result = FMOD_System_Release(fsystem)
    ERRCHECK(result)
