Code: Select all
;/ 
;/ Object     Audio Recorder 1.0 (a) 
;/ 
;/ Date       August 2004 
;/ Author     Philippe Carpentier 
;/ Contact    flype@altern.org 
;/ Info       MS Windows only - winmm.lib - mmsystem.h 
;/ 
;  Bug fixes by chris319 on September 2, 2007
;
;  04/02/2010 : DrGolf for PB 4.50
;
;- REC GLOBAL 
; 
Global QuitRec.l 
; 
;- REC CONSTANTES 
; 
#MinWidth      = 320 
#MinHeight     = 240 
; 
;- REC INITIALISATION 
; 
Enumeration 0 ; #CHANNEL 
  #CHANNEL_LEFT 
  #CHANNEL_RIGHT 
EndEnumeration 
Enumeration 0 ; #GADGET 
  #gadFrame1 
  #gadFrame2 
  #gadStart 
  #gadStop 
  #gadSndVol 
  #gadFile 
  #gadChannel 
  #gadResolution 
  #gadFrequence 
  #gadDevice 
EndEnumeration 
Enumeration 0 ; #WINDOW 
  #Window 
EndEnumeration 
Enumeration 0 ; #TOOLBAR 
  #ToolBar 
EndEnumeration 
Enumeration 0 ; #STATUSBAR 
  #StatusBar 
EndEnumeration 
;Structure WAVEFORMATEX -- NOT NEEDED IN PB 4.10 -- chris319
;  wFormatTag.w 
;  nChannels.w 
;  nSamplesPerSec.l 
;  nAvgBytesPerSec.l 
;  nBlockAlign.w 
;  wBitsPerSample.w 
;  cbSize.w 
;EndStructure 
Structure SCOPE 
  channel.b 
  left.l 
  top.l 
  width.l 
  height.l 
  middleY.l 
  quarterY.l 
EndStructure 
Structure CONFIG 
  
  hWindow.l           ; Window handle 
  hToolBar.l          ; ToolBar handle 
  hfont.l             ; Font handle 
  
  Date.l              ; Start date 
  size.l              ; Wave buffer size 
  buffer.l            ; Wave buffer pointer 
  output.l            ; WindowOutput() 
  wave.l              ; Address of waveform-audio input device 
  recorded.l          ; Number of bytes recorded 
  recording.b         ; Record is running... 
  
  File.s              ; Recording FileName (c:\unnamed.raw) 
  FileId.l            ; Recording FileId (#PB_Any) 
  SndVol.s            ; Microsoft Volume Control (sndvol32.exe) 
  format.WAVEFORMATEX ; Capturing WaveFormatEx 
  lBuf.l              ; Capturing Buffer size 
  nBuf.l              ; Capturing Buffer number 
  nDev.l              ; Capturing Device identifier 
  nBit.l              ; Capturing Resolution (8/16) 
  nHertz.l            ; Capturing Frequency  (Hertz) 
  nChannel.l          ; Capturing Channels number (Mono/Stereo) 
  
  LScope.SCOPE        ; Wave form display 
  RScope.SCOPE        ; Wave form display 
  ScopeTimer.l        ; Scope Timer (redraw every n times) 
  cback.l             ; Back color 
  cline.l             ; Line color 
  cwave.l             ; Wave color 
  ColRecWave.l        ; Scope Record Wave Color 
  ColRecBack.l        ; Scope Record Back Color 
  ColRecLine.l        ; Scope Record Line Color 
  ColCapWave.l        ; Scope Capture Wave Color 
  ColCapBack.l        ; Scope Capture Back Color 
  ColCapLine.l        ; Scope Capture Line Color 
  
EndStructure 
Global Config.CONFIG 
Global Dim inHdr.WAVEHDR(16) 
Config\hfont             = LoadFont(0,"Arial",7) 
Config\format\cbSize     = 0 
Config\format\wFormatTag = #WAVE_FORMAT_PCM 
Config\LScope\channel    = #CHANNEL_LEFT 
Config\RScope\channel    = #CHANNEL_RIGHT 
; 
;- REC DECLARATIONS 
; 
Declare Clamp(value.l,min.l,max.l) 
Declare CONFIG_Load() 
Declare CONFIG_Save() 
Declare CAPTURE_Stop() 
Declare CAPTURE_Start() 
Declare CAPTURE_Error(err.l) 
Declare CAPTURE_GetDevices(gadId.l) 
Declare CAPTURE_Read(hWaveIn.l,lpWaveHdr.l) 
Declare DRAW_Scope() 
Declare DRAW_Wave(*scope.SCOPE) 
Declare DRAW_Wave8M(*scope.SCOPE) 
Declare DRAW_Wave8S(*scope.SCOPE) 
Declare DRAW_Wave16M(*scope.SCOPE) 
Declare DRAW_Wave16S(*scope.SCOPE) 
Declare DRAW_LCD(*scope.SCOPE,lcd$) 
Declare DRAW_Background(*scope.SCOPE) 
Declare FILE_Close() 
Declare FILE_Append() 
Declare FILE_Create() 
Declare FILE_Select() 
Declare FILE_Recording(state.b) 
Declare FILE_raw2wav(File.s) 
Declare GUI_Init() 
Declare GUI_Resize() 
Declare GUI_TBCombo(Id,x,y,w,h) 
Declare GUI_CallBack(hWnd.l,Msg.l,wParam.l,lParam.l) 
; 
;- REC PROCEDURES 
; 
; 
Procedure Clamp(value.l,min.l,max.l) 
  If value<min : ProcedureReturn min : EndIf 
  If value>max : ProcedureReturn max : EndIf  
  ProcedureReturn value 
EndProcedure 
; 
Procedure CONFIG_Load() 
  
  OpenPreferences("Recorder.ini") 
  
  PreferenceGroup("Files") 
  Config\File   = ReadPreferenceString("FileName","c:\unnamed.raw") 
  Config\SndVol = ReadPreferenceString("SndVol","sndvol32") 
  
  PreferenceGroup("Capture") 
  Config\nDev     = ReadPreferenceLong("Device",0) 
  Config\nChannel = ReadPreferenceLong("Channel",1) 
  Config\nHertz   = ReadPreferenceLong("Frequency",7) 
  Config\nBit     = ReadPreferenceLong("Resolution",1) 
  Config\nBuf     = ReadPreferenceLong("BufferNum",8) 
  Config\lBuf     = ReadPreferenceLong("BufferLen", 2048) ;chris319
  
  PreferenceGroup("Scope") 
  Config\ScopeTimer   = ReadPreferenceLong("ScopeTimer",25) 
  Config\ColRecLine   = ReadPreferenceLong("ColRecLine",  $000035) 
  Config\ColRecWave   = ReadPreferenceLong("ColRecWave",  $1010E0) 
  Config\ColRecBack   = ReadPreferenceLong("ColRecBack",  $000050) 
  Config\ColCapLine   = ReadPreferenceLong("ColCapLine",  $004000) 
  Config\ColCapWave   = ReadPreferenceLong("ColCapWave",  $20E020) 
  Config\ColCapBack   = ReadPreferenceLong("ColCapBack",  $004900) 
  
  PreferenceGroup("Window") 
  pos.WINDOWPLACEMENT 
  pos\length=SizeOf(WINDOWPLACEMENT) 
  pos\ptMinPosition\x         = ReadPreferenceLong("MinPosX",0) 
  pos\ptMinPosition\y         = ReadPreferenceLong("MinPoxY",0) 
  pos\ptMaxPosition\x         = ReadPreferenceLong("MaxPosX",-1) 
  pos\ptMaxPosition\y         = ReadPreferenceLong("MaxPosY",-1) 
  pos\rcNormalPosition\left   = ReadPreferenceLong("PosX1",100) 
  pos\rcNormalPosition\top    = ReadPreferenceLong("PosY1",100) 
  pos\rcNormalPosition\right  = ReadPreferenceLong("PosX2",#MinWidth) 
  pos\rcNormalPosition\bottom = ReadPreferenceLong("PosY2",#MinHeight) 
  
  ClosePreferences() 
  
  Config\cback   = Config\ColCapBack 
  Config\cline   = Config\ColCapLine 
  Config\cwave   = Config\ColCapWave 
  
  StatusBarText(0,2,Config\File) 
  SetGadgetState(#gadDevice,Config\nDev) 
  SetGadgetState(#gadChannel,Config\nChannel) 
  SetGadgetState(#gadFrequence,Config\nHertz) 
  SetGadgetState(#gadResolution,Config\nBit) 
  SetWindowPlacement_(Config\hWindow,@pos) 
  ShowWindow_(Config\hWindow,#True) 
  
EndProcedure 
; 
Procedure CONFIG_Save() 
  
  pos.WINDOWPLACEMENT 
  pos\length = SizeOf(WINDOWPLACEMENT) 
  GetWindowPlacement_(Config\hWindow,@pos) 
  
  If CreatePreferences("Recorder.ini") 
    
    PreferenceGroup("Files") 
    WritePreferenceString("FileName",Config\File) 
    WritePreferenceString("SndVol",Config\SndVol) 
    
    PreferenceGroup("Capture") 
    WritePreferenceLong("Device",Config\nDev) 
    WritePreferenceLong("Channel",Config\nChannel) 
    WritePreferenceLong("Frequency",Config\nHertz) 
    WritePreferenceLong("Resolution",Config\nBit) 
    WritePreferenceLong("BufferNum",Config\nBuf) 
    WritePreferenceLong("BufferLen",Config\lBuf) 
    
    PreferenceGroup("Scope") 
    WritePreferenceLong("ScopeTimer",Config\ScopeTimer) 
    WritePreferenceLong("ColRecLine",Config\ColRecLine) 
    WritePreferenceLong("ColRecWave",Config\ColRecWave) 
    WritePreferenceLong("ColRecBack",Config\ColRecBack) 
    WritePreferenceLong("ColCapLine",Config\ColCapLine) 
    WritePreferenceLong("ColCapWave",Config\ColCapWave) 
    WritePreferenceLong("ColCapBack",Config\ColCapBack) 
    
    PreferenceGroup("Window") 
    WritePreferenceLong("MinPosX",pos\ptMinPosition\x) 
    WritePreferenceLong("MinPoxY",pos\ptMinPosition\y) 
    WritePreferenceLong("MaxPosX",pos\ptMaxPosition\x) 
    WritePreferenceLong("MaxPosY",pos\ptMaxPosition\y) 
    WritePreferenceLong("PosX1",pos\rcNormalPosition\left) 
    WritePreferenceLong("PosY1",pos\rcNormalPosition\top) 
    WritePreferenceLong("PosX2",pos\rcNormalPosition\right) 
    WritePreferenceLong("PosY2",pos\rcNormalPosition\bottom) 
    
    ClosePreferences() 
    ProcedureReturn #True 
    
  EndIf 
  
EndProcedure 
; 
Procedure CAPTURE_Error(err.l) 
  If err 
    text.s=Space(#MAXERRORLENGTH) 
    waveInGetErrorText_(err,text,#MAXERRORLENGTH) 
    MessageRequester("Error",text,#MB_ICONERROR) 
    CAPTURE_Stop() 
    End 
  EndIf 
EndProcedure 
; 
Procedure CAPTURE_Start() 
  
  CAPTURE_Stop() 
  
  Config\nDev = GetGadgetState(#gadDevice) 
  
  Config\nChannel = GetGadgetState(#gadChannel) 
  Select Config\nChannel 
    Case 0 : Config\format\nChannels = 1 
    Case 1 : Config\format\nChannels = 2 
  EndSelect 
  
  Config\nBit = GetGadgetState(#gadResolution) 
  Select Config\nBit 
    Case 0 : Config\format\wBitsPerSample = 8 
    Case 1 : Config\format\wBitsPerSample = 16 
  EndSelect 
  
  Config\nHertz = GetGadgetState(#gadFrequence) 
  Select Config\nHertz 
    Case 0 : Config\format\nSamplesPerSec =  8000 
    Case 1 : Config\format\nSamplesPerSec = 11025 
    Case 2 : Config\format\nSamplesPerSec = 12000 
    Case 3 : Config\format\nSamplesPerSec = 16000 
    Case 4 : Config\format\nSamplesPerSec = 22050 
    Case 5 : Config\format\nSamplesPerSec = 24000 
    Case 6 : Config\format\nSamplesPerSec = 32000 
    Case 7 : Config\format\nSamplesPerSec = 44100 
    Case 8 : Config\format\nSamplesPerSec = 48000 
  EndSelect 
  
  Config\format\nBlockAlign     = (Config\format\nChannels*Config\format\wBitsPerSample)/8 
  Config\format\nAvgBytesPerSec = Config\format\nSamplesPerSec*Config\format\nBlockAlign 
  
  If #MMSYSERR_NOERROR = waveInOpen_(@Config\wave,#WAVE_MAPPER+Config\nDev,@Config\format,Config\hWindow,#Null,#CALLBACK_WINDOW|#WAVE_FORMAT_DIRECT) 
    
    For i=0 To Config\nBuf-1 
      inHdr(i)\lpData=AllocateMemory(Config\lBuf) 
      inHdr(i)\dwBufferLength=Config\lBuf 
      waveInPrepareHeader_(Config\wave,inHdr(i),SizeOf(WAVEHDR)) 
      waveInAddBuffer_(Config\wave,inHdr(i),SizeOf(WAVEHDR)) 
    Next 
    
    If #MMSYSERR_NOERROR = waveInStart_(Config\wave) 
      SetTimer_(Config\hWindow,0,Config\ScopeTimer,0) 
    EndIf 
    
  EndIf 
  
EndProcedure 
; 
Procedure CAPTURE_Stop() 
  If Config\wave 
    waveInReset_(Config\wave) 
    waveInStop_(Config\wave) 
    For i=0 To Config\nBuf-1 
      If inHdr(i) 
        waveInUnprepareHeader_(Config\wave,inHdr(i),SizeOf(WAVEHDR)) 
      EndIf 
    Next 
    waveInClose_(Config\wave) 
  EndIf 
  
  KillTimer_(Config\hWindow,0) 
  
EndProcedure 
; 
Procedure CAPTURE_Read(hWaveIn.l,lpWaveHdr.l) 
;  waveInAddBuffer_(hWaveIn,lpWaveHdr,SizeOf(WAVEHDR)) 
  *hWave.WAVEHDR=lpWaveHdr 
  Config\buffer=*hWave\lpData 
  Config\size=*hWave\dwBytesRecorded 
;  dwBytesRecorded MUST BE SAVED BEFORE CALLING waveInAddBuffer -- chris319  
  waveInAddBuffer_(hWaveIn,lpWaveHdr,SizeOf(WAVEHDR)) 
  FILE_Append() 
  
EndProcedure 
; 
Procedure CAPTURE_GetDevices(gadId.l) 
  MMNumDevice.l = waveInGetNumDevs_() 
  If MMNumDevice 
    For MMDeviceId=#WAVE_MAPPER To MMNumDevice-1 
      MMResult.l = waveInGetDevCaps_(MMDeviceId,@Caps.WAVEINCAPS,SizeOf(WAVEINCAPS)) 
      If MMResult = #MMSYSERR_NOERROR 
        AddGadgetItem(gadId,-1,PeekS(@Caps\szPname,#MAXPNAMELEN)) 
      EndIf 
    Next 
  EndIf 
EndProcedure 
; 
Procedure DRAW_Scope() 
  If Config\buffer 
    StartDrawing(WindowOutput(0)) ; 04/02/2010  DrGolf
   ;  StartDrawing(Config\output) 
      DRAW_Background(Config\LScope) 
      DRAW_Background(Config\RScope) 
      DRAW_Wave(Config\LScope) 
      If Config\nChannel 
        DRAW_Wave(Config\RScope) 
      EndIf 
    StopDrawing() 
  EndIf 
EndProcedure 
; 
Procedure DRAW_Background(*scope.SCOPE) 
  
  Box (*scope\left,*scope\top,*scope\width,*scope\height,Config\cback) 
  Line(*scope\left,*scope\middleY-*scope\quarterY,*scope\width,0,Config\cline) 
  Line(*scope\left,*scope\middleY+*scope\quarterY,*scope\width,0,Config\cline) 
  
EndProcedure 
; 
Procedure DRAW_LCD(*scope.SCOPE,lcd$) 
  
  DrawingMode(1) 
  FrontColor($00FFFF) 
  DrawingFont(Config\hfont) 
  Select *scope\channel 
    Case #CHANNEL_LEFT  : DrawText(*scope\left+1, *scope\top, "[L] "+lcd$) 
    Case #CHANNEL_RIGHT : DrawText(*scope\left+1, *scope\top, "[R] "+lcd$) 
  EndSelect 
  DrawingMode(0) 
  
EndProcedure 
; 
Procedure DRAW_Wave(*scope.SCOPE) 
  Select Config\nBit 
    Case 0 
      DRAW_LCD(*scope.SCOPE,"8 bits") 
      Select Config\nChannel 
        Case 0 : DRAW_Wave8M(*scope.SCOPE) 
        Case 1 : DRAW_Wave8S(*scope.SCOPE) 
      EndSelect 
    Case 1 
      DRAW_LCD(*scope.SCOPE,"16 bits") 
      Select Config\nChannel 
        Case 0 : DRAW_Wave16M(*scope.SCOPE) 
        Case 1 : DRAW_Wave16S(*scope.SCOPE) 
      EndSelect 
  EndSelect 
EndProcedure 
; 
Procedure DRAW_Wave8M(*scope.SCOPE) 
  Protected Max_Y = (Config\RScope\height)/2
  oldx.l=*scope\left 
  For i = 0 To Config\size - 1 ;chris319
    value.b=PeekB(Config\buffer+i)+$7F 
    xx=Clamp(*scope\left+(i**scope\width)/(Config\size+1),*scope\left,*scope\width) 
    yy=(value**scope\height)/$FF 
    If yy > Max_Y : yy = Max_Y : EndIf
    If yy < -Max_Y : yy = -Max_Y : EndIf
    LineXY(oldx,*scope\middleY+oldy,xx,*scope\middleY+yy,Config\cwave) 
    oldx=xx:oldy=yy 
  Next 
  
EndProcedure 
; 
Procedure DRAW_Wave8S(*scope.SCOPE) 
  Protected Max_Y = (Config\RScope\height)/2
  oldx.l=*scope\left 
  For i = 0 To (Config\size - 1) Step 2 ;chris319
    value.b=PeekB(Config\buffer+i+*scope\channel*2)+$7F 
    xx=Clamp(*scope\left+(i**scope\width)/(Config\size+1),*scope\left,*scope\width) 
    yy=(value**scope\height)/$FF
    If yy > Max_Y : yy = Max_Y : EndIf
    If yy < -Max_Y : yy = -Max_Y : EndIf
    LineXY(oldx,*scope\middleY+oldy,xx,*scope\middleY+yy,Config\cwave) 
    oldx=xx:oldy=yy 
  Next 
  
EndProcedure 
; 
Procedure DRAW_Wave16M(*scope.SCOPE) 
  Protected Max_Y = (Config\RScope\height)/2
  oldx.l=*scope\left 
  For i=0 To (Config\size -2) Step 2 ;chris319
    value.w=PeekW(Config\buffer+i) 
    xx=Clamp(*scope\left+(i**scope\width)/(Config\size+1),*scope\left,*scope\width) 
    yy=(value**scope\height)/$FFFF 
    If yy > Max_Y : yy = Max_Y : EndIf
    If yy < -Max_Y : yy = -Max_Y : EndIf
    LineXY(oldx,*scope\middleY+oldy,xx,*scope\middleY+yy,Config\cwave) 
    oldx=xx:oldy=yy 
  Next 
  
EndProcedure 
; 
Procedure DRAW_Wave16S(*scope.SCOPE) ;chris319
  Protected Max_Y = (Config\RScope\height)/2
Select *scope\channel
Case 0 ;LEFT CHANNEL
  oldx.l = *scope\left
  For i = 0 To (Config\size - 2) Step 4
    value.w = PeekW(Config\buffer + i)
    xx = Clamp(*scope\left+(i**scope\width)/(Config\size+1),*scope\left,*scope\width)
;    yy = (value * *scope\height)/$FFFF
    yy = (value * *scope\height) / $FFF
    ayy = Abs(yy)
    If ayy > vmax: vmax = ayy: EndIf
    If yy > Max_Y : yy = Max_Y : EndIf
    If yy < -Max_Y : yy = -Max_Y : EndIf
    LineXY(oldx,*scope\middleY+oldy,xx,*scope\middleY+yy,Config\cwave)
    oldx = xx: oldy = yy
  Next
Case 1 ;RIGHT CHANNEL
  oldx.l = *scope\left
  For i = 2 To (Config\size - 2) Step 4
    value.w = PeekW(Config\buffer + i)
    xx=Clamp(*scope\left+(i * *scope\width)/(Config\size+1),*scope\left,*scope\width)
;    yy = (value * *scope\height)/$FFFF
    yy = (value * *scope\height) / $FFF
    ayy = Abs(yy)
    If ayy > vmax: vmax = ayy: EndIf
    If yy > Max_Y : yy = Max_Y : EndIf
    If yy < -Max_Y : yy = -Max_Y : EndIf
    LineXY(oldx,*scope\middleY + oldy, xx, *scope\middleY + yy, Config\cwave)
    oldx = xx: oldy = yy
  Next
EndSelect
EndProcedure 
; 
Procedure FILE_Create() 
  
  Config\recorded  = #Null ; -- MOVED HERE BY chris319
    
  If Config\File 
    Config\FileId = CreateFile(#PB_Any,Config\File) 
    If Config\FileId 
      DisableToolBarButton(#ToolBar, #gadStart,#True) 
      DisableToolBarButton(#ToolBar, #gadFile,#True) 
      DisableGadget(#gadChannel,#True) 
      DisableGadget(#gadFrequence,#True) 
      DisableGadget(#gadResolution,#True) 
      DisableGadget(#gadDevice,#True) 
      Config\Date = GetTickCount_() 
      FILE_Recording(#True) 
    Else 
      MessageRequester("Error","Can't create file",#MB_ICONERROR) 
    EndIf 
  EndIf 
  
EndProcedure 
; 
Procedure FILE_Append() 
  
  If Config\recording = #True 
    Config\recorded + Config\size 
    WriteData(Config\FileId, Config\buffer,Config\size) 
    StatusBarText(#StatusBar, 0,Str(Config\recorded)+" bytes",#PB_StatusBar_Center) 
    StatusBarText(#StatusBar, 1,StrF((GetTickCount_()-Config\Date)/1000,3)+" secs",#PB_StatusBar_Center) 
  EndIf 
  
EndProcedure 
; 
Procedure FILE_Recording(state.b) 
  
  If state 
    Config\cback   = Config\ColRecBack 
    Config\cline   = Config\ColRecLine 
    Config\cwave   = Config\ColRecWave 
  Else 
    Config\cback   = Config\ColCapBack 
    Config\cline   = Config\ColCapLine 
    Config\cwave   = Config\ColCapWave 
  EndIf 
  
  Config\recording = state 
;  Config\recorded  = #Null -- THIS LINE OF CODE MOVED TO FILE_create-- chris319
EndProcedure 
; 
Procedure FILE_Close() 
  If Config\recording 
    Config\Date = #Null 
    FILE_Recording(#False) 
    CloseFile(Config\FileId) 
    Delay(1000) 
    FILE_raw2wav(Config\File)    
    DisableToolBarButton(#ToolBar, #gadStart,#False) 
    DisableToolBarButton(#ToolBar, #gadFile,#False) 
    DisableGadget(#gadChannel,#False) 
    DisableGadget(#gadFrequence,#False) 
    DisableGadget(#gadResolution,#False) 
    DisableGadget(#gadDevice,#False) 
  EndIf 
EndProcedure 
; 
Procedure FILE_Select() 
  
  File.s = SaveFileRequester("Select a file",Config\File,"Raw Sound|(*.raw)",0) 
  
  If File 
    Config\File = File 
  EndIf 
  
  StatusBarText(0,2,Config\File) 
  
EndProcedure 
; 
Procedure FILE_raw2wav(File.s) 
  inId.l = ReadFile(#PB_Any,File) 
  
  If inId = #Null 
    MessageRequester("Error", "Unable to open file",#MB_ICONERROR) ; chris319
    ProcedureReturn #False 
  EndIf 
  
  lBuf.l = Lof(inId) 
  pBuf.l = AllocateMemory(lBuf) 
  If pBuf = #Null
    MessageRequester("Error", "Unable to allocate buffer",#MB_ICONERROR) ; chris319
    ProcedureReturn #False 
  EndIf 
  
  ReadData(inId, pBuf,lBuf) 
  CloseFile(inId) 
  
  subchunk2size.l = Config\recorded
  chunksize.l = 36 + subchunk2size
  
  f$ = GetFilePart(File) 
  x$ = GetPathPart(File)+Left(f$,Len(f$)-Len(GetExtensionPart(File))-1)+".wav" 
  
  outId.l = CreateFile(#PB_Any,x$)  
  If outId = #Null 
    MessageRequester("Error", "Unable to create file",#MB_ICONERROR) ; chris319
    ProcedureReturn #False 
  EndIf 
  
  b.w = Config\format\wBitsPerSample 
  c.w = Config\format\nChannels 
  h.l = Config\format\nSamplesPerSec 
  WriteString(outId, "RIFF") ; 4 bytes 
;  WriteLong(outId, lBuf+44) ; 4 bytes 
  WriteLong(outId, chunksize) ; 4 bytes -- chris319
  WriteString(outId, "WAVEfmt ") ; 8 bytes -- chris319
    ;WriteString(outId, "fmt ") 
  
  ;WriteLong(outId, 16)
  WriteLong(outId, b) ; 4 bytes -- chris319
  
   
  WriteWord(outId, 1) ; 2 bytes -- PCM 
  WriteWord(outId, c) ; 2 bytes
  WriteLong(outId, h) ; 4 bytes
  WriteLong(outId, c*h*(b/8)) ; 4 bytes
  
  ;WriteWord(outId, c*(h/8))
  WriteWord(outId, (c * b) / 8) ; -- blockalign 2 bytes -- chris319
   
  WriteWord(outId, b) ; 2 bytes
  WriteString(outId, "data") ; 4 bytes
  WriteLong(outId, lBuf) ; -- 4 bytes
  WriteData(outId, pBuf,lBuf) 
  
  CloseFile(outId) 
  
  ProcedureReturn #True 
  
EndProcedure 
; 
Procedure GUI_Init() 
  QuitRec = 0 
  WndId.l = OpenWindow(0,0,0,500,400,"Recorder",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_Invisible) 
  If WndId=#Null : ProcedureReturn #False : EndIf 
  
  Config\hWindow=WindowID(0) 
  Config\output=WindowOutput(0) 
  Config\hToolBar=CreateToolBar(#ToolBar,Config\hWindow) 
  If Config\hToolBar=#Null : ProcedureReturn #False : EndIf 
  
  If CreateStatusBar(#StatusBar,Config\hWindow)=#Null 
    ProcedureReturn #False 
  EndIf 
  
  ToolBarStandardButton(#gadStart,#PB_ToolBarIcon_Open) 
  ToolBarStandardButton(#gadStop,#PB_ToolBarIcon_Delete) 
  
  ToolBarStandardButton(#gadFile,#PB_ToolBarIcon_Save) 
  ToolBarSeparator() 
  ToolBarStandardButton(#gadSndVol,#PB_ToolBarIcon_Properties) 
  ToolBarSeparator() 
  
  ToolBarToolTip(#ToolBar, #gadStart,"Record") 
  ToolBarToolTip(#ToolBar, #gadStop,"Stop") 
  ToolBarToolTip(#ToolBar, #gadFile,"Create a file") 
  ToolBarToolTip(#ToolBar, #gadSndVol,"Volume") 
  
  GUI_TBCombo(#gadChannel,0,1,58,20) ; 04/02/2010 DrGolf
  AddGadgetItem(#gadChannel,-1,"Mono") 
  AddGadgetItem(#gadChannel,-1,"Stereo") 
  SetGadgetState(#gadChannel,0) 
  
  GUI_TBCombo(#gadResolution,2,1,55,20) ; 04/02/2010 DrGolf
  AddGadgetItem(#gadResolution,-1,"8 bits") 
  AddGadgetItem(#gadResolution,-1,"16 bits") 
  
  GUI_TBCombo(#gadFrequence,2,1,80,20) ; 04/02/2010 DrGolf
  AddGadgetItem(#gadFrequence,-1,"8.0 kHz") 
  AddGadgetItem(#gadFrequence,-1,"11.025 kHz") 
  AddGadgetItem(#gadFrequence,-1,"12.0 kHz") 
  AddGadgetItem(#gadFrequence,-1,"16.0 kHz") 
  AddGadgetItem(#gadFrequence,-1,"22.05 kHz") 
  AddGadgetItem(#gadFrequence,-1,"24.0 kHz") 
  AddGadgetItem(#gadFrequence,-1,"32.0 kHz") 
  AddGadgetItem(#gadFrequence,-1,"44.1 kHz") 
  AddGadgetItem(#gadFrequence,-1,"48.0 kHz") 
  
  GUI_TBCombo(#gadDevice,2,1,160,20) ; 04/02/2010 DrGolf
  CAPTURE_GetDevices(#gadDevice) 
  SetGadgetState(#gadDevice,0) 
  
  Frame3DGadget(#gadFrame1,0,0,0,0,"",#PB_Frame3D_Double) 
  Frame3DGadget(#gadFrame2,0,0,0,0,"",#PB_Frame3D_Double) 
  
  AddStatusBarField( 100) 
  AddStatusBarField(  80) 
  AddStatusBarField(1000) 
  StatusBarText(0,0,"0 "+"bytes",#PB_StatusBar_Center) 
  StatusBarText(0,1,"0.000 "+"secs",#PB_StatusBar_Center) 
  
  SetWindowCallback(@GUI_CallBack()) 
  FILE_Recording(#False) 
  GUI_Resize() 
  ProcedureReturn #True 
  
EndProcedure 
; 
Procedure GUI_Resize() 
  
  WndW.l = ( WindowWidth(0)  -  4 ) 
  WndH.l = ( WindowHeight(0) - 60 ) >> 1 
  Config\LScope\left     = 2 
  Config\LScope\top      = 30 
  Config\LScope\width    = WndW 
  Config\LScope\height   = WndH 
  Config\LScope\quarterY = Config\LScope\height >> 2 
  Config\LScope\middleY  = Config\LScope\top + Config\LScope\height >> 1 
  ResizeGadget(#gadFrame1,Config\LScope\left-2,Config\LScope\top-2,Config\LScope\width+4,Config\LScope\height+4) 
  
  Config\RScope\left     = 2 
  Config\RScope\top      = Config\LScope\top + Config\LScope\height + 6 
  Config\RScope\width    = WndW 
  Config\RScope\height   = WndH 
  Config\RScope\quarterY = Config\RScope\height >> 2 
  Config\RScope\middleY  = Config\RScope\top + Config\RScope\height >> 1 
  ResizeGadget(#gadFrame2,Config\RScope\left-2,Config\RScope\top-2,Config\RScope\width+4,Config\RScope\height+4) 
  
EndProcedure 
; 
Procedure GUI_TBCombo(Id,x,y,w,h) 
  
  pos=SendMessage_(Config\hToolBar,#TB_BUTTONCOUNT,0,0) 
  ToolBarSeparator()        
  SendMessage_(Config\hToolBar,#TB_GETBUTTON,pos,@separator.TBBUTTON) 
  separator\iBitmap=x+w 
  SendMessage_(Config\hToolBar,#TB_DELETEBUTTON,pos,0) 
  SendMessage_(Config\hToolBar,#TB_INSERTBUTTON,pos,separator) 
  SendMessage_(Config\hToolBar,#TB_GETITEMRECT,pos,@rc.RECT)    
  UseGadgetList(Config\hToolBar) 
  ComboBoxGadget(Id,x+rc\left,y,w,h) 
  UseGadgetList(Config\hWindow) 
  
EndProcedure 
; 
Procedure GUI_CallBack(hWnd.l,Msg.l,wParam.l,lParam.l) 
  
  Result.l=#PB_ProcessPureBasicEvents 
  
  Select Msg 
    Case #WM_KEYDOWN 
      If GetAsyncKeyState_(#VK_ESCAPE) 
        QuitRec = 1 
      EndIf 
    Case #WM_SIZE     : GUI_Resize() 
    Case #WM_TIMER    : DRAW_Scope() 
    Case #MM_WIM_DATA : CAPTURE_Read(wParam,lParam) 
    Case #WM_COMMAND 
      Select wParam & $FFFF 
        Case #gadStart      : FILE_Create() 
        Case #gadStop       : FILE_Close() 
        Case #gadFile       : FILE_Select() 
        Case #gadSndVol     : RunProgram(Config\SndVol,"","") 
        Case #gadFrequence  : If EventType()=9 : CAPTURE_Start() : EndIf 
        Case #gadResolution : If EventType()=9 : CAPTURE_Start() : EndIf 
        Case #gadChannel    : If EventType()=9 : CAPTURE_Start() : EndIf 
        Case #gadDevice     : If EventType()=9 : CAPTURE_Start() : EndIf 
      EndSelect 
    Case #WM_GETMINMAXINFO 
      *mmi.MINMAXINFO=lParam 
      *mmi\ptMinTrackSize\x=#MinWidth 
      *mmi\ptMinTrackSize\y=#MinHeight 
  EndSelect 
  
  ProcedureReturn Result 
  
EndProcedure 
; 
;- REC MAIN 
; 
Procedure StartRecorder() 
  
  If GUI_Init() 
    CONFIG_Load() 
    CAPTURE_Start() 
    Repeat 
    Until WaitWindowEvent()=#WM_CLOSE Or QuitRec 
    CAPTURE_Stop() 
    CONFIG_Save() 
  EndIf 
  
EndProcedure 
StartRecorder()