/'===============================================================================================
 Load from memory example
 Copyright (c), Firelight Technologies Pty, Ltd 2004-2011.

 This example is simply a variant of the play sound example, but it loads the data into memory
 then uses the 'load from memory' feature of System::createSound.
==============================================================================================='/
#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

sub LoadFileIntoMemory(byval fname as zstring ptr, byval buff as any ptr ptr, byval length as integer ptr)
    dim as FILE ptr fp = fopen(fname, "rb")
    
    fseek(fp, 0, SEEK_END)
    *length = ftell(fp)
    fseek(fp, 0, SEEK_SET)
    
    *buff = allocate(*length)
    fread(*buff, *length, 1, fp)
    
    fclose(fp)
end sub

' program start
    dim as FMOD_SYSTEM      ptr fsystem = any
    dim as FMOD_SOUND       ptr sound1 = any, sound2 = any, sound3 = any
    dim as FMOD_CHANNEL     ptr channel = 0
    dim as FMOD_RESULT       result = any
    dim as string key
    dim as uinteger      version = any
    dim as any              ptr buff = 0
    dim as integer               length = 0
    dim as FMOD_CREATESOUNDEXINFO exinfo

    /'
        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

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

    LoadFileIntoMemory("media/drumloop.wav", @buff, @length)

    exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO)
    exinfo.length = length

    result = FMOD_System_CreateSound(fsystem, buff, FMOD_HARDWARE or FMOD_OPENMEMORY, @exinfo, @sound1)
    ERRCHECK(result)

    result = FMOD_Sound_SetMode(sound1, FMOD_LOOP_OFF)
    ERRCHECK(result)

    deallocate(buff) ' don't need the original memory any more.  Note!  If loading as a stream, the memory must stay active so do not free it!

    LoadFileIntoMemory("media/jaguar.wav", @buff, @length)
    clear(exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO))
    exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO)
    exinfo.length = length    

    result = FMOD_System_CreateSound(fsystem, buff, FMOD_SOFTWARE or FMOD_OPENMEMORY, @exinfo, @sound2)
    ERRCHECK(result)

    deallocate(buff) ' don't need the original memory any more.  Note!  If loading as a stream, the memory must stay active so do not free it!

    LoadFileIntoMemory("media/swish.wav", @buff, @length)
    clear(exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO))
    exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO)
    exinfo.length = length    

    result = FMOD_System_CreateSound(fsystem, buff, FMOD_HARDWARE or FMOD_OPENMEMORY, @exinfo, @sound3)
    ERRCHECK(result)

    deallocate(buff) ' don't need the original memory any more.  Note!  If loading as a stream, the memory must stay active so do not free it!

    printf(!"==========================================================================\n")
    printf(!"Load from memory example.  Copyright (c) Firelight Technologies 2004-2011.\n")
    printf(!"==========================================================================\n")
    printf(!"\n")
    printf(!"Press '1' to play a mono sound using hardware mixing\n")
    printf(!"Press '2' to play a mono sound using software mixing\n")
    printf(!"Press '3' to play a stereo sound using hardware mixing\n")
    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, 0, @channel)
                    ERRCHECK(result)
                case "2" :
                    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound2, 0, @channel)
                    ERRCHECK(result)
                case "3" :
                    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound3, 0, @channel)
                    ERRCHECK(result)
        end select

        FMOD_System_Update(fsystem)

        scope
            dim as uinteger ms = 0
            dim as uinteger lenms = 0
            dim as integer          playing = 0
            dim as integer          paused = 0
            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

            result = FMOD_Sound_GetLength(sound1, @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

            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_Sound_Release(sound3)
    ERRCHECK(result)
    result = FMOD_System_Close(fsystem)
    ERRCHECK(result)
    result = FMOD_System_Release(fsystem)
    ERRCHECK(result)
