Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Windows sound recorder...
#1
Any way to use QM to record with Windows Sound Recorder
run "$system$\sndrec32.exe" "" "" "*" ;;Sound Recorder

I want to record the stereo mix on my computer and save as an MP3 file..

Thanks.
Jimmy Vig
#2
Better download software that can do it, for example Audacity + Lame.
#3
Any way to use http://www.portaudio.com/ in QM?

I need to write a program that will record 10 minute segments continuously to log audio.

Will probably covert files to wav after the file is recorded.

Thanks,
Jimmy Vig
#4
Dll, declarations, sample.


Attached Files
.zip   portaudio_x86.zip (Size: 60.66 KB / Downloads: 359)
#5
To record audio you can use Windows API functions.
Function dlg_wave_meter
Code:
Copy      Help
\Dialog_Editor

;Records audio input (eg microphone) and displays level.

function# hDlg message wParam lParam
if(hDlg) goto messages

if(!ShowDialog("dlg_wave_meter" &dlg_wave_meter 0)) ret

;BEGIN DIALOG
;0 "" 0x90C80A44 0x100 0 0 223 31 "Wave In Level"
;3 Static 0x54000000 0x0 2 2 32 12 "Peak"
;4 msctls_progress32 0x54030000 0x0 36 2 184 12 ""
;6 Static 0x54000000 0x0 2 16 32 12 "Average"
;5 msctls_progress32 0x54030000 0x0 36 16 184 12 ""
;END DIALOG
;DIALOG EDITOR: "" 0x2030205 "*" "" ""

ret
;messages
int- hwi
WAVEHDR- hd

sel message
,case WM_INITDIALOG
,;start recording
,WAVEFORMATEX wf.cbSize=sizeof(wf)
,wf.wFormatTag=WAVE_FORMAT_PCM
,wf.nChannels=1 ;;mono
,wf.nSamplesPerSec=44100
,wf.wBitsPerSample=16
,wf.nBlockAlign=wf.nChannels*wf.wBitsPerSample/8
,wf.nAvgBytesPerSec=wf.nSamplesPerSec*wf.nBlockAlign
,
,int rc=waveInOpen(&hwi WAVE_MAPPER &wf hDlg 0 CALLBACK_WINDOW); if(rc) out "waveInOpen: %i" rc; ret
,
,hd.dwBufferLength=wf.nAvgBytesPerSec/5 ;;5 buffers/s
,hd.lpData=q_malloc(hd.dwBufferLength)
,rc=waveInPrepareHeader(hwi &hd sizeof(hd)); if(rc) out "waveInPrepareHeader: %i" rc; ret
,
,rc=waveInAddBuffer(hwi &hd sizeof(hd)); if(rc) out "waveInAddBuffer: %i" rc; ret
,rc=waveInStart(hwi)
,if(rc) out "waveInStart: %i" rc; ret
,
,case WM_DESTROY
,;stop recording
,waveInStop(hwi)
,rc=waveInUnprepareHeader(hwi &hd sizeof(hd)); if(rc) out "waveInUnprepareHeader: %i" rc
,q_free hd.lpData
,waveInClose(hwi)
,hwi=0
,0
,
,;case MM_WIM_OPEN
,;out "open"
,
,;case MM_WIM_CLOSE
,;out "close"
,
,case MM_WIM_DATA ;;this runs at 5 Hz frequency
,;out "%i %i 0x%X" hd.dwBytesRecorded hd.lpData hd.dwFlags
,if(!hwi or !hd.dwBytesRecorded) ret
,
,int i dc v peak avg nsamples
,word* w=hd.lpData
,nsamples=hd.dwBytesRecorded/2
,
,;calc direct current level, because on some computers it is not 0
,for(i 0 nsamples) dc+ConvertSignedUnsigned(w[i] 2)
,dc/nsamples
,
,;calc peak and average
,for(i 0 nsamples)
,,v=abs(ConvertSignedUnsigned(w[i] 2)-dc)
,,if(v>peak) peak=v
,,avg+v
,;convert to %
,peak=MulDiv(peak 100 0x8000)
,avg=MulDiv(avg/nsamples 100 0x8000)
,if(peak>100) peak=100
,;display
,SendMessage id(4 hDlg) PBM_SETPOS peak 0
,SendMessage id(5 hDlg) PBM_SETPOS avg 0
,
,;continue to record
,rc=waveInAddBuffer(hwi &hd sizeof(hd))
,
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1
#6
How to use Windows API functions to write to a file? Specify length?

Thanks bunches,
Jimmy Vig
#7
Same as with PortAudio. Just data source is different.
#8
I see that portaudio declares how many number of frames totalFrames = numSeconds * sampleRate; to give the length of file

and then to record:
Code:
Copy      Help
/* Write recorded data to a file. */
#if 1
type WAVFILEHEADER _RIFF size _WAVE _fmt_ size1 @audioFormat @nChannels sampleRate byteRate @blockAlign @bitsPerSample _data size2
WAVFILEHEADER h
memcpy &h._RIFF "RIFF" 4
memcpy &h._WAVE "WAVE" 4
memcpy &h._fmt_ "fmt " 4
memcpy &h._data "data" 4
h.size1=16
h.size2=totalFrames*numChannels*sizeof(word)
h.size=36+h.size2
h.audioFormat=1
h.nChannels=numChannels
h.sampleRate=sampleRate
h.byteRate=h.sampleRate*h.nChannels*sizeof(word)
h.blockAlign=h.nChannels*sizeof(word)
h.bitsPerSample=sizeof(word)*8

FILE* fid;
fid = fopen(_s.expandpath("$desktop$\recorded.wav"), "wb");
if(fid == 0)
,out("Could not open file.");
else
,fwrite(+&h sizeof(WAVFILEHEADER) 1 fid)
,fwrite(+data.recordedSamples, numChannels*sizeof(word), totalFrames, fid);
,fclose(fid);
,out("<>Saved to <link>$desktop$\recorded.wav</link>");
#endif

I guess I don't know where I would put this in the dlg_wave_meter to get output a wav file.

Thanks,
Jimmy Vig
#9
Having problems getting port audio to work. I've tried it on two different computers. Is it the computers or is it the audioport, do you think?


Attached Files Image(s)
   
#10
Did not test on XP.
Now fixed.
#11
Can use this class to write wav file.


Attached Files
.qml   WriteWavFile.qml (Size: 2.35 KB / Downloads: 376)
#12
Having trouble figuring out how to call the Write function properly.

Mainly I don't understand which variables actually have the audio data and how to figure out how many frames are there.

Thank you so much for you help with this. It all looks great and perhaps will finally do exactly what I've been trying to figure out.
#13
Function dlg_audio_record
Code:
Copy      Help
\Dialog_Editor

;Records audio input (eg microphone) and saves in file.

function# hDlg message wParam lParam
if(hDlg) goto messages

str controls = "3"
str e3
e3="$desktop$\recorded.wav"
if(!ShowDialog("dlg_audio_record" &dlg_audio_record &controls)) ret

;BEGIN DIALOG
;0 "" 0x90C80A44 0x100 0 0 223 135 "Record Audio"
;4 Static 0x54000000 0x0 2 6 14 10 "File"
;3 Edit 0x54030080 0x200 20 4 200 14 ""
;5 Button 0x54032000 0x0 2 30 48 14 "Record"
;6 Button 0x5C032000 0x0 54 30 48 14 "Stop"
;9 msctls_progress32 0x54030000 0x0 112 30 108 12 ""
;7 Button 0x54032000 0x0 2 50 48 14 "Play"
;8 Button 0x54032000 0x0 54 50 48 14 "Stop"
;1 Button 0x54030001 0x4 120 116 48 14 "OK"
;2 Button 0x54030000 0x4 170 116 48 14 "Cancel"
;END DIALOG
;DIALOG EDITOR: "" 0x2030205 "*" "" ""

ret
;messages
#compile "__WriteWavFile"
WriteWavFile-- t_wav
int-- t_hwi t_nChannels t_sampleRate
ARRAY(WAVEHDR)-- t_a
WAVEHDR& h
int rc i

sel message
,case WM_INITDIALOG
,
,case WM_DESTROY
,if(t_hwi) SendMessage hDlg WM_COMMAND 6 0; 0
,
,;case MM_WIM_OPEN
,;out "open"
,
,;case MM_WIM_CLOSE
,;out "close"
,
,case MM_WIM_DATA
,&h=+lParam
,;out "%i %i %i 0x%X" t_hwi h.dwBytesRecorded h.lpData h.dwFlags
,if(!t_hwi or !h.dwBytesRecorded) ret
,
,;write this buffer to file
,t_wav.Write(+h.lpData h.dwBytesRecorded/2/t_nChannels); err out _error.description
,
,;display peak level
,int dc v peak nsamples
,word* w=h.lpData
,nsamples=h.dwBytesRecorded/2
,;calc direct current level, because on some computers it is not 0
,for(i 0 nsamples) dc+ConvertSignedUnsigned(w[i] 2)
,dc/nsamples
,;calc peak
,for(i 0 nsamples) v=abs(ConvertSignedUnsigned(w[i] 2)-dc); if(v>peak) peak=v
,peak=MulDiv(peak 100 0x8000); if(peak>100) peak=100 ;;%
,SendMessage id(9 hDlg) PBM_SETPOS peak 0
,
,;continue to record
,rc=waveInAddBuffer(t_hwi &h sizeof(h)); if(rc) wave_in_error "waveInAddBuffer" rc
,
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case 5 ;;Record
,if(t_hwi) ret
,
,;you can change these values
,t_nChannels=2 ;;stereo
,t_sampleRate=44100 ;;44.1 kHz
,int nBuffers=4 ;;works with 1 too, but must be at least 2 to record smoothly
,int nBuffersSecond=10 ;;10 buffers/s
,
,t_wav.Begin(_s.getwintext(id(3 hDlg)) t_nChannels t_sampleRate); err out _error.description; ret
,
,WAVEFORMATEX wf.cbSize=sizeof(wf)
,wf.wFormatTag=WAVE_FORMAT_PCM
,wf.nChannels=t_nChannels
,wf.nSamplesPerSec=t_sampleRate
,wf.wBitsPerSample=16
,wf.nBlockAlign=wf.nChannels*wf.wBitsPerSample/8
,wf.nAvgBytesPerSec=t_sampleRate*t_nChannels*2
,
,rc=waveInOpen(&t_hwi WAVE_MAPPER &wf hDlg 0 CALLBACK_WINDOW); if(rc) wave_in_error "waveInOpen" rc; ret
,
,if(!t_a.len) t_a.create(nBuffers)
,for i 0 t_a.len
,,&h=t_a[i]
,,h.dwBufferLength=t_sampleRate*t_nChannels*2/nBuffersSecond
,,h.lpData=q_malloc(h.dwBufferLength)
,,rc=waveInPrepareHeader(t_hwi &h sizeof(h)); if(rc) wave_in_error "waveInPrepareHeader" rc; break
,,rc=waveInAddBuffer(t_hwi &h sizeof(h)); if(rc) wave_in_error "waveInAddBuffer" rc
,
,if(!rc) rc=waveInStart(t_hwi); if(rc) wave_in_error "waveInStart" rc
,
,if(rc) PostMessage hDlg WM_COMMAND 6 0; ret
,
,EnableWindow id(5 hDlg) 0
,EnableWindow id(6 hDlg) 1
,
,case 6 ;;Stop
,if(!t_hwi) ret
,rc=waveInReset(t_hwi); if(rc) wave_in_error "waveInReset" rc
,
,for i 0 t_a.len
,,&h=t_a[i]
,,rc=waveInUnprepareHeader(t_hwi &h sizeof(h)); if(rc) wave_in_error "waveInUnprepareHeader" rc; continue
,,q_free h.lpData; h.lpData=0
,
,rc=waveInClose(t_hwi); if(rc) wave_in_error "waveInClose" rc
,t_hwi=0
,
,EnableWindow id(5 hDlg) 1
,EnableWindow id(6 hDlg) 0
,SendMessage id(9 hDlg) PBM_SETPOS 0 0
,
,t_wav.End; err out _error.description; ret
,out "<>Saved: <link>%s</link>." _s.getwintext(id(3 hDlg))
,
,case 7 ;;Play
,bee _s.getwintext(id(3 hDlg)); err out _error.description
,
,case 8 ;;Stop
,bee ""
,
,case IDOK
,case IDCANCEL
ret 1

Function wave_in_error
Code:
Copy      Help
;/
function $funcName errorCode

str s.all(300)
if(!waveInGetErrorText(errorCode s 300)) s.fix; else s=""
out "%s: error %i, %s" funcName errorCode s

WriteWavFile:
Windows sound recorder...

Converting wav to mp3:
Write MP3 files.
#14
Gintaras,

Everything is turned all the way up on Windows mixer and am using Stereo Mix to record audio on the computer.

dlg_audio_record records choppy. It is leaving out little bits of audio causing zero crossing distortion and an increase in speed (not pitch). The overall amplitude is lower than the original source as well. Fidelity tanks as nBuffersSecond increases.

PortAudio records smoothly, but over all amplitude is fairly low. Fidelity seems a little compromised.

Any ideas on how to fix up dlg_audio_record? or boost the volume on either one?

Thank you so much for all of your help,
jimmy Vig
#15
Need to add more than 1 buffer. Now fixed.
#16
Gintaras,

Absolutely beautiful!

Thank You so much,
Jimmy vig


Forum Jump:


Users browsing this thread: 1 Guest(s)