Now my idea is recognizing one, two or three hand claps to control three different functions. The first step is done with the code below (mixed some sources from the forum) so I am able to differ between "silence" and "noise" already.
But how to detect, if one or more quick claps have been done? Actually one single "clapping wave" can be seen in one captured buffer but can also appear in two consecutive buffers as well.
So I'd need a simple method to get the "clap count", this is my actual method...
...which is not perfectly reliable (and from time to time, the program even crashs)
Code: Select all
; Define Audio
#AudioMaxBuffer= 16
#AudioTreshholdLow= 123
#AudioTreshholdHigh= 133
Enumeration 1
#AudioMono
#AudioStereo
EndEnumeration
Enumeration
#AudioChannelLeft
#AudioChannelRight
EndEnumeration
Structure AudioType
Device.l
Window.l
Channels.l
Wave.l
ScopeTimer.l
Buffers.l
BufferLen.l
Format.WAVEFORMATEX
EndStructure
Global Audio.AudioType
Global AudioSemaphore=CreateSemaphore()
Global AudioCapturing
Global AudioPw.l,AudioPl.l
Global *AudioBuffer=AllocateMemory(32768)
Global Dim AudioBuffer.WAVEHDR(#AudioMaxBuffer)
Structure ClapType
RingPos.i
RingTrend.i
OnState.i
ClapCount.i
Claps.i
Pause.i
EndStructure
Global Clap.ClapType
#RingBuffer=250
Global Dim OnOff(#RingBuffer)
Global Position=0
Global Trend=0
Global State
Global Clap
Global ClapCount
Global Pause
With Audio
\Device= 0;
\ScopeTimer= 20;
\Format\nChannels= #AudioMono
\Format\nSamplesPerSec= 12000; 8000 / 11025 / 12000 / 16000 / 22050 / 24000 / 32000 / 44100 / 48000
\Format\wBitsPerSample= 8; 8 / 16
\Buffers= 8; 1..MaxBuffers
\BufferLen= 1024; 1024..8192?
\Format\wFormatTag= #WAVE_FORMAT_PCM
\Format\nBlockAlign= \Format\nChannels*\Format\wBitsPerSample/8
\Format\nAvgBytesPerSec=\Format\nSamplesPerSec*\Format\nBlockAlign
\Format\cbSize= 0
EndWith
; EndDefine
Procedure AudioGetDevices()
MMNumDevice.l = waveInGetNumDevs_()
If MMNumDevice
For MMDeviceId=0 To MMNumDevice
MMResult.l = waveInGetDevCaps_(#WAVE_MAPPER+MMDeviceId,@Caps.WAVEINCAPS,SizeOf(WAVEINCAPS))
If MMResult = #MMSYSERR_NOERROR
Debug Str(MMDeviceId)+" - "+PeekS(@Caps\szPname,#MAXPNAMELEN)
EndIf
Next
EndIf
EndProcedure
Procedure AudioStartCapture()
With Audio
If waveInOpen_(@\Wave,#WAVE_MAPPER+\Device,@\Format,\Window,#Null,#CALLBACK_WINDOW|#WAVE_FORMAT_DIRECT)=#MMSYSERR_NOERROR
For i = 0 To \Buffers-1
AudioBuffer(i)\lpData=AllocateMemory(\BufferLen)
AudioBuffer(i)\dwBufferLength=\BufferLen
waveInPrepareHeader_(\Wave,AudioBuffer(i),SizeOf(WAVEHDR))
waveInAddBuffer_(\Wave,AudioBuffer(i),SizeOf(WAVEHDR))
Next
If waveInStart_(\Wave)=#MMSYSERR_NOERROR
Debug ":)"
SetTimer_(\Window,0,\ScopeTimer,0)
EndIf
EndIf
EndWith
EndProcedure
Procedure AudioStopCapture()
AudioPw=#Null
AudioCapturing=#Null
SignalSemaphore(AudioSemaphore)
With Audio
If \Wave
waveInReset_(\Wave)
waveInStop_(\Wave)
For i = 0 To \Buffers-1
If AudioBuffer(i)
waveInUnprepareHeader_(\Wave,AudioBuffer(i),SizeOf(WAVEHDR))
FreeMemory(AudioBuffer(i)\lpData)
EndIf
Next
waveInClose_(\Wave)
EndIf
EndWith
Debug "done."
EndProcedure
Procedure AudioReadCapture(WaveIn.l,*WaveBuffer.WAVEHDR)
If WaveIn And *WaveBuffer
If *WaveBuffer\lpData
CopyMemory(*WaveBuffer\lpData,*AudioBuffer,*WaveBuffer\dwBytesRecorded)
EndIf
max=0
min=999
StartDrawing(CanvasOutput(0))
Box(0,0,1024,255,#Black)
on=0
off=0
time=0
count=0
With Clap
For i=0 To 1023
b=PeekA(*AudioBuffer+i)
noise=Bool(b<#AudioTreshholdLow Or b>#AudioTreshholdHigh)
\RingTrend-OnOff(\RingPos)+noise
OnOff(\RingPos)=noise
\RingPos=(\RingPos+1)%#RingBuffer
If \OnState
If \RingTrend<#RingBuffer/8
\OnState=0
\Pause=0
EndIf
Else
If \RingTrend>#RingBuffer/4
\OnState=1
\ClapCount+1
Debug "*"
\Pause=0
ElseIf \RingTrend=0
\Pause+1
If \Pause=5000
If \ClapCount
\Claps=\ClapCount
\ClapCount=0
Debug "CLAP "+Str(\Claps)
EndIf
EndIf
EndIf
EndIf
LineXY(i,0,i,b,#Green)
Box(i,240-\OnState*222,3,3,#Red)
Next i
StopDrawing()
If \Claps
;Debug Str(\Claps)
\Claps=#Null
EndIf
EndWith
waveInAddBuffer_(WaveIn,*WaveBuffer,SizeOf(WAVEHDR))
EndIf
EndProcedure
Procedure AudioLoop(nil)
AudioCapturing=#True
While AudioCapturing
WaitSemaphore(AudioSemaphore)
If AudioPw
AudioReadCapture(AudioPw,AudioPl)
EndIf
Wend
Debug "Thread done."
EndProcedure
Procedure Callback(handle.l,msg.l,w.l,l.l)
If msg=#MM_WIM_DATA
AudioPw=w
AudioPl=l
SignalSemaphore(AudioSemaphore)
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Audio\Window=OpenWindow(0,10,10,1024,255,"TEST")
CanvasGadget(0,0,0,1024,255)
CreateThread(@AudioLoop(),0)
SetWindowCallback(@Callback(),0)
AudioGetDevices()
AudioStartCapture()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
quit=1
EndSelect
Until quit
AudioStopCapture()
Delay(100)