beaterkennung über ein Aufnahmegerät

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Rothammel
Beiträge: 53
Registriert: 17.09.2006 17:22

beaterkennung über ein Aufnahmegerät

Beitrag von Rothammel »

Servus Jungs,

ich hab da mal versucht über API die Daten vom WindowsSoundMaper zu hohlen und jez hab ich sie glaube auch, aber was soll ich nun damit anstellen? möchte gern damit ein paar lichteffekte steuern...

Code: Alles auswählen

Structure CONFIG
  hWindow.l           ; Window 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

  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)
 
  ScopeTimer.l        ; Scope Timer (redraw every n times)
EndStructure

Global Config.CONFIG
Global Dim inHdr.WAVEHDR(16)

Config\format\cbSize     = 0
Config\format\wFormatTag = #WAVE_FORMAT_PCM


Declare Clamp(value.l,min.l,max.l)


Declare CAPTURE_Stop()
Declare CAPTURE_Start()
Declare CAPTURE_Error(err.l)
Declare CAPTURE_GetDevices(gadId.l)
Declare CAPTURE_Read(hWaveIn.l,lpWaveHdr.l)


Declare CallBack(hWnd.l,Msg.l,wParam.l,lParam.l)




;
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 = 0
 
  Config\nChannel = 0
  Select Config\nChannel
    Case 0 : Config\format\nChannels = 1
    Case 1 : Config\format\nChannels = 2
  EndSelect
 
  Config\nBit = 1
  Select Config\nBit
    Case 0 : Config\format\wBitsPerSample = 8
    Case 1 : Config\format\wBitsPerSample = 16
  EndSelect
 
  Config\nHertz = 7
  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)
  Shared time
  Shared zaehler
;  waveInAddBuffer_(hWaveIn,lpWaveHdr,SizeOf(WAVEHDR))
 
  *hWave.WAVEHDR=lpWaveHdr
  Config\buffer=*hWave\lpData
  
  
;-Daten  hier...
    wert= PeekW(Config\buffer)
    Debug wert


  Config\size=*hWave\dwBytesRecorded
;  dwBytesRecorded MUST BE SAVED BEFORE CALLING waveInAddBuffer -- chris319 
  waveInAddBuffer_(hWaveIn,lpWaveHdr,SizeOf(WAVEHDR))

  
  
  ;durchläufe pro sekunde zählen
  ;zaehler=zaehler+1
  ;If time<Date()
  ;  Debug zaehler
  ;  zaehler=0
  ;  time=Date()
  ;EndIf
EndProcedure
;
Procedure CallBack(hWnd.l,Msg.l,wParam.l,lParam.l)
 
  Result.l=#PB_ProcessPureBasicEvents
 
  Select Msg
    

    Case #MM_WIM_DATA : CAPTURE_Read(wParam,lParam)
    
  EndSelect
 
  ProcedureReturn Result
 
EndProcedure
;
;- REC MAIN
;

 
      OpenWindow(0,0,0,500,400,"Tester",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_SizeGadget)
      CreateImage(1,300,100)
      ImageGadget(2,10,10,300,100,ImageID(1))
      Config\hWindow=WindowID(0)
      SetWindowCallback(@CallBack())
      Config\nBuf     = 8
      Config\lBuf     = 1048
      CAPTURE_Start()
      
    Repeat
    Until WaitWindowEvent()=#WM_CLOSE
    CAPTURE_Stop()
der code is ausem englischen forum, dort war es ein Recorder und ich hab ihn soweit minimalisiert

aber wie erkenne ich nun ob es ein beat war? erstmal die negativen werte *-1 und dann?
Benutzeravatar
Kukulkan
Beiträge: 1066
Registriert: 09.09.2004 07:07
Wohnort: Süddeutschland
Kontaktdaten:

Re: beaterkennung über ein Aufnahmegerät

Beitrag von Kukulkan »

Hallo,

eine Beaterkennung geht am besten, indem Du zuerst einen Low-Pass Filter auf die Sample-Daten anwendest. Also nur die Frequenzen unter zB unter 250 Hz beachtest (die beste Frequenz musst Du durch Versuche ermitteln). Alternativ könnte eine FFT verwendet werden. Bei den tiefen Frequenzen wird die Basstrommel (Basedrum) geschlagen. Der Beat kann dort am besten erkannt werden.

Dann würde ich dort einen Lautstärke Treshold ermitteln der das erreichen eines Peak erkennt. Am besten einen sich anpassenden Treshold. Dann immer die Zeit zählen, bis wieder ein solcher Peak erreicht wird. Daraus kannst Du dann (unter Annahme eines 4/4 Taktes) die BPM errechnen. Ich würde aber immer die vorangegangenen Peaks ebenfalls berücksichtigen. Also zB immer die letzten 10.

Grüße,

Kukulkan
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: beaterkennung über ein Aufnahmegerät

Beitrag von NicTheQuick »

Hier ist ein kleines Vorlesungspaper von einem kleinen Seminar, das ich mal vor 2 Jahren gehört hab. Dort ist eine sehr gute Beat-Ermittlungsmethode angegeben. Los geht's abe Seite 4 im PDF.
Tempo and Beat Analysis.pfp
Benutzeravatar
Kukulkan
Beiträge: 1066
Registriert: 09.09.2004 07:07
Wohnort: Süddeutschland
Kontaktdaten:

Re: beaterkennung über ein Aufnahmegerät

Beitrag von Kukulkan »

Hallo,

ja, das Dokument ist gut. Die von mir skizzierte Methode funktioniert nämlich nur bei moderner Musik mit Bass-Rhytmus (die meisten Pop, Rock, Rap, HipHop und Disko-Sachen). Wenn man es genauer und vielseitiger braucht, dann kommt man um aufwändigere Algorithmen nicht herum :|

Grüße,

Kukulkan
Antworten