LB Booster
« waveIn functions »

Welcome Guest. Please Login or Register.
Apr 1st, 2018, 03:47am



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
We apologize Conforums does not have any export functions to migrate data.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

Thank you Conforums members.
Speed up Liberty BASIC programs by up to ten times!
Compile Liberty BASIC programs to compact, standalone executables!
Overcome many of Liberty BASIC's bugs and limitations!
LB Booster Resources
LB Booster documentation
LB Booster Home Page
LB Booster technical Wiki
Just BASIC forum
BBC BASIC Home Page
Liberty BASIC forum (the original)

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: waveIn functions  (Read 96 times)
Phineas Freak
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 18
xx waveIn functions
« Thread started on: Jan 16th, 2018, 07:47am »

So, i have been trying to make a waveIn demo but considering the complexity of the code i surely failed to make it work:

Code:
'   ----------------------------------------------------------------------------------------------------

    '   Setup the global variables.

    hWndDevice = _NULL
    result     = _NULL

'   ----------------------------------------------------------------------------------------------------

    '   Setup the structs.

    struct WAVEHDR,               _
        lpData          as long,  _
        dwBufferLength  as ulong, _
        dwBytesRecorded as ulong, _
        dwUser          as ulong, _
        dwFlags         as ulong, _
        dwLoops         as ulong, _
        lpNext          as long,  _
        reserved        as ulong

    struct WAVEFORMATEX,          _
        wFormatTag      as word,  _
        nChannels       as word,  _
        nSamplesPerSec  as ulong, _
        nAvgBytesPerSec as ulong, _
        nBlockAlign     as word,  _
        wBitsPerSample  as word,  _
        cbSize          as word

'   ----------------------------------------------------------------------------------------------------

    '   Setup the basic recording parameters.

    dwBitsPerSample = 8
    dwChannels      = 1
    dwSamplesPerSec = 22050
    dwTimePeriod    = 1

'   ----------------------------------------------------------------------------------------------------

    '   Calculate the rest of the recording parameters.

    dwBufferLength   = 2 * dwSamplesPerSec * dwTimePeriod
    dwBlockAlign     = (dwChannels * dwBitsPerSample) / 8
    dwAvgBytesPerSec = (dwChannels * dwBitsPerSample *  dwSamplesPerSec) / 8

'   ----------------------------------------------------------------------------------------------------

    '   Create the buffer.

    hMem = GlobalAlloc(_GMEM_ZEROINIT, dwBufferLength)

'   ----------------------------------------------------------------------------------------------------

    '  Specify the recording parameters.

    WAVEFORMATEX.wFormatTag.struct      = _WAVE_FORMAT_PCM
    WAVEFORMATEX.nChannels.struct       = dwChannels
    WAVEFORMATEX.nSamplesPerSec.struct  = dwSamplesPerSec
    WAVEFORMATEX.nAvgBytesPerSec.struct = dwAvgBytesPerSec
    WAVEFORMATEX.nBlockAlign.struct     = dwBlockAlign
    WAVEFORMATEX.wBitsPerSample.struct  = dwBitsPerSample
    WAVEFORMATEX.cbSize.struct          = _NULL

'   ----------------------------------------------------------------------------------------------------

    '   Setup and prepare the input header.

    WAVEHDR.lpData.struct          = GlobalLock(hMem)
    WAVEHDR.dwBufferLength.struct  = dwBufferLength
    WAVEHDR.dwBytesRecorded.struct = _NULL
    WAVEHDR.dwUser.struct          = _NULL
    WAVEHDR.dwFlags.struct         = _NULL
    WAVEHDR.dwLoops.struct         = _NULL

'   ----------------------------------------------------------------------------------------------------

    '   Get the number of sound devices installed.

    result = waveInGetNumDevs()

    if (result = _NULL) then

        null = MessageBoxEx(_NULL, "No waveform audio input devices found!", "Error", _MB_ICONERROR or _MB_OK, _NULL)

        end

    end if

'   ----------------------------------------------------------------------------------------------------

    '   Open the sound device.

    result = waveInOpen(hWndDevice, _WAVE_MAPPER, _NULL, _NULL, _CALLBACK_NULL or _WAVE_FORMAT_DIRECT)

    if (result <> _MMSYSERR_NOERROR) then

        null = MessageBoxEx(_NULL, "Failed to open the waveform audio input device!", "Error", _MB_ICONERROR or _MB_OK, _NULL)

        end

    end if

'   ----------------------------------------------------------------------------------------------------

   '    Prepare the header.

    result = waveInPrepareHeader(hWndDevice, len(WAVEHDR.struct))

    if (result <> _MMSYSERR_NOERROR) then

        null = MessageBoxEx(_NULL, "Failed to prepare a waveform audio header!", "Error", _MB_ICONERROR or _MB_OK, _NULL)        

        end

    end if

'   ----------------------------------------------------------------------------------------------------

    '   Insert the wave input buffer.

    result  = waveInAddBuffer(hWndDevice, len(WAVEHDR.struct))

    if (result <> _MMSYSERR_NOERROR) then

        null = MessageBoxEx(_NULL, "Failed to insert a waveform audio buffer!", "Error", _MB_ICONERROR or _MB_OK, _NULL)        

        end

    end if

'   ----------------------------------------------------------------------------------------------------

    '   Commence the input sampling.

    result = waveInStart(hWndDevice)

    if (result <> _MMSYSERR_NOERROR) then

        null = MessageBoxEx(_NULL, "Failed to start the waveform audio device!", "Error", _MB_ICONERROR or _MB_OK, _NULL)        

        end

    end if

'   ----------------------------------------------------------------------------------------------------

    '   Wait until the buffer is full.

    while ((WAVEHDR.dwFlags.struct and _WHDR_DONE) = _NULL)

        '   Recording is in progress.

        print "Buffer Pointer..." ; WAVEHDR.lpData.struct
        print "Bytes Recorded..." ; WAVEHDR.dwBytesRecorded.struct
        print "Flags............" ; WAVEHDR.dwFlags.struct
        print
        print "Data............." ; winstring(WAVEHDR.lpData.struct)
        print

        '   Minimize CPU usage.

        null = Sleep(100)

    wend

'   ----------------------------------------------------------------------------------------------------

    '   Release the sound device.

    null = GlobalFree(hMem)

    null = waveInUnprepareHeader(hWndDevice, len(WAVEHDR.struct))

    null = waveInClose(hWndDevice)

'   ----------------------------------------------------------------------------------------------------

    print "Done!"

    end
 


As a starting point, i believe that the problematic code is the buffer initialization "routine" (memory allocation). But, i may have failed big time in something much more mundane...
User IP Logged

Phineas Freak
New Member
Image


member is offline

Avatar




PM

Gender: Male
Posts: 18
xx Re: waveIn functions
« Reply #1 on: Jan 16th, 2018, 07:51am »

And the required functions:

Code:
'   ====================================================================================================
'   Function GlobalAlloc()

'   Allocates the specified number of bytes from the heap.
'   ====================================================================================================

    function GlobalAlloc(uFlags, dwBytes)

        calldll #kernel32, "GlobalAlloc", _
            uFlags      as ulong,         _
            dwBytes     as ulong,         _
            GlobalAlloc as handle        

    end function

'   ====================================================================================================
'   Function GlobalFree()

'   Frees the specified global memory object and invalidates its handle.
'   ====================================================================================================

    function GlobalFree(hMem)

        calldll #kernel32, "GlobalFree", _
            hMem       as handle,        _
            GlobalFree as handle

    end function

'   ====================================================================================================
'   Function GlobalLock()

'   Locks a global memory object and returns a pointer to the first byte of the object's memory block.
'   ====================================================================================================

    function GlobalLock(hMem)

        calldll #kernel32, "GlobalLock", _
            hMem       as handle,        _
            GlobalLock as long

    end function

'   ====================================================================================================
'   Function MessageBoxEx()

'   Creates, displays, and operates a message box. The message box contains an
'   application-defined message and title, plus any combination of predefined icons
'   and push buttons. The buttons are in the language of the system user interface.
'   ====================================================================================================

    function MessageBoxEx(hWnd, lpText$, lpCaption$, uType, wLanguage)

        calldll #user32, "MessageBoxExA", _
            hWnd         as handle,       _
            lpText$      as ptr,          _
            lpCaption$   as ptr,          _
            uType        as ulong,        _
            wLanguage    as word,         _
            MessageBoxEx as long

    end function

'   ====================================================================================================
'   Function Sleep()

'   Suspends the execution of the current thread until the time-out interval elapses.
'   ====================================================================================================

    function Sleep(dwMilliseconds)

        calldll #kernel32, "Sleep",  _
            dwMilliseconds as ulong, _
            _NULL          as void

    end function

'   ====================================================================================================
'   Function waveInAddBuffer()

'   Sends an input buffer to the given waveform-audio input device. When the buffer is filled, the
'   application is notified.
'   ====================================================================================================

    function waveInAddBuffer(hwi, cbwh)

        calldll #winmm, "waveInPrepareHeader", _
            hwi             as handle,         _
            WAVEHDR         as struct,         _
            cbwh            as ulong,          _
            waveInAddBuffer as ulong

    end function

'   ====================================================================================================
'   Function waveInClose()

'   Closes the given waveform-audio input device.
'   ====================================================================================================

    function waveInClose(hwi)

        calldll #winmm, "waveInClose", _
            hwi         as handle,     _
            waveInClose as ulong

    end function

'   ====================================================================================================
'   Function waveInGetNumDevs()

'   Returns the number of waveform-audio input devices present in the system.
'   ====================================================================================================

    function waveInGetNumDevs()

        calldll #winmm, "waveInGetNumDevs", _
            waveInGetNumDevs as ulong

    end function

'   ====================================================================================================
'   Function waveInGetErrorText()

'   Retrieves a textual description of the error identified by the given error number.
'   ====================================================================================================

    function waveInGetErrorText$(mmrError)

        cchText  = 256
        pszText$ = space$(cchText)

        calldll #winmm, "waveInGetErrorText", _
            mmrError           as ulong,      _
            pszText$           as ptr,        _
            cchText            as ulong,      _
            waveInGetErrorText as ulong

        if (waveInGetErrorText = _MMSYSERR_NOERROR) then waveInGetErrorText$ = trim$(pszText$)

    end function

'   ====================================================================================================
'   Function waveInOpen()

'   Opens the given waveform-audio input device for recording.
'   ====================================================================================================

    function waveInOpen(byref phwi, uDeviceID, dwCallback, dwCallbackInstance, fdwOpen)

        struct WAVEIN, _
            phwi$ as ptr

        WAVEIN.phwi$.struct = space$(8)

        calldll #winmm, "waveInOpen",     _
            WAVEIN             as struct, _
            uDeviceID          as ulong,  _
            WAVEFORMATEX       as struct, _
            dwCallback         as ulong,  _
            dwCallbackInstance as ulong,  _
            fdwOpen            as ulong,  _
            waveInOpen         as ulong

        if (waveInOpen = _MMSYSERR_NOERROR) then phwi = WAVEIN.phwi$.struct else phwi = _NULL

    end function

'   ====================================================================================================
'   Function waveInPrepareHeader()

'   Prepares a buffer for waveform-audio input.
'   ====================================================================================================

    function waveInPrepareHeader(hwi, cbwh)

        calldll #winmm, "waveInPrepareHeader", _
            hwi                 as handle,     _
            WAVEHDR             as struct,     _
            cbwh                as ulong,      _
            waveInPrepareHeader as ulong

    end function

'   ====================================================================================================
'   Function waveInReset()

'   Stops input on the given waveform-audio input device and resets the current position to zero. All
'   pending buffers are marked as done and returned to the application.
'   ====================================================================================================

    function waveInReset(hwi)

        calldll #winmm, "waveInReset", _
            hwi         as handle,     _
            waveInReset as ulong

    end function

'   ====================================================================================================
'   Function waveInStart()

'   Starts input on the given waveform-audio input device.
'   ====================================================================================================

    function waveInStart(hwi)

        calldll #winmm, "waveInStart", _
            hwi         as handle,     _
            waveInStart as ulong

    end function

'   ====================================================================================================
'   Function waveInStop()

'   Stops waveform-audio input.
'   ====================================================================================================

    function waveInStop(hwi)

        calldll #winmm, "waveInStop", _
            hwi        as handle,     _
            waveInStop as ulong

    end function

'   ====================================================================================================
'   Function waveInUnprepareHeader()

'   Cleans up the preparation performed by the waveInPrepareHeader function. This function must be
'   called after the device driver fills a buffer and returns it to the application. You must call this
'   function before freeing the buffer.
'   ====================================================================================================

    function waveInUnprepareHeader(hwi, cbwh)

        calldll #winmm, "waveInUnprepareHeader", _
            hwi                   as handle,     _
            WAVEHDR               as struct,     _
            cbwh                  as ulong,      _
            waveInUnprepareHeader as ulong

    end function
 
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: waveIn functions
« Reply #2 on: Jan 16th, 2018, 08:15am »

on Jan 16th, 2018, 07:47am, Phineas Freak wrote:
So, i have been trying to make a waveIn demo but considering the complexity of the code i surely failed to make it work

In case it helps, here again is the listing of my Audio Recorder program. This was originally written for LB, so contains code to fake an array of structures (which of course LBB supports natively).

Richard.

Code:
    nomainwin
    global record.flag, record.buff, wavfile$

    filedialog "Save WAV file", "*.wav", wavfile$
    if wavfile$ = "" then end

    button #w.start, "Start Recording", startrec, UL, 100, 100
    button #w.stop, "Stop Recording", stoprec, UL, 100, 200
    open "Audio recorder" for window as #w
    #w "trapclose quit"
    #w.stop "!disable"
    call record.init
    timer 50, record.poll
    wait

sub quit handle$
    timer 0
    call record.exit
    close #w
    end
end sub

sub startrec handle$
    #w.start "!disable"
    #w.stop "!enable"
    call record.start wavfile$
end sub

sub stoprec handle$
    call record.stop
    #w.stop "!disable"
    #w.start "!enable"
end sub

sub record.init
    ' Initialise the wave input format:
    struct waveFormatEx, _
        wFormatTag as word, nChannels as word, nSamplesPerSec as ulong, _
        nAvgBytesPerSec as ulong, nBlockAlign as word, _
        wBitsPerSample as word, cbSize as word

    waveFormatEx.wFormatTag.struct = _WAVE_FORMAT_PCM
    waveFormatEx.nChannels.struct = 2 
    waveFormatEx.nSamplesPerSec.struct = 44100
    waveFormatEx.wBitsPerSample.struct = 16
    waveFormatEx.nBlockAlign.struct = waveFormatEx.nChannels.struct * waveFormatEx.wBitsPerSample.struct / 8
    waveFormatEx.nAvgBytesPerSec.struct = waveFormatEx.nSamplesPerSec.struct * waveFormatEx.nBlockAlign.struct

    ' Create wave headers:
    struct WAVEHDR, lpData as ulong, dwBufferLength as ulong, _
        dwBytesRecorded as ulong, dwUser as ulong, dwFlags as ulong, _
        dwLoops as ulong, lpNext as ulong, Reserved as ulong

    ' Fill in wave headers, allocate, prepare and add buffers:
    BytesPerBuffer = 16384

    struct WaveIn, hndl as ulong
    calldll #winmm, "waveInOpen", WaveIn as struct, _WAVE_MAPPER as long, _
        waveFormatEx as struct, 0 as long, 0 as long, _
        0 as long, ret as long
    if ret then notice "waveInOpen failed" : end

    for buff = 0 TO 7
        h = WaveIn.hndl.struct
        l = len(WAVEHDR.struct)

        ' Kludge to fake array of structures:
        calldll #kernel32, "GlobalAlloc", _GMEM_FIXED as long, _
            l as ulong, header as ulong
        calldll #kernel32, "GlobalAlloc", _GMEM_FIXED as long, _
            BytesPerBuffer as ulong, buffer as ulong
        Headers(buff) = header
        WAVEHDR.lpData.struct = buffer
        WAVEHDR.dwBufferLength.struct = BytesPerBuffer
        WAVEHDR.dwFlags.struct = 0
        calldll #kernel32, "RtlMoveMemory", header as ulong, _
            WAVEHDR as struct, l as ulong, ret as long

        calldll #winmm, "waveInPrepareHeader", h as ulong, _
            header as ulong, l as ulong, ret as long
        if ret then notice "waveInPrepareHeader failed" : end
  
        calldll #winmm, "waveInAddBuffer", h as ulong, _
            header as ulong, l as ulong, ret as long
        if ret then notice "waveInAddBuffer failed" : end
      next

      record.buff = 0
      calldll #winmm, "waveInStart", h as ulong, ret as long
      if ret then notice, "waveInStart failed" : end
end sub

sub record.start filename$ 
    open filename$ for output as #recordfile
    format$ = waveFormatEx.struct
    print #recordfile, "RIFF";
    print #recordfile, d4$(0); ' Filled in later
    print #recordfile, "WAVE";
    print #recordfile, "fmt ";
    print #recordfile, d4$(16);
    print #recordfile, left$(format$,16);
    print #recordfile, "data";
    print #recordfile, d4$(0); ' Filled in later
    seek #recordfile, 44
    record.flag = 1
end sub

sub record.stop
    record.flag = 0
    size = lof(#recordfile)
    seek #recordfile, 4
    print #recordfile, d4$(size - 8);
    seek #recordfile, 40
    print #recordfile, d4$(size - 44);    
    seek #recordfile, size
    close #recordfile
end sub

sub record.exit
    h = WaveIn.hndl.struct
    calldll #winmm, "waveInStop", h as ulong, r as long
    calldll #winmm, "waveInReset", h as ulong, r as long
    for i = 0 to 7
        header = Headers(i)
        WAVEHDR.struct = header
        h = WaveIn.hndl.struct
        l = len(WAVEHDR.struct)
        p = WAVEHDR.lpData.struct
        calldll #winmm, "waveInUnprepareHeader", h as ulong, _
            header as ulong, l as ulong, r as long
        calldll #kernel32, "GlobalFree", p as ulong, r as long
        calldll #kernel32, "GlobalFree", header as ulong, r as long
    next i
    calldll #winmm, "waveInClose", h as ulong, r as long
end sub

sub record.poll
    header = Headers(record.buff)
    WAVEHDR.struct = header
    if WAVEHDR.dwFlags.struct and _WHDR_DONE then
        WAVEHDR.dwFlags.struct = WAVEHDR.dwFlags.struct and (-_WHDR_DONE-1)
        if record.flag then
            h = hwnd(#recordfile)
            d = WAVEHDR.lpData.struct
            l = WAVEHDR.dwBytesRecorded.struct
            struct written, n as ulong
            calldll #kernel32, "WriteFile", h as ulong, d as ulong, _
                l as ulong, written as struct, 0 as ulong, r as long
        end if
        h = WaveIn.hndl.struct
        l = len(WAVEHDR.struct)
        calldll #winmm, "waveInAddBuffer", h as ulong, header as ulong, _
            l as ulong, r as long
    record.buff = (record.buff + 1) mod 8
    end if
end sub

function d4$(n)
    a = n mod 256
    n = int(n/256)
    b = n mod 256
    n = int(n/256)
    c = n mod 256
    n = int(n/256)
    d = n mod 256
    d4$ = chr$(a)+chr$(b)+chr$(c)+chr$(d)
end function 
User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls