/'===============================================================================================
 Custom DSP Example
 Copyright (c), Firelight Technologies Pty, Ltd 2004-2011.

 This example shows how to add a user created DSP callback to process audio data.
 A read callback is generated at runtime, and can be added anywhere in the DSP network.

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


function myDSPCallback(byval dsp_state as FMOD_DSP_STATE ptr, byval inbuffer as float ptr, byval outbuffer as float ptr, byval length as uinteger, byval inchannels as integer, byval outchannels as integer) as FMOD_RESULT
    dim as uinteger count = any, userdata = any
    dim as integer count2 = any
    dim as zstring * 256 name_ = any
    dim as FMOD_DSP ptr thisdsp = dsp_state->instance 

    /' 
        This redundant call just shows using the instance parameter of FMOD_DSP_STATE and using it to 
        call a DSP information function. 
    '/
    FMOD_DSP_GetInfo(thisdsp, name_, 0, 0, 0, 0)

    FMOD_DSP_GetUserData(thisdsp, @userdata)

    /'
        This loop assumes inchannels = outchannels, which it will be if the DSP is created with '0' 
        as the number of channels in FMOD_DSP_DESCRIPTION.  
        Specifying an actual channel count will mean you have to take care of any number of channels coming in,
        but outputting the number of channels specified.  Generally it is best to keep the channel 
        count at 0 for maximum compatibility.
    '/
    for count = 0 to length-1
        /'
            Feel free to unroll this.
        '/
        for count2 = 0 to outchannels-1
            /' 
                This DSP filter just halves the volume! 
                Input is modified, and sent to output.
            '/
            outbuffer[(count * outchannels) + count2] = inbuffer[(count * inchannels) + count2] * 0.2f
next
next

    return FMOD_OK 
end function


' program start
    dim as FMOD_SYSTEM ptr fsystem = any
    dim as FMOD_SOUND ptr sound = any
    dim as FMOD_CHANNEL  ptr channel = any
    dim as FMOD_DSP ptr mydsp = any
    dim as FMOD_RESULT result = any
    dim as string key
    dim as integer version = any
    dim as float pan = 0

    /'
        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, 0)
    ERRCHECK(result)

    result = FMOD_System_CreateSound(fsystem, "media/drumloop.wav", FMOD_SOFTWARE or FMOD_LOOP_NORMAL, 0, @sound)
    ERRCHECK(result)

    printf(!"===============================================================================\n")
    printf(!"Custom DSP example. Copyright (c) Firelight Technologies 2004-2011.\n")
    printf(!"===============================================================================\n")
    printf(!"Press 'f' to activate, deactivate user filter\n")
    printf(!"Press 'Esc' to quit\n")
    printf(!"\n")

    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, sound, FALSE, @channel)
    ERRCHECK(result)

    /'
        Create the DSP effects.
    '/  
    scope
        dim as FMOD_DSP_DESCRIPTION  dspdesc

        strcpy(dspdesc.name, "My first DSP unit") 
        dspdesc.channels     = 0                   ' 0 = whatever comes in, else specify. 
        dspdesc.read         = @myDSPCallback 
        dspdesc.userdata     = cast(any ptr,&h12345678)

        result = FMOD_System_CreateDSP(fsystem, @dspdesc, @mydsp) 
        ERRCHECK(result) 
    end scope

    /'
        Inactive by default.
    '/
    FMOD_DSP_SetBypass(mydsp, TRUE)

    /'
        Main loop.
    '/
    result = FMOD_System_AddDSP(fsystem, mydsp, 0) 


    /'
        Main loop.
    '/
    do
key = inkey
select case key
                case "f","F" : 
                    static as integer active = FALSE

                    FMOD_DSP_SetBypass(mydsp, active)

                    active xor= 1
end select

        FMOD_System_Update(fsystem)

        Sleep(10)

    loop while (key <> chr(27))

    printf(!"\n")

    /'
        Shut down
    '/
    result = FMOD_Sound_Release(sound)
    ERRCHECK(result)

    result = FMOD_DSP_Release(mydsp)
    ERRCHECK(result)

    result = FMOD_System_Close(fsystem)
    ERRCHECK(result)
    result = FMOD_System_Release(fsystem)
    ERRCHECK(result)
