The program object is a voice recorder that saves sequential files. In actuality it will be part of a larger app, but for the present this is an extraction for solving a problem. The code is based on Jim Fritts VOX code.
The code below works recording a single file. Sometimes it will record several samples without problem. However after a while it either misses to record, or records but appears to be appending the previous buffer content. Since I've not previously had this requirement I'm hoping someone who has can shed a bit more light on the problem.
The code below works recording a single file. Sometimes it will record several samples without problem. However after a while it either misses to record, or records but appears to be appending the previous buffer content. Since I've not previously had this requirement I'm hoping someone who has can shed a bit more light on the problem.
Code:
' main code for getting samples is from Jim Fritts VOX recorder ' "A Simple VOX Recorder (Voice Activated)" in the SourceCode ' with some alterations #COMPILE EXE #DIM ALL #INCLUDE "Win32API.inc" %IDD_DIALOG1 = 101 %ID_BTN_WAV_RECORD = 1001 %ID_BTN_WAV_STOP = 1002 %ID_BTN_WAV_PLAY = 1003 %IDC_LBL_LIVE = 1004 %IDC_BTN_QUIT = 1005 '------------- GLOBAL ghMainDialog AS DWORD GLOBAL gSample2Play AS ASCIIZ * 260 'las file recorded GLOBAL gNextMyWAVNum AS LONG 'next append number for user made samples GLOBAL gMyWAVSample AS ASCIIZ * 260 'current sample file name beng recorded GLOBAL gCAPTRS AS LONG '=1 WHEN RECORDING WAVEFILE GLOBAL gVOXcount AS LONG GLOBAL gVOXrecord AS LONG GLOBAL gNumberOfZeroCount AS LONG GLOBAL gRecordPulse AS LONG GLOBAL gStopPulse AS LONG GLOBAL gThreshold AS LONG GLOBAL gSamplePoints AS LONG GLOBAL gTotalPoints AS LONG GLOBAL gSR AS LONG GLOBAL gDevHandle1 AS LONG GLOBAL gInData() AS INTEGER ' Source data '============================================================================== SUB GetSamples() STATIC WAVE1 AS WAVEHDR STATIC junk AS DWORD, tt AS SINGLE REGISTER j AS LONG LOCAL m& LOCAL pk% LOCAL d% LOCAL i& REGISTER X AS LONG LOCAL X2 AS LONG, Y2 AS SINGLE, LastX AS LONG, LastY AS SINGLE STATIC WF1 AS WAVEFORMATEX DIM gSR AS LONG 'WAVE FORMAT STRUCTURE WF1.wFormatTag = %WAVE_FORMAT_PCM WF1.nChannels = 1 WF1.nSamplesPerSec = 44100 WF1.wBitsPerSample = 16 WF1.nBlockAlign = WF1.nChannels * WF1.wBitsPerSample \ 8 WF1.nAvgBytesPerSec = WF1.nBlockAlign * WF1.nSamplesPerSec waveInOpen gDevHandle1, 0, WF1, 0, 0, 0 IF gDevHandle1 = 0 THEN MSGBOX "Wave input device didn't open!", %MB_ICONWARNING, "Warning" CONTROL SEND ghMainDialog, %ID_BTN_WAV_STOP, %BM_CLICK,0,0 '%WM_COMMAND, %IDCANCEL, 0 'quit EXIT SUB END IF CALL waveInStart(gDevHandle1) gVOXcount = 0 gNumberOfZeroCount = 0 gThreshold = 0 gSamplePoints = 0 gTotalPoints = 0 gRecordPulse = 0 gStopPulse = 0 REDIM gInData(256 * 2 - 1) AS GLOBAL INTEGER ' Need extra 'cause triggering eats samples FOR i& = 1 TO 20: SLEEP 10 : NEXT CONTROL SET COLOR ghMainDialog, %IDC_LBL_LIVE ,%YELLOW,%GREEN CONTROL SET TEXT ghMainDialog, %IDC_LBL_LIVE ,"RECORD" CONTROL REDRAW ghMainDialog, %IDC_LBL_LIVE DO ' WAVE HDR STRUCTURE WAVE1.lpData = VARPTR(gInData(0)) WAVE1.dwBufferLength = 1024 ' WAVE1.dwBytegSRecorded = ' WAVE1.dwUser = WAVE1.dwFlags = 0 ' WAVE1.dwLoops = ' WAVE1.lpNext = ' WAVE1.Reserved = waveInPrepareHeader gDevHandle1, WAVE1, LEN(WAVE1) waveInAddBuffer gDevHandle1, WAVE1, LEN(WAVE1) ' Begin recording DO 'Just wait for the blocks to be done or the device to close DIALOG DOEVENTS 50 LOOP UNTIL (WAVE1.dwFlags AND %WHDR_DONE) OR (gDevHandle1 = %NULL) IF gDevHandle1 = 0 THEN EXIT DO ' Exit if the device is closed waveInUnprepareHeader gDevHandle1, WAVE1, LEN(WAVE1) ' Adaptive (+) peak detecting, zero-crossing Triggered Sweep. RESET pk% FOR j = 2 TO 256 \ 2 - 1 d% = gInData(j) IF d% => 0 AND d% > pk% THEN ' Noise (overshoot) filter IF ISFALSE(gInData(j - 2) <= 0) THEN pk% = d% : m& = j END IF NEXT ' Got the peak, now get a zero-crossing... FOR j = m& TO 256 - 1 IF gInData(j) <= 0 THEN m& = m& + (j - m&) : EXIT FOR NEXT ' Move our trigger point to head of buffer MoveMemory BYVAL VARPTR(gInData(0)), BYVAL VARPTR(gInData(m&)), 256 * 2 + 2 LastY = gInData(0) / 144 + 223 \ 4 FOR X = 1 TO 256 X2 = X Y2 = gInData(X) \ 144 + 223 \ 4 LastX = X2 : LastY = Y2 IF gSamplePoints < 2000 THEN gTotalPoints = gTotalPoints + LastY: _ INCR gSamplePoints: _ gThreshold = gTotalPoints/2000 IF gSamplePoints = 2000 THEN IF ABS(LastY - gThreshold) > 5 THEN gVOXcount = 1 ' limits sensitivity IF ABS(LastY - gThreshold) <= 5 THEN gVOXcount = 0 ' limits sensitivity ' Sets up conditions to produce trigger record and stop IF gVOXcount = 1 THEN gVOXrecord = 1 gNumberOfZeroCount = 0 ELSE INCR gNumberOfZeroCount IF gNumberOfZeroCount > = 2000 THEN gVOXrecord = 0 gNumberOfZeroCount = 0 END IF IF gVOXrecord = 1 AND gCAPTRS = 0 AND gRecordPulse = 0 THEN gRecordPulse = 1 'mciSendString "record capture1 from 0", BYVAL %NULL, 0, 0 'mciSendString "record capture1 from 0", BYVAL %NULL, 0, 0 mciSendString "record capture1", BYVAL %NULL, 0, 0 gCAPTRS = 1 END IF IF gVOXrecord = 0 AND gCAPTRS = 1 AND gStopPulse = 0 THEN gStopPulse = 1 mciSendString "stop capture1", BYVAL %NULL, 0, 0 mciSendString "save capture1 " & gMyWAVSample, BYVAL %NULL, 0, 0 gCAPTRS = 0 END IF END IF ELSE END IF NEXT LOOP WHILE gDevHandle1 END SUB '============================================================================== SUB DoStop() LOCAL result& IF ISTRUE gDevHandle1 THEN result& = waveInReset (gDevHandle1) GOSUB CheckWavError result& = waveInClose (gDevHandle1) GOSUB CheckWavError RESET gDevHandle1 END IF EXIT SUB CheckWavError: IF result& <> %MMSYSERR_NOERROR THEN SELECT CASE AS LONG result& CASE %MMSYSERR_INVALHANDLE : ? "%MMSYSERR_INVALHANDLE",%MB_TASKMODAL,"DoStop Error" CASE %MMSYSERR_NODRIVER : ? "%MMSYSERR_NODRIVER",%MB_TASKMODAL,"DoStop Error" CASE %MMSYSERR_NOMEM : ? "%MMSYSERR_NOMEM",%MB_TASKMODAL,"DoStop Error" CASE %WAVERR_STILLPLAYING : ? "%WAVERR_STILLPLAYING",%MB_TASKMODAL,"DoStop Error" END SELECT END IF RETURN END SUB '============================================================================== CALLBACK FUNCTION MainDlgProc() STATIC rfn$, wav$ SELECT CASE AS LONG CBMSG CASE %WM_INITDIALOG rfn$ = "Sample" wav$ = ".wav" CONTROL DISABLE CBHNDL, %ID_BTN_WAV_STOP CASE %WM_DESTROY IF gCAPTRS = 1 THEN mciSendString "stop capture1", BYVAL %NULL, 0, 0 mciSendString "save capture1 " & gMyWAVSample, BYVAL %NULL, 0, 0 gCAPTRS = 0 END IF mciSendString "close all", BYVAL %NULL, 0, 0 CALL DoStop ' CASE %WM_COMMAND ' Process control notifications SELECT CASE AS LONG CBCTL CASE %ID_BTN_WAV_PLAY DIALOG SET TEXT CBHNDL, gSample2Play SndPlaySound gSample2Play, %SND_ASYNC 'gSample2Play is already ASCIIZ CASE %ID_BTN_WAV_RECORD IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN INCR gNextMyWAVNum gMyWAVSample = rfn$ + FORMAT$(gNextMyWAVNum)+ wav$ DIALOG SET TEXT CBHNDL, gMyWAVSample CONTROL DISABLE CBHNDL,%ID_BTN_WAV_RECORD CONTROL ENABLE CBHNDL, %ID_BTN_WAV_STOP CONTROL SET TEXT CBHNDL, %IDC_LBL_LIVE ,"WAIT" CONTROL SET COLOR CBHNDL, %IDC_LBL_LIVE ,%YELLOW,%RED CONTROL REDRAW CBHNDL, %IDC_LBL_LIVE mciSendString "open new Type waveaudio Alias capture1", BYVAL %NULL, 0, 0 mciSendString "set capture1 bitspersample " & "16", BYVAL %NULL, 0, 0 mciSendString "set capture1 samplespersec " & "44100", BYVAL %NULL, 0, 0 mciSendString "set capture1 channels " & "1", BYVAL %NULL, 0, 0 GetSamples END IF CASE %ID_BTN_WAV_STOP IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN DoStop IF gCAPTRS = 1 THEN mciSendString "stop capture1", BYVAL %NULL, 0, 0 mciSendString "save capture1 " & gMyWAVSample, BYVAL %NULL, 0, 0 mciSendString "close capture1" , BYVAL %NULL, 0, 0 mciSendString "close " & gMyWAVSample, BYVAL %NULL, 0, 0 gCAPTRS = 0 END IF CONTROL SET TEXT CBHNDL, %IDC_LBL_LIVE ,"WAIT" CONTROL SET COLOR CBHNDL, %IDC_LBL_LIVE ,%YELLOW,%RED CONTROL REDRAW CBHNDL, %IDC_LBL_LIVE CONTROL ENABLE CBHNDL,%ID_BTN_WAV_RECORD CONTROL DISABLE CBHNDL, %ID_BTN_WAV_STOP gSample2Play = gMyWAVSample END IF CASE %IDC_BTN_QUIT IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN DIALOG END CBHNDL END IF END SELECT END SELECT END FUNCTION FUNCTION PBMAIN () AS LONG LOCAL hDLG AS DWORD LOCAL lRslt AS LONG DIALOG NEW PIXELS, 0, "Sound Problem",,, 500, 60, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg CONTROL ADD BUTTON, hDlg, %ID_BTN_WAV_RECORD ,"START" ,80 ,10 ,60 ,30 CONTROL ADD BUTTON, hDlg, %ID_BTN_WAV_STOP ,"STOP" ,150 ,10 ,60 ,30 CONTROL ADD BUTTON, hDlg, %ID_BTN_WAV_PLAY ,"PLAY" ,220 ,10 ,60 ,30 CONTROL ADD BUTTON, hDlg, %IDC_BTN_QUIT ,"Quit" ,400 ,10 ,60 ,30 CONTROL ADD LABEL, hDlg, %IDC_LBL_LIVE ,"WAIT" ,10 ,10 ,60 ,30 , _ %SS_CENTER OR %SS_CENTERIMAGE CONTROL SET COLOR hDlg, %IDC_LBL_LIVE ,%YELLOW,%RED ghMainDialog = hDlg DIALOG SHOW MODAL hDlg, CALL MainDlgProc TO lRslt END FUNCTION
Comment