Capturing Audio [COMPLETE SOURCE]

Share your advanced PureBasic knowledge/code with the community.
chris319
Enthusiast
Enthusiast
Posts: 782
Joined: Mon Oct 24, 2005 1:05 pm

Post by chris319 »

You should be able to run this program in real-time priority by adding the following line of code:

SetPriorityClass_(GetCurrentProcess_(), #REALTIME_PRIORITY_CLASS)

This may help prevent dropped audio samples due to contention for CPU cycles. In Windows Vista you will need to be logged in as Administrator (not simply an account with administrator priveleges but the actual Administrator account). If running Vista Home Basic you can enable the Administrator account by following the steps listed here:

http://www.rage3d.com/board/archive/ind ... 82250.html
Philippe-felixer76-2
Enthusiast
Enthusiast
Posts: 135
Joined: Sat Aug 18, 2007 7:09 am
Location: Netherlands

draw scope into imageoutput

Post by Philippe-felixer76-2 »

Why isn't it possible to draw directoy into a imageoutput?

Gr,
Phil.
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

Thank you Flype (and chris319) for this excellent audio capture code. You have saved me hours of research time. 8)
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

chris319 wrote:OpenAL does not support 24-bit recording.
It doesn't support Float? (PS! if the windows driver for the card support float or just convert from 16bit to float is a different matter :roll:)

PS! Vista uses only 32bit float in it's audio stack, so if you ask for 16bit you might get 16bit>32bit float>16bit :shock:
or if you ask for 32bit float you might get 16bit>32bit float>32bit float,
or if lucky 24bit>32bit float>32bit float or 32bit float>32bit float>32bit float,
depending on the card/driver. Have fun :lol:
chris319
Enthusiast
Enthusiast
Posts: 782
Joined: Mon Oct 24, 2005 1:05 pm

Post by chris319 »

Vista uses only 32bit float in it's audio stack, so if you ask for 16bit you might get 16bit>32bit float>16bit or if you ask for 32bit float you might get 16bit>32bit float>32bit float, or if lucky 24bit>32bit float>32bit float or 32bit float>32bit float>32bit float, depending on the card/driver.
This program uses WinMM which only deals in integer samples.
chris319
Enthusiast
Enthusiast
Posts: 782
Joined: Mon Oct 24, 2005 1:05 pm

Post by chris319 »

More bug fixes to this program. 16-bit stereo is now drawn properly to the scope display. See original post of source code for other fixes.
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Re: Capturing Audio [COMPLETE SOURCE]

Post by dobro »

the last code dont work in Pb 4.41 ! :cry:
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
drgolf
Enthusiast
Enthusiast
Posts: 106
Joined: Tue Mar 03, 2009 3:40 pm
Location: france

Re: Capturing Audio [COMPLETE SOURCE]

Post by drgolf »

Here is the code for PB 4.50 :

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) 
  
  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 
    LineXY(oldx,*scope\middleY+oldy,xx,*scope\middleY+yy,Config\cwave) 
    oldx=xx:oldy=yy 
  Next 
  
EndProcedure 
; 
Procedure DRAW_Wave8S(*scope.SCOPE) 
  
  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 
    LineXY(oldx,*scope\middleY+oldy,xx,*scope\middleY+yy,Config\cwave) 
    oldx=xx:oldy=yy 
  Next 
  
EndProcedure 
; 
Procedure DRAW_Wave16M(*scope.SCOPE) 
  
  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 
    LineXY(oldx,*scope\middleY+oldy,xx,*scope\middleY+yy,Config\cwave) 
    oldx=xx:oldy=yy 
  Next 
  
EndProcedure 
; 
Procedure DRAW_Wave16S(*scope.SCOPE) ;chris319

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
    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
    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()


User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Re: Capturing Audio [COMPLETE SOURCE]

Post by dobro »

:) Thanks !! :)
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
Susan20
User
User
Posts: 19
Joined: Fri Feb 29, 2008 1:10 pm
Location: Berlin

Re: Capturing Audio [COMPLETE SOURCE]

Post by Susan20 »

Hi,

I downloaded the lame mp3-encoder from http://lame.sourceforge.net/index.php recently. Besides the lame_enc.dll there were also lame.exe and some examples in the package. One command line example was this:
# Streaming mono 22.05 kHz raw pcm, 24 kbps output:
cat inputfile | lame -r -m m -b 24 -s 22.05 -- > output
# Streaming mono 44.1 kHz raw pcm, with downsampling to 22.05 kHz:
cat inputfile | lame -r -m m -b 24 --resample 22.05 -- > output
I'm not an expert on this field and may be I'm too naiv. But: Does this mean that lame.exe can encode raw audio data, which is in the input butter, to mp3? If yes: Could this feature be added to this capturing code?
User avatar
zekitez@lycos.com
User
User
Posts: 15
Joined: Fri Nov 11, 2005 5:42 pm
Location: Netherlands
Contact:

Re: Capturing Audio [COMPLETE SOURCE]

Post by zekitez@lycos.com »

Here is the code for PB 4.50
I don't have sndvol32 in Windows7...
It just needs some clamping of yy between + and - (height / 2).
wimapon
Enthusiast
Enthusiast
Posts: 290
Joined: Thu Dec 16, 2010 2:05 pm
Location: Delfzijl ( The Netherlands )
Contact:

Re: Capturing Audio [COMPLETE SOURCE]

Post by wimapon »

Hi, i am completely new in this forum and in Pure Basic,

for my radio-telescope i need to register 2 seconds of receiver noise with a sound card.
i try to compile the program above.... it will solve my wish , i think.
But i can not compile it.
the last error was: Structure not found: WAVEHDR

i do use windows xp and pure basic v 4.51 demo version

what must i do


( for more info about my telescope: http://home.kpn.nl/apon001/huis.htm
Thanks
Wim
PureLust
Enthusiast
Enthusiast
Posts: 477
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: Capturing Audio [COMPLETE SOURCE]

Post by PureLust »

wimapon wrote:i do use windows xp and pure basic v 4.51 demo version

what must i do
Just go and get the fully licensed Version of PB. :wink:

I don't have a look at the code, but I'm sure it uses some API-Functions.

Because you cannot use API-Functions in the Demo-Version of PB, the only way will be to buy a license (btw.: it's worth it !!! :wink: ).
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Re: Capturing Audio [COMPLETE SOURCE]

Post by Rook Zimbabwe »

I am reworking as it seems to overdraw the window with the green ossiliscope lines in some music files... putting ins a less OOPish format
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
Vitor_Boss®
User
User
Posts: 81
Joined: Thu Sep 23, 2010 4:22 am

Re: Capturing Audio [COMPLETE SOURCE]

Post by Vitor_Boss® »

zekitez@lycos.com wrote:
Here is the code for PB 4.50
I don't have sndvol32 in Windows7...
It just needs some clamping of yy between + and - (height / 2).
Here is the fixed code for clamping:

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()
Sorry by bad English.
HP Pavilion DV6-2155DX: Intel i3-330m 2.13 / 4GB DDR3 / 500GB Sata2 HD / Display 15.6" LED / Win7 Ultimate x64 / PB 4.50 x86 demo.
Post Reply