Capturing Audio [COMPLETE SOURCE]

Share your advanced PureBasic knowledge/code with the community.
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Capturing Audio [COMPLETE SOURCE]

Post by Flype »

Here is my program that shows how to capture audio under windows without using MCI functions. Raw sound is saved in a file... which can be loaded and listened thanx a software like SoundForge.

Raw format sound generated : 16bit, Mono, 44100Hz

You have to configure the Volume Control (use the volume systray icon) in order to select Stereo Mixer (Menu->Properties->Record...). You should also set the volume not too high...

Have fun :wink:

Code: Select all

i removed it, see the correct source below
Last edited by Flype on Wed Oct 18, 2006 6:28 pm, edited 3 times in total.
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Tranquil
Addict
Addict
Posts: 952
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Post by Tranquil »

WOW! Very, very nice work!! Thanks for sharing this source!!!!

Respect!

Mike
Tranquil
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

Je dirais même plus : excellent :D
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

merci merci 8)

thanx, i'll hope somebody will increase the functionnality of this little proggy ! and especially shared it :wink:

there's much of things to do like, in a first part, listing the available devices in order to let the user choose...
It would be, also, nice to let the user select Mono/Stereo - 8/16bits - Frequency...

I'm interesting to know if it doesn't work on your configuration, especially win98/Me :roll: ...

I've tested it on win2000 / winXP and there's no problem.

I know that sometimes when resizing the window, it freezes, Silly...
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Denis
Enthusiast
Enthusiast
Posts: 778
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Post by Denis »

:wink:


Denis
A+
Denis
Tranquil
Addict
Addict
Posts: 952
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Post by Tranquil »

Works fine on Windows 2000 Prof and Server.
Tranquil
kns
User
User
Posts: 54
Joined: Sat Apr 26, 2003 2:06 am

Post by kns »

This is my personal bias....

The code presented appears beautifully structured and readable. It's been my experience (C in this case) that it's easier to follow the logic when long stretches are broken into discrete functions. On a personal level I would have an easier time learning from more such examples. [I know that there an any number of retorts that can be hurled my way, hence couching the observation as a personal preference.]

Thanks for the example!

KNS
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

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...
I know that sometimes when resizing the window, it freezes, Silly...
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 :wink:

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
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
midebor
User
User
Posts: 26
Joined: Fri Apr 25, 2003 10:22 pm
Location: Liege, Belgium

Post by midebor »

Code doesn't compile : MMSYSTEM010 - a non valid indicator has been transmitted to system fonction.
Debugger variable list shows only: inHdr 0 long
No other variables.
OS is win98.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Hi Flype.
It is a good idea your program, but here doesn't work. When i run it windows stops all sound, and when i make windows to expose some sound, your program can't run.

Windows 2000


AL
DominiqueB
Enthusiast
Enthusiast
Posts: 103
Joined: Fri Apr 25, 2003 4:00 pm
Location: France

so

Post by DominiqueB »

It works great for me.
i'm under XP pro sp1.

Dominique.
Dominique

Windows 10 64bits. Pure basic 32bits
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

bad, not cool :cry: I'v not win98 to test it... I'd take care of using only win98 compliant api functions : "winmm". Perhaps an error appear when the system can't find an audiocard... try this to see : comment lines

Code: Select all

Procedure CAPTURE_Start()
;  DeviceName.s = CAPTURE_GetDevice()
;  If DeviceName
;    SetWindowText_( WindowID(), DeviceName )
.
.
.
;  EndIf
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
chio
User
User
Posts: 30
Joined: Thu Jun 24, 2004 1:55 pm
Location: New York City
Contact:

note frequency

Post by chio »

How could I didplay the Hz of the note played? I have my guitar connected and would love to see the note I am playing being recognized.

Thanks
chio
aaron
Enthusiast
Enthusiast
Posts: 267
Joined: Mon Apr 19, 2004 3:04 am
Location: Canada
Contact:

Post by aaron »

You would have to convert the waveform to frequency on the fly. A fast fourier transform (FFT) will do the trick. A quick search on google turns up tons of info on it.... you'll likely end up converting source from C or using a DLL.

This page looks like a good place to start:
http://www.fullspectrum.com/deeth/programming/fft.html
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post by Hroudtwolf »

Code: Select all

;Corrected for current version of PB (3.93) (Hroudtwolf)

;***********************************************************************************
;- 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
;***********************************************************************************



#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



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(  #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
  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
Post Reply