kns, thanx for your observation : Structuring source code is VERY important i think even if it's at a cost of more lines !  This way, we can read it easier and as a consequence make the project grows faster...
 So, i would like to post a correction of my recorder. It now use a SetTimer_() for displaying wave and there's no more freezes. Also, i improved some things, try and you'll see  
Code: Select all
;***********************************************************************************
;- DECLARATIONS                                ; SOUND CAPTURE, Flype (26-juil-2002)
;***********************************************************************************
Declare CAPTURE_Read( hWaveIn.l, lpWaveHdr.l )
Declare CAPTURE_Error( err.l )
Declare CAPTURE_Start()
Declare CAPTURE_Stop()
Declare CAPTURE_Draw()
Declare CAPTURE_Now()
Declare GUI_CallBack( hWnd.l, Message.l, wParam.l, lParam.l )
Declare GUI_Button( id.l, ico.l, tip.s )
Declare GUI_Init()
Declare GUI_Main()
Declare GUI_Resize()
Declare FILE_Recording( state.b )
Declare FILE_Create()
Declare FILE_Append()
Declare FILE_Close()
;***********************************************************************************
;- INIT CONFIGURABLE CONSTANTES
;***********************************************************************************
#SOUND_NCHANNELS   = 1      ; This example only support Mono
#SOUND_NBITS       = 16     ; This example only support 16bits
#SOUND_NHERTZ      = 44100  ; Try 8000, 11050, 22100, 44100...
#BUFFER_NUM        = 8      ; Number of buffer for capture
#BUFFER_SIZE       = 512    ; Size of each buffer, should be x2 in Stereo
#BUFFER_TICK       = 10     ; Wave redraw delay : SetTimer_ in CAPTURE_Start()
;***********************************************************************************
;- INIT CONSTANTES
;***********************************************************************************
#BYTE = 1
#WORD = 2
#gadRecord   =  0
#gadStop     =  1
#gadMode     =  2
#StatusBar   =  0
#StatusTime  =  0
#StatusInfo  =  1
#StatusFile  =  2
#COLOR_RECBACK  = $000050
#COLOR_RECLINE  = $000035
#COLOR_RECWAVE  = $1010E0
#COLOR_CAPBACK  = $004900
#COLOR_CAPLINE  = $004000
#COLOR_CAPWAVE  = $20E020
#COLOR_VOLUME   = $00FFFF
#STR_ERROR      = "Error"
#STR_STOP       = "Stop"
#STR_RECORD     = "Record"
#STR_CLOSED     = "File saved"
#STR_SAVEREQ    = "Choose a file..."
#STR_MODE       = "Display mode"
#STR_RECORDED   = " bytes recorded"
#STR_PBFILE     = "Problem while creating file"
#STR_NODEVICE   = "Audio device not found"
;***********************************************************************************
;- INIT STRUCTURES
;***********************************************************************************
Structure RECORD_INFO
  x.l          ; Left
  y.l          ; Top
  w.l          ; Width
  h.l          ; Height
  m.l          ; YMiddle
  cback.l      ; Back color
  cline.l      ; Line color
  cwave.l      ; Wave color
  size.l       ; Wave buffer size
  buffer.l     ; Wave buffer pointer
  output.l     ; WindowOutput()
  mode.b       ; Wave mode (line or plain)
  wave.l       ; Address of waveform-audio input device
  frame.b      ; Counter for back clearing
  update.b     ; If true Wave have to be redrawn
  recorded.l   ; Number of bytes recorded
  recording.b  ; Record is running...
  time.s       ; Store the time string
EndStructure
Structure WAVEFORMATEX
  wFormatTag.w
  nChannels.w
  nSamplesPerSec.l
  nAvgBytesPerSec.l
  nBlockAlign.w
  wBitsPerSample.w
  cbSize.w
EndStructure
Dim inHdr.WAVEHDR( #BUFFER_NUM )
Global inHdr, rec.RECORD_INFO, now.SYSTEMTIME
rec\time = Space(9)
;***********************************************************************************
;- PROCS CAPTURE
;***********************************************************************************
Procedure CAPTURE_Error( err.l )
  If err
    text.s = Space( #MAXERRORLENGTH )
    waveInGetErrorText_( err, text, #MAXERRORLENGTH )
    MessageRequester( #STR_ERROR, text, #MB_ICONERROR )
    CAPTURE_Stop()
    End
  EndIf
EndProcedure
;==============================================================================
Procedure CAPTURE_Now()
  GetLocalTime_( @now )
  GetTimeFormat_(0, 0, @now, "HH:mm:ss:", @rec\time, 9 )
  StatusBarText( #StatusBar, #StatusTime, rec\time+Str(now\wMilliseconds) )
EndProcedure
;==============================================================================
Procedure CAPTURE_Draw()
  If rec\update = #TRUE
    CAPTURE_Now()
    StartDrawing( rec\output )
      ; Draw Background...
      If rec\frame = 2
        Box( rec\x, rec\y, rec\w, rec\h, rec\cback )
        shift = rec\h >> 2
        Line( rec\x, rec\m - shift, rec\w, 0, rec\cline )
        Line( rec\x, rec\m + shift, rec\w, 0, rec\cline )
        rec\frame = 0
      Else
        rec\frame + 1
      EndIf
      ; Draw Wave Data
      oldx = rec\x : oldy = 0
      For i=0 To rec\size Step #WORD
        value = PeekW( rec\buffer + i )
        x = rec\x + ( i * rec\w-1 ) / rec\size
        y = ( value * rec\h ) / $FFFF
        If value > max : max = value : EndIf
        If x <> oldx
          Select rec\mode
            Case #TRUE  : LineXY(oldx,rec\m+oldy,x,rec\m+y,rec\cwave)
            Case #FALSE : LineXY(oldx,rec\m+oldy,x,rec\m-y,rec\cwave)
          EndSelect
          oldx=x : oldy=y
        EndIf
      Next
      ; Draw Volume
      Box(rec\x+1,rec\h+rec\y-5,(max*(rec\w-2))/$7FFF,2,#COLOR_VOLUME)
    StopDrawing()
    rec\update = #FALSE
  EndIf
EndProcedure
;==============================================================================
Procedure.s CAPTURE_GetDevice()
  Caps.WAVEINCAPS
  For i=0 To waveInGetNumDevs_()-1
    CAPTURE_ERROR( waveInGetDevCaps_( i, @Caps, SizeOf( WAVEINCAPS ) ) )
    If Caps\dwFormats & #WAVE_FORMAT_1S08
      ProcedureReturn PeekS( @Caps\szPname, 32 )
    EndIf
  Next
  ProcedureReturn #STR_NODEVICE
EndProcedure
;==============================================================================
Procedure CAPTURE_Start()
  DeviceName.s = CAPTURE_GetDevice()
  If DeviceName
    SetWindowText_( WindowID(), DeviceName )
    format.WAVEFORMATEX
    format\wFormatTag      = 1
    format\nChannels       = #SOUND_NCHANNELS
    format\wBitsPerSample  = #SOUND_NBITS
    format\nSamplesPerSec  = #SOUND_NHERTZ
    format\nBlockAlign     = #SOUND_NCHANNELS * (#SOUND_NBITS/8)
    format\nAvgBytesPerSec = #SOUND_NHERTZ * format\nBlockAlign
    format\cbSize          = 0
    CAPTURE_Error( waveInOpen_( @rec\wave, #WAVE_MAPPER, @format, WindowID(), #NULL, #CALLBACK_WINDOW|#WAVE_FORMAT_DIRECT ) )
    For i = 0 To #BUFFER_NUM - 1
      inHdr(i)\lpData         = AllocateMemory( i, #BUFFER_SIZE )
      inHdr(i)\dwBufferLength = #BUFFER_SIZE
      CAPTURE_Error( waveInPrepareHeader_( rec\wave, inHdr(i), SizeOf( WAVEHDR ) ) )
      CAPTURE_Error( waveInAddBuffer_    ( rec\wave, inHdr(i), SizeOf( WAVEHDR ) ) )
    Next
    CAPTURE_Error( waveInStart_( rec\wave ) )
    SetTimer_( WindowID(), 0, #BUFFER_TICK, 0 )
  EndIf
EndProcedure
;==============================================================================
Procedure CAPTURE_Stop()
  If rec\wave
    CAPTURE_Error( waveInReset_( rec\wave ) )
    CAPTURE_Error( waveInStop_ ( rec\wave ) )
    For i = 0 To #BUFFER_NUM - 1
      CAPTURE_Error( waveInUnprepareHeader_( rec\wave, inHdr(i), SizeOf( WAVEHDR ) ) )
    Next
    CAPTURE_Error( waveInClose_( rec\wave ) )
  EndIf
  KillTimer_( WindowID(), 0 )
EndProcedure
;==============================================================================
Procedure CAPTURE_Read( hWaveIn.l, lpWaveHdr.l )
  CAPTURE_Error( waveInAddBuffer_( hWaveIn, lpWaveHdr, SizeOf( WAVEHDR ) ) )
  rec\buffer  = PeekL( lpWaveHdr )
  rec\size    = PeekL( lpWaveHdr + 8 )
  rec\update  = #TRUE
  FILE_Append()
EndProcedure
;***********************************************************************************
;- PROCS FILE
;***********************************************************************************
Procedure FILE_Create()
  File.s = SaveFileRequester( #STR_SAVEREQ, "C:\test.raw", "Son brut|(*.raw)", 0 )
  If File
    If CreateFile( 0, File )
      FILE_Recording( #True )
      StatusBarText( #StatusBar, #StatusFile, File )
    Else
      MessageRequester( #STR_ERROR, #STR_PBFILE, #MB_ICONERROR )
    EndIf
  EndIf
EndProcedure
;==============================================================================
Procedure FILE_Append()
  If rec\recording = #True
    rec\recorded + rec\size
    WriteData( rec\buffer, rec\size )
    StatusBarText( #StatusBar, #StatusInfo, Str(rec\recorded) + #STR_RECORDED )
  EndIf
EndProcedure
;==============================================================================
Procedure FILE_Recording( state.b )
  If state = #TRUE
    rec\cback = #COLOR_RECBACK
    rec\cline = #COLOR_RECLINE
    rec\cwave = #COLOR_RECWAVE
  Else
    rec\cback = #COLOR_CAPBACK
    rec\cline = #COLOR_CAPLINE
    rec\cwave = #COLOR_CAPWAVE
  EndIf
  DisableToolBarButton( #gadRecord, state )
  DisableToolBarButton( #gadStop, #TRUE-state )
  rec\recording = state
  rec\recorded = 0
EndProcedure
;==============================================================================
Procedure FILE_Close()
  If rec\recording = #TRUE
    FILE_Recording( #FALSE )
    CloseFile(0)
    StatusBarText( #StatusBar, #StatusFile, #STR_CLOSED )
  EndIf
EndProcedure
;***********************************************************************************
;- PROCS GUI
;***********************************************************************************
Procedure GUI_Button( id.l, ico.l, tip.s )
  ToolBarStandardButton( id, ico )
  ToolBarToolTip( id, tip )
EndProcedure
;==============================================================================
Procedure GUI_Init()
  hFlags.l = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered
  If OpenWindow( 0, 0,0,320,160, hFlags, "" ) = #NULL
    ProcedureReturn #FALSE
  EndIf
  If CreateToolBar( 0, WindowID() ) = #NULL
    ProcedureReturn #FALSE
  EndIf
  If CreateGadgetList( WindowID() ) = #NULL
    ProcedureReturn #FALSE
  EndIf
  Frame3DGadget( 0, 0,0,0,0, "", #PB_Frame3D_Double )
  If CreateStatusBar( #StatusBar, WindowID() ) = #NULL
    ProcedureReturn #FALSE
  EndIf
  rec\output = WindowOutput()
  GUI_Button( #gadRecord, #PB_ToolBarIcon_Save,       #STR_RECORD )
  GUI_Button( #gadStop,   #PB_ToolBarIcon_Delete,     #STR_STOP   )
  GUI_Button( #gadMode,   #PB_ToolBarIcon_Properties, #STR_MODE   )
  AddStatusBarField(   80 )
  AddStatusBarField(  150 )
  AddStatusBarField( $FFF )
  ProcedureReturn #TRUE
EndProcedure
;==============================================================================
Procedure GUI_Resize()
  rec\x = 2
  rec\y = 30
  rec\w = WindowWidth()-4
  rec\h = WindowHeight()-52
  rec\m = rec\y + rec\h / 2
  UpdateStatusBar( #StatusBar )
  ResizeGadget( 0, rec\x-2, rec\y-2, rec\w+4, rec\h+4 )
EndProcedure
;==============================================================================
Procedure GUI_CallBack( hWnd.l, uMsg.l, wParam.l, lParam.l )
  Result.l = #PB_ProcessPureBasicEvents 
  Select uMsg
    Case #MM_WIM_DATA : CAPTURE_Read( wParam, lParam )
    Case #WM_TIMER    : CAPTURE_Draw()
    Case #WM_SIZE     : GUI_Resize()
    Case #WM_CLOSE    : Quit = #TRUE
    Case #WM_COMMAND
      Select wParam
        Case #gadRecord : FILE_Create()
        Case #gadStop   : FILE_Close()
        Case #gadMode   : rec\mode = #TRUE-rec\mode
      EndSelect
  EndSelect
  ProcedureReturn Result 
EndProcedure
;==============================================================================
Procedure GUI_Main()
  If GUI_Init()
    SetWindowCallback( @GUI_CallBack() )
    FILE_Recording( #FALSE )  
    GUI_Resize()
    CAPTURE_Start()
    While WaitWindowEvent()<>#WM_CLOSE : Wend
    CAPTURE_Stop()
  EndIf
EndProcedure
;***********************************************************************************
;- START
;***********************************************************************************
GUI_Main()
End