/'===============================================================================================
 Record to disk example
 Copyright (c), Firelight Technologies Pty, Ltd 2004-2011.

 This example shows how to do a streaming record to disk.
==============================================================================================='/
#include "windows.bi"
#include "win/mmsystem.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

/'
[
	[DESCRIPTION]
	Writes out the contents of a record buffer to a file.

	[PARAMETERS]
 
	[RETURN_VALUE]
	void

	[REMARKS]
]
'/
sub WriteWavHeader(byval fp as FILE ptr, byval sound as FMOD_SOUND ptr, byval length as integer)
    dim as integer             channels = any, bits = any
    dim as float           rate = any

    if (sound) = 0 then
        return
    end if

    fseek(fp, 0, SEEK_SET)

    FMOD_Sound_GetFormat  (sound, 0, 0, @channels, @bits)
    FMOD_Sound_GetDefaults(sound, @rate, 0, 0, 0)

    scope
        
        /'
            WAV Structures
        '/
        type RIFFCHUNK field = 4
	        as byte id(0 to 3)
	        as integer 		size
        end type
    
        type FMTCHUNK field = 4
            as RIFFCHUNK       chunk
            as ushort	wFormatTag      /' format type  '/
            as ushort	nChannels       /' number of channels (i.e. mono, stereo...)  '/
            as uinteger	nSamplesPerSec  /' sample rate  '/
            as uinteger	nAvgBytesPerSec /' for buffer estimation  '/
            as ushort	nBlockAlign     /' block size of data  '/
            as ushort	wBitsPerSample  /' number of bits per sample of mono data '/
        end type 

        type DATACHUNK field = 4
            as RIFFCHUNK   chunk
        end type

        type WAVHEADER field = 4
            as RIFFCHUNK   chunk
	        as byte rifftype(0 to 3)
        end type

    dim as FMTCHUNK FmtChunk = _
    type( ({asc("f"),asc("m"),asc("t"),asc(" ")}, sizeof(FMTCHUNK) - sizeof(RIFFCHUNK) ), _
    1, channels, rate, rate * channels * bits / 8, 1 * channels * bits / 8, bits )

    dim as DATACHUNK DataChunk = type( ({asc("d"),asc("a"),asc("t"),asc("a")}, length ) )

    dim as WAVHEADER WavHeader = _
    type( ({asc("R"),asc("I"),asc("F"),asc("F")}, sizeof(FMTCHUNK) + sizeof(RIFFCHUNK) + length ), _
    {asc("W"),asc("A"),asc("V"),asc("E")} )
      
        /'
            Write out the WAV header.
        '/
        fwrite(@WavHeader, sizeof(WAVHEADER), 1, fp)
        fwrite(@FmtChunk, sizeof(FMTCHUNK), 1, fp)
        fwrite(@DataChunk, sizeof(DATACHUNK), 1, fp)
    end scope
end sub


' program start
    dim as FMOD_SYSTEM          ptr fsystem  = 0
    dim as FMOD_SOUND           ptr sound   = 0
    dim as FMOD_RESULT            result = any
    dim as FMOD_CREATESOUNDEXINFO exinfo
    dim as string                    key
    dim as integer recorddriver = any, numdrivers = any, count = any
    dim as uinteger           version = any
    dim as FILE                  ptr fp = any
    dim as uinteger           datalength = 0, soundlength = 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

    /' 
        System initialization
    '/
    printf(!"---------------------------------------------------------\n")    
    printf(!"Select OUTPUT type\n")    
    printf(!"---------------------------------------------------------\n")    
    printf(!"1 :  DirectSound\n")
    printf(!"2 :  Windows Multimedia WaveOut\n")
    printf(!"3 :  ASIO\n")
    printf(!"---------------------------------------------------------\n")
    printf(!"Press a corresponding number or ESC to quit\n")

    do
        key = inkey
sleep 10
        loop while (key <> chr(27) and key < "1")
    
    select case key
        case "1" :  result = FMOD_System_SetOutput(fsystem, FMOD_OUTPUTTYPE_DSOUND)
        case "2" :  result = FMOD_System_SetOutput(fsystem, FMOD_OUTPUTTYPE_WINMM)
        case "3" :  result = FMOD_System_SetOutput(fsystem, FMOD_OUTPUTTYPE_ASIO)
        case else  :  end 1 
    end select
    ERRCHECK(result)
    
    /'
        Enumerate record devices
    '/

    result = FMOD_System_GetRecordNumDrivers(fsystem, @numdrivers)
    ERRCHECK(result)

    printf(!"---------------------------------------------------------\n")    
    printf(!"Choose a RECORD driver\n")
    printf(!"---------------------------------------------------------\n")    
    for count=0 to numdrivers-1
        dim as zstring * 256 sname = any

        result = FMOD_System_GetRecordDriverInfo(fsystem, count, @sname, 256, 0)
        ERRCHECK(result)

        printf(!"%d : %s\n", count + 1, sname)
    next
    printf(!"---------------------------------------------------------\n")
    printf(!"Press a corresponding number or ESC to quit\n")

    recorddriver = 0
    do
        key = inkey
        if (key = chr(27)) then
            end 0
        end if
        recorddriver = asc(key) - asc("1")
sleep 10
     loop while (recorddriver < 0 or recorddriver >= numdrivers)

    printf(!"\n")
  
    result = FMOD_System_Init(fsystem, 32, FMOD_INIT_NORMAL, 0)
    ERRCHECK(result)

    exinfo.cbsize           = sizeof(FMOD_CREATESOUNDEXINFO)
    exinfo.numchannels      = 2
    exinfo.format           = FMOD_SOUND_FORMAT_PCM16
    exinfo.defaultfrequency = 44100
    exinfo.length           = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * 2
    
    result = FMOD_System_CreateSound(fsystem, 0, FMOD_2D or FMOD_SOFTWARE or FMOD_OPENUSER, @exinfo, @sound)
    ERRCHECK(result)

    printf(!"========================================================================\n")
    printf(!"Record to disk example.  Copyright (c) Firelight Technologies 2004-2011.\n")
    printf(!"========================================================================\n")
    printf(!"\n")
    printf(!"Press any key to start recording to record.wav\n")
    printf(!"\n")

    sleep

    result = FMOD_System_RecordStart(fsystem, recorddriver, sound, TRUE)
    ERRCHECK(result)

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

    fp = fopen("record.wav", "wb")
    if (fp) = 0 then
        printf(!"ERROR : could not open record.wav for writing.\n")
        end 1
    end if

    /'
        Write out the wav header.  As we don't know the length yet it will be 0.
    '/
    WriteWavHeader(fp, sound, datalength)

    result = FMOD_Sound_GetLength(sound, @soundlength, FMOD_TIMEUNIT_PCM)
    ERRCHECK(result)

    /'
        Main loop.
    '/
    do
        static as uinteger lastrecordpos = 0
        dim as uinteger recordpos = 0

            key = inkey

        FMOD_System_GetRecordPosition(fsystem, recorddriver, @recordpos)
        ERRCHECK(result)

        if (recordpos <> lastrecordpos) then
            dim as any  ptr ptr1 = any, ptr2 = any
            dim as integer blocklength = any
            dim as uinteger len1 = any, len2 = any
            
            blocklength = recordpos - lastrecordpos
            if (blocklength < 0) then
                blocklength += soundlength
            end if

            /'
                Lock the sound to get access to the raw data.
            '/
            FMOD_Sound_Lock(sound, lastrecordpos * exinfo.numchannels * 2, blocklength * exinfo.numchannels * 2, @ptr1, @ptr2, @len1, @len2)   /' * exinfo.numchannels * 2 = stereo 16bit.  1 sample = 4 bytes. '/

            /'
                Write it to disk.
            '/
            if (ptr1 andalso len1) then
                datalength += fwrite(ptr1, 1, len1, fp)
            end if
            if (ptr2 andalso len2) then
                datalength += fwrite(ptr2, 1, len2, fp)
            end if

            /'
                Unlock the sound to allow FMOD to use it again.
            '/
            FMOD_Sound_Unlock(sound, ptr1, ptr2, len1, len2)
        end if

        lastrecordpos = recordpos

        printf(!"%-23s. Record buffer pos = %6d : Record time = %02d:%02d\r", iif((timeGetTime() \ 500) and 1,@"Recording to record.wav",@""), _
recordpos, datalength \ exinfo.defaultfrequency \ exinfo.numchannels \ 2 \ 60, (datalength \ exinfo.defaultfrequency \ exinfo.numchannels \ 2) mod 60)

        FMOD_System_Update(fsystem)

        Sleep(10)

    loop while (key <> chr(27))

    printf(!"\n")

    /'
        Write back the wav header now that we know its length.
    '/
    WriteWavHeader(fp, sound, datalength)

    fclose(fp)

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

    result = FMOD_System_Release(fsystem)
    ERRCHECK(result)
