/'===============================================================================================
 DSP_GAIN.DLL
 Copyright (c), Firelight Technologies Pty, Ltd 2005-2011.

==============================================================================================='/

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

declare function dspcreate  (byval dsp as FMOD_DSP_STATE ptr) as FMOD_RESULT
declare function dsprelease (byval dsp as FMOD_DSP_STATE ptr) as FMOD_RESULT
declare function dspreset   (byval dsp as FMOD_DSP_STATE ptr) as FMOD_RESULT
declare function dspread    (byval dsp 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
declare function dspsetparam(byval dsp as FMOD_DSP_STATE ptr, byval index as integer, byval value as float) as FMOD_RESULT
declare function dspgetparam(byval dsp as FMOD_DSP_STATE ptr, byval index as integer, byval value as float ptr, byval valuestr as zstring ptr) as FMOD_RESULT


/'
    DSP Parameter list.
'/
dim  shared as FMOD_DSP_PARAMETERDESC dspparam(0 to ...) = { _
type (0.0f,     1.0f,   1.0f, "Level",   "%",     @"Gain level") _
}


dim shared as FMOD_DSP_DESCRIPTION dspgaindesc = type( _
    "FMOD gain example", _       ' name
    &h00010000, _                ' version 0xAAAABBBB   A = major, B = minor.
    0, _                         ' 0 = we can filter whatever you throw at us.  To be most user friendly, always write a filter like this.
    @dspcreate, _                 '
    @dsprelease, _                '
    @dspreset, _                  '
    @dspread, _                   '
    0, _                         ' This is for if you want to allow the plugin to seek, which doesnt really make sense in a gain filter so we'll just leave it out.
    1, _                         ' 1 parameter.  "level"
    @dspparam(0), _                  ' pointer to the parameter list definition.
    @dspsetparam, _               '
    @dspgetparam, _               '
    0, _                         ' This is for if you want to pop up a dialog box to configure the plugin.  Not doing that here.
    0, _                         ' This is for if you want to pop up a dialog box to configure the plugin.  Not doing that here.
    0)                          ' This is for if you want to pop up a dialog box to configure the plugin.  Not doing that here.


/'
    FMODGetDSPDescription is mandantory for every fmod plugin.  This is the symbol the registerplugin function searches for.
    Must be declared with F_API to make it export as stdcall.
    MUST BE EXTERN'ED AS C!  C++ functions will be mangled incorrectly and not load in fmod.
'/

function FMODGetDSPDescription stdcall alias "_FMODGetDSPDescription"() as FMOD_DSP_DESCRIPTION ptr export
beep
    function = @dspgaindesc
end function



type dspgain_state
    as float gain
end type


function dspcreate(byval dsp as FMOD_DSP_STATE ptr) as FMOD_RESULT
    dim as dspgain_state ptr state

    /'
        If we were allocating memory for buffers etc, it would be done in this function.
    '/

    state = allocate(sizeof(dspgain_state))
    if (state = 0) then
        return FMOD_ERR_MEMORY
    end if

    state->gain = dspparam(0).defaultval

    dsp->plugindata = state

function = FMOD_OK
end function

function dsprelease(byval dsp as FMOD_DSP_STATE ptr) as FMOD_RESULT
    dim as dspgain_state ptr state = dsp->plugindata

    /'
        If memory was allocated in create, it would be freed in this function.
    '/

    deallocate(state)
    
function = FMOD_OK
end function


function dspreset(byval dsp as FMOD_DSP_STATE ptr) as FMOD_RESULT
    dim as dspgain_state ptr state = dsp->plugindata

    /'
        This callback isnt really needed for a gain filter.  It is used to reset a filter back to 
        it's default state. This is where buffers would be cleared so that the filter is ready for
        reuse.
    '/

function = FMOD_OK
end function


/'
    This callback does the work.  Modify data from inbuffer and send it to outbuffer.
'/
function dspread(byval dsp 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 dspgain_state ptr state = dsp->plugindata
    dim as uinteger count = any
    dim as integer count2 = any
    dim as integer channels = inchannels  ' outchannels and inchannels will always be the same because this is a flexible filter.

    for count = 0 to length-1
        for count2 = 0 to channels-1
            outbuffer[(count * channels) + count2] = inbuffer[(count * channels) + count2] * state->gain
        next
    next

    function = FMOD_OK
end function

/'
    This callback is for when the user sets a parameter.  It is automatically clamped between 0 and 1.
'/
function dspsetparam(byval dsp as FMOD_DSP_STATE ptr, byval index as integer, byval value as float) as FMOD_RESULT
    dim as dspgain_state ptr state = dsp->plugindata

    select case index
        case 0:
            state->gain = value
    end select
    function = FMOD_OK
end function

/'
    This callback is for when the user gets a parameter.  The label for our only parameter is percent, 
    so when the string is requested print it out as 0 to 100.
'/
function dspgetparam(byval dsp as FMOD_DSP_STATE ptr, byval index as integer, byval value as float ptr, byval valuestr as zstring ptr) as FMOD_RESULT
    dim as dspgain_state ptr state = dsp->plugindata

    select case index
        case 0:
            *value = state->gain
            sprintf(valuestr, "%.02f", state->gain * 100.0f)    ' our units are '%', so print it out as 0 to 100.
        end select

    function = FMOD_OK
end function

