LB Booster
« Recwave "talking.wav", 44100 / Stoprec »

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



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 2  Notify Send Topic Print
 veryhotthread  Author  Topic: Recwave "talking.wav", 44100 / Stoprec  (Read 3174 times)
James
New Member
Image


member is offline

Avatar




PM


Posts: 42
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #16 on: Aug 11th, 2014, 4:11pm »

Wow, Mr. Russel, this seems to work fine! Sorry for the delay, I was finally able to test it on something besides XP. That would be great if we could use this ability in Liberty Basic!
« Last Edit: Aug 11th, 2014, 4:14pm by James » User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #17 on: Aug 14th, 2014, 1:33pm »

on Aug 11th, 2014, 4:11pm, James wrote:
That would be great if we could use this ability in Liberty Basic!

One of the problems is that the BBC BASIC code uses an array-of-structures, and sadly Liberty BASIC doesn't support arrays of structures. sad

If I get a chance I will look into the possibility of using a kludge to resolve this issue.

Richard.
User IP Logged

James
New Member
Image


member is offline

Avatar




PM


Posts: 42
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #18 on: Aug 15th, 2014, 06:24am »

Thanks very much! grin
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #19 on: Aug 15th, 2014, 12:04pm »

Try this. It records 44100 Hz stereo to a WAV file; I've tested it with LBB 2.64 on Windows XP, 7 and 8.1. There is no source selection or setting of level, you will need to do that in Control Panel (Sound... Recording...). If you develop this into something amazing, I would appreciate an acknowledgement of my contribution. Enjoy!

Code:
    ' Audio recorder (c) Richard Russell, 15-Aug-2014
    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 

Richard.
User IP Logged

James
New Member
Image


member is offline

Avatar




PM


Posts: 42
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #20 on: Aug 24th, 2014, 3:21pm »

Thank you very much!
User IP Logged

James
New Member
Image


member is offline

Avatar




PM


Posts: 42
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #21 on: Aug 24th, 2014, 3:50pm »

Mr. Russell, can I post this code in the LB forum? Can people use it in their LB 4.04 programs? smiley
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #22 on: Aug 24th, 2014, 4:28pm »

on Aug 24th, 2014, 3:50pm, James wrote:
can I post this code in the LB forum? Can people use it in their LB 4.04 programs? smiley

As it stands it's not fully compatible with LB 4.04. There are a few changes that would need to be made:
  1. It uses some Windows Constants that LB 4.04 doesn't know about. You would need to replace them with numbers or global variables.

  2. It uses TIMER with a SUB. Although the LB docs describe this usage, there's a bug in LB 4.04 which means you have to use a branch label instead.

  3. It uses the HWND() function with a file, rather than with a window. This is an LBB extension to the language so doesn't work in LB 4.04.
If you can fix those incompatibilities then of course it's OK to post it so long as it retains the copyright notice.

Richard.
User IP Logged

James
New Member
Image


member is offline

Avatar




PM


Posts: 42
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #23 on: Aug 25th, 2014, 5:59pm »

Code:
   ' Audio recorder (c) Richard Russell, 15-Aug-2014
    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, [recordpoll]
    wait

[quit]
    timer 0
    call record.exit
    close #w
    end


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

    WAVEFORMATPCM = hexdec("0x0001") '_WAVE_FORMAT_PCM

    waveFormatEx.wFormatTag.struct = WAVEFORMATPCM
    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

    WAVEMAPPER = hexdec("0xFFFFFFFF") '_WAVE_MAPPER

    struct WaveIn, hndl as ulong
    calldll #winmm, "waveInOpen", WaveIn as struct, WAVEMAPPER 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

[recordpoll]
    WHDRDONE = 1 '_WHDR_DONE
    header = Headers(record.buff)
    WAVEHDR.struct = header
    if WAVEHDR.dwFlags.struct and WHDRDONE then
        WAVEHDR.dwFlags.struct = WAVEHDR.dwFlags.struct and (WHDRDONE-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
wait

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
 


This is as far as I've got...
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #24 on: Aug 26th, 2014, 10:13am »

on Aug 25th, 2014, 5:59pm, James wrote:
This is as far as I've got...

Yes, the hwnd(#recordfile) is the tricky thing to workaround in order to make it LB 4.04 compatible (that's assuming it would run fast enough in LB). One possible solution might be to use the fact that LB's structures are effectively strings, so you can do things like:

Code:
    test$ = test.struct 

(it doesn't look as though it should work, but it does).

Using that technique it might be possible to eliminate the WriteFile API call and thus lose the HWND() too.

But I'm not motivated to work it out in detail, because I want people to use LBB; making my programs compatible with LB 4.04 is hardly in my best interests! I'd rather you posted my original code to the LB forum with a note saying that it only runs in LBB, but we all know what would happen if you did....

Richard.
User IP Logged

James
New Member
Image


member is offline

Avatar




PM


Posts: 42
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #25 on: Aug 26th, 2014, 5:26pm »

Well, you have helped us with LBB and I now want to appreciate you taking the time to write this code. Thank you very much for your work! smiley
User IP Logged

James
New Member
Image


member is offline

Avatar




PM


Posts: 42
xx Re: Recwave "talking.wav", 44100 / Stopr
« Reply #26 on: Aug 1st, 2017, 09:31am »

Hi, Mr. Russel,

If someone wants to use/modify your wave recording code, they just have to say in their code:

Base wave code courtesy of Richard Russel, copyright owned by him

Right?

-Thanks
James

User IP Logged

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

| |

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