Announcement

Collapse
No announcement yet.

recording multiple sequential wav files

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • recording multiple sequential wav files

    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.

    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
    Rick Angell

  • #2
    Richard,
    I know this is a bit out of date for you but this should help others.

    Change CASE %ID_BTN_WAV_RECORD to this:

    Code:
                    CASE %ID_BTN_WAV_RECORD
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            INCR gNextMyWAVNum
                            gMyWAVSample = rfn$ + FORMAT$(gNextMyWAVNum)+ wav$
    [B]                        [SIZE=14px]KILL gMyWAVSample[/SIZE][/B]
                            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
    [B]                        [SIZE=14px]mciSendString "delete capture1 from 1", BYVAL %NULL, 0, 0[/SIZE][/B]
                            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

    Comment

    Working...
    X