It is currently Mon Oct 26, 2020 4:35 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: [Windows] Simple voice control
PostPosted: Sun Sep 20, 2020 10:21 am 
Offline
Addict
Addict
User avatar

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 2549
I need to control some functions within my purebasic program while staying away some meters from the keyboard. So I thought about voice control, but don't want to install an external program, etc.

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:

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


Top
 Profile  
Reply with quote  
 Post subject: Re: [Windows] Simple voice control
PostPosted: Wed Sep 23, 2020 8:56 am 
Online
Enthusiast
Enthusiast

Joined: Fri Oct 16, 2009 10:12 am
Posts: 700
Location: BE
Michael Vogel wrote:
...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) :|
Hi Michael ,
I'm not able to test your code at the moment, but (based on midi recording proces) I think you need to have a continu time registration, at least untill the third clap is recorded. If I understand your code without being able to test it, it looks like todo only recording when there is data. So what's the time between two records ?
The recording itself can imo just be a little part, as a absolutle threshold level, that must be in each clap sound. (A clapsound can have strange levels mostly two high parts in one clap).

_________________
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: Evil1, kpeters58 and 60 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye