Author |
Topic: Recwave "talking.wav", 44100 / Stoprec (Read 3174 times) |
|
James
New Member
member is offline


Posts: 42
|
 |
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 » |
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
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. 
If I get a chance I will look into the possibility of using a kludge to resolve this issue.
Richard.
|
|
Logged
|
|
|
|
James
New Member
member is offline


Posts: 42
|
 |
Re: Recwave "talking.wav", 44100 / Stopr
« Reply #18 on: Aug 15th, 2014, 06:24am » |
|
Thanks very much!
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
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.
|
|
Logged
|
|
|
|
James
New Member
member is offline


Posts: 42
|
 |
Re: Recwave "talking.wav", 44100 / Stopr
« Reply #20 on: Aug 24th, 2014, 3:21pm » |
|
Thank you very much!
|
|
Logged
|
|
|
|
James
New Member
member is offline


Posts: 42
|
 |
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?
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
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? |
|
As it stands it's not fully compatible with LB 4.04. There are a few changes that would need to be made:
It uses some Windows Constants that LB 4.04 doesn't know about. You would need to replace them with numbers or global variables.
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.
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.
|
|
Logged
|
|
|
|
James
New Member
member is offline


Posts: 42
|
 |
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...
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
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: (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.
|
|
Logged
|
|
|
|
James
New Member
member is offline


Posts: 42
|
 |
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!
|
|
Logged
|
|
|
|
James
New Member
member is offline


Posts: 42
|
 |
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
|
|
Logged
|
|
|
|
|