Posts: 1,000
 
	
	
		Any way to use QM to record with Windows Sound Recorder
	
	
	
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		Better download software that can do it, for example Audacity + Lame.
	
	
	
	
	
 
 
	
	
	
		
	Posts: 1,000
 
	
	
		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
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		Dll, declarations, sample.
	
	
Attached Files portaudio_x86.zip  (Size: 60.66 KB / Downloads: 459)
 
	
	
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		To record audio you can use Windows API functions.
Function 
dlg_wave_meter  \Dialog_Editor ;Records audio input (eg microphone) and displays level. function #  hDlg message wParam lParamif ( hDlg)  goto  messagesif ( ! ShowDialog ( "dlg_wave_meter"  & dlg_wave_meter  0 ))  ret ;BEGIN DIALOG ret ;messages int -  hwiWAVEHDR -  hdsel  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  messages2ret ;messages2 sel  wParam, case  IDOK , case  IDCANCEL ret  1 
 
 
	
	
	
		
	Posts: 1,000
 
	
	
		How to use Windows API functions to write to a file? Specify length?
	
	
	
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		Same as with PortAudio. Just data source is different.
	
	
	
	
	
 
 
	
	
	
		
	Posts: 1,000
 
	
	
		I see that portaudio declares how many number of frames totalFrames = numSeconds * sampleRate; to give the length of file
and then to record:
/* Write recorded data to a file. */ #if  1 type  WAVFILEHEADER _RIFF size _WAVE _fmt_ size1 @ audioFormat @ nChannels sampleRate byteRate @ blockAlign @ bitsPerSample _data size2memcpy  & h._RIFF "RIFF"  4 memcpy  & h._WAVE "WAVE"  4 memcpy  & h._fmt_ "fmt "  4 memcpy  & h._data "data"  4 = 16 = totalFrames* numChannels* sizeof ( word ) = 36 + h.size2= 1 = numChannels= sampleRate= h.sampleRate* h.nChannels* sizeof ( word ) = h.nChannels* sizeof ( word ) = sizeof ( word ) * 8 *  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
	
 
 
	
	
	
		
	Posts: 1,000
 
	
	
		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)  
	
	
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		Did not test on XP.
	
	
	
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		Can use this class to write wav file.
	
	
Attached Files WriteWavFile.qml  (Size: 2.35 KB / Downloads: 488)
 
	
	
	
 
 
	
	
	
		
	Posts: 1,000
 
	
	
		Having trouble figuring out how to call the Write function properly.
	
	
	
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		Function 
dlg_audio_record  \Dialog_Editor ;Records audio input (eg microphone) and saves in file. function #  hDlg message wParam lParamif ( hDlg)  goto  messagesstr  controls =  "3" str  e3= "$desktop$\recorded.wav" if ( ! ShowDialog ( "dlg_audio_record"  & dlg_audio_record  & controls))  ret ;BEGIN DIALOG ret ;messages #compile  "__WriteWavFile" WriteWavFile --  t_wavint --  t_hwi t_nChannels t_sampleRateARRAY ( WAVEHDR ) --  t_aWAVEHDR &  hint  rc isel  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  messages2ret ;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  ;/ function  $ funcName errorCodestr  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. 
	 
 
	
	
	
		
	Posts: 1,000
 
	
	
		Gintaras,
	
	
	
	
 
 
	
	
	
		
	Posts: 12,239
 
	
	
		Need to add more than 1 buffer. Now fixed.
	
	
	
	
	
 
 
	
	
	
		
	Posts: 1,000
 
	
	
		Gintaras,