AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Beat Detection
Thema durchsuchen
Ansicht
Themen-Optionen

Beat Detection

Ein Thema von BenjaminH · begonnen am 7. Sep 2009 · letzter Beitrag vom 2. Mai 2014
Antwort Antwort
Seite 2 von 2     12   
BenjaminH
Registriert seit: 14. Okt 2004
Der Beat Detector erkennt aus einer Aufnahmequelle heraus Beats. Es liefert allerdings nicht die bpm Zahl oder so etwas, sondern sendet bei jedem erkannten Beat eine MIDI-Signal.
Der Nutzen des Programms liegt in der Kombination mit anderen Programmen, z.B. DMXControl(Lichtsteuerung über DMX Controller am PC) wobei hier mit jedem Beat in eine neue Lichtszene gewechselt wird(Lauflicht o.ä.).
Das Programm wurde darauf optimiert im laufenden Betrieb möglichst schnell zu sein.

Wichtigste Besonderheit: Ab Windows Vista wird direkt auf die "Hauptlautstärke" zugegriffen. D.h. auch ohne Stereomix kann die Audioausgabe direkt abgegriffen werden.

Beschreibung der neuesten Version hier


Zur Erkennung des Beats wird ein Algorithmus verwendet, den ich bei Gamedev gefunden habe. Wahrscheinlich habe ich nicht alles genau richtig gemacht, weil ich nicht alles so genau verstanden habe. Aber es funktioniert.
Der Toneingang wird mittels der Bass.dll gelesen, auch die Fourier-Analyse übernimmt sie.

Ich freue mich über jeden Verbesserungsvorschlag!

Das Programm erstellt im Benutzerverzeichnis/Lokale Einstellungen/Anwendungsdaten eine Datei(.BeatDetector.ini).
Damit die Core-Audio Features funktionieren(Aufnahme der Wiedergabe durch den Lautsprecher) muss die bass.dll aus diesem Beitrag verwendet werden: http://www.un4seen.com/forum/?topic=8816 (Bzw direktlink: http://www.un4seen.com/stuff/bass.dll)

Grobe Funktion der Beat-Analyse(wird mit ca. 40Hz aufgerufen)
Delphi-Quellcode:
type
    THistArray= array[0..43] of Single;
var
    fft : array[0..1023] of Single;
    i,
    bound_lower, //untere -
    bound_upper:Integer; //obere Grenze zum erstellen der Bänder
    Sum:Single;//Energie eines Bandes

    BandHistory:array [0..31] of THistArray;//Alte Werte der Bänder gespeichert
    Histposition:0..43;//Aktuelle Stelle im Band History Array
    LastBeat:Cardinal;//GetTickCount beim letzten erkannten Beat

//FFT berechnen, Amplituden speichern
BASS_ChannelGetData(MainForm.Channel, @fft, BASS_DATA_FFT1024); // get the FFT data

//FFT in Bänder aufteilen
bound_lower:=0;
for i := 0 to bands - 1 do
begin
  //Bandbreite bestimmen
  bound_upper:=Trunc(Power(2, i * 10.0 / (BANDS - 1)));
  if bound_upper>1023 then
    bound_upper:=1023;
  if bound_upper<=bound_lower then//mindestens 1 FFT bin verwenden
    bound_upper:=bound_lower+1;

  //Summe der Amplituden innerhalb eines Bandes
  Sum:=0;
  while bound_lower<bound_upper do
  begin
    Sum:=Sum + fft[bound_lower+1];
    inc(bound_lower);
  end;
  //Amplitude des ganzen Bandes speichern
  BandHistory[i,HistPosition]:=sum;
end;
Inc(MainForm.HistPosition);

//Erkennen eines Beats(nur, wenn die gesamte Lautstärke nicht zu gering ist
if LOWORD(BASS_ChannelGetLevel(Channel)) >= 500 then
begin
  //Beat ist dann, wenn der Ausschlag des Bandes um den Faktor x größer ist als der Durchschnitt der letzten 43 Ausschläge
  if AverageBandEnergy(BandHistory[SelectedBand]) * DetectingFactor < BandHistory[SelectedBand,HistPosition-1] then
//AverageBandEnergy berechnet den Durchschnitt der letzten 43 Ausschläge im gegebenen Band
    if gettickcount>lastbeat+WaitingTime then//zu schnell aufeinanderfolgende Beats vermeiden
    begin
      Beat;//Beat Signal weitergeben
      lastbeat:=gettickcount;
    end;
end;
Miniaturansicht angehängter Grafiken
screenshot-1-1-0.png  
Angehängte Dateien
Dateityp: exe beatdetector_307.exe (542,5 KB, 203x aufgerufen)

Geändert von BenjaminH (22. Jun 2010 um 14:08 Uhr)
 
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

 
Delphi 7 Professional
 
#11
  Alt 16. Apr 2010, 20:36
Zitat von BenjaminH:
Achtung dafür braucht man die Modifizierte Bass.dll, die in diesem Beitrag zu finden ist.
Könntest du bitte genauer beschreiben, wo die modifizierte Bass.dll zu finden ist? Auf den ersten Blick findet man die nämlich im un4seen-Forum nicht.

Bernhard
Bernhard
  Mit Zitat antworten Zitat
BenjaminH

 
Turbo Delphi für Win32
 
#12
  Alt 16. Apr 2010, 22:19
Die modifizierte Bass.dll direkt: http://www.un4seen.com/stuff/bass.dll
Benjamin
  Mit Zitat antworten Zitat
dustin
 
#13
  Alt 17. Apr 2010, 02:40
Hallo,

Ich versuche mich auch an irgendeiner Art Beaterkennung,aber eine zufriedenstellende Lösung finde ich nicht so richtig.
Das verfahren von Gamedev verstehe ich nicht wirklich, da mein Englisch sehr mieeeeees ist und finde
da auch nicht mehr rein (ins Englisch).

Vieleicht hat ja da einer noch eine Idee.
Es giebt ja verschiedene Ansätze im Netz, aber meist nur theoretische Ansätze.

Meime Idee war es eigendlich eine saubere BPM Erkennung und die dann mit den Peakwerten zu syncronisieren um die zwischenbeat's zu unterdrücken. Aber die BPM Ermittlung stellt da das Problem.

Mit der Bass DLL habe ich nicht viel am Hut da giebt es bei mir immer probleme.
Angehängte Dateien
Dateityp: exe project1_968.exe (635,0 KB, 47x aufgerufen)
  Mit Zitat antworten Zitat
nobbi29
 
#14
  Alt 30. Apr 2014, 12:02
Hallo BenjaminH,

der Eintrag ist ja schon ein paar Tage alt, nicht desto trotz habe ich gestern den Beat_Detector_307 unter Windows 7/64 Bit ausprobiert und direkt ans Laufen bekommen. Jetzt mein Frage, was muss ich tun um in einem eigenen Delphi Programm die MIDI Message vom Deinem Beat Detector Programm zu empfangen?
Gib es da eine Chance?

Freue mich auf einen Hinweis oder besser noch auf ein Code Sample.

Viele Grüße

nobbi29
  Mit Zitat antworten Zitat
ElektroLurch

 
Delphi XE2 Professional
 
#15
  Alt 30. Apr 2014, 12:41
Hi,
grob umrissen:
Richte auf deinem System einen virtuellen Midiport ein. (loopMidi ist da eine Möglichkeit)
Weise dem Programm diesen Port als Ausgang zu.
Für dein eigenes Programm sollte dann dieser als Eingang gewählt werden.
Werner B
  Mit Zitat antworten Zitat
nobbi29
 
#16
  Alt 1. Mai 2014, 08:44
Hallo ElektroLurch,

Danke für die prompte Antwort. Das probiere ich heute mal aus. Hast Du noch einen Tipp, welche Komponente ich am Einfachsten verwenden sollte. Mit Midi hab ich noch nie was programmiert.

Viele Grüße

nobbi29
  Mit Zitat antworten Zitat
ElektroLurch

 
Delphi XE2 Professional
 
#17
  Alt 1. Mai 2014, 10:36
Hier in der DP, Tutorials und Kurse unter M findest du etwas zu MidiIn und MidiOut.
Das ist ein guter Anfang.
Mit MidiIn kannst du die Steuersignale übernehmen, interpretieren und dann damit sonstwas auslösen. Muss ja nicht zwangsläufig etwas mit Musik zu tun haben.
Werner B
  Mit Zitat antworten Zitat
BenjaminH

 
Turbo Delphi für Win32
 
#18
  Alt 2. Mai 2014, 21:06
Hi,
ich habe das damals so gemacht:
Delphi-Quellcode:
uses MMSystem;

var fHandle:Hwnd;

//startet den Empfang der MIDI-Signale
// Verarbeitung in midiInCallback, für mididevnum siehe unten
procedure InitMidi(mididevnum);
begin
  midierror:=midiInOpen(@fHandle, mididevnum, Cardinal(@midiInCallback), mididevnum, CALLBACK_FUNCTION);
  if MMSYSERR_NOERROR<>midierror then
    case midierror of
      MMSYSERR_ALLOCATED: ShowMessage('The specified resource is already allocated.');
      MMSYSERR_BADDEVICEID: ShowMessage('The specified device identifier is out of range.');
      MMSYSERR_INVALFLAG: ShowMessage('The flags specified by dwFlags are invalid.');
      MMSYSERR_INVALPARAM: ShowMessage('The specified pointer or structure is invalid.');
    end;
  midiinstart(fHandle);
end;

procedure MidiEnd();
begin
  MidiInStop(fHandle);
  MidiInClose(fHandle);
end;

procedure midiInCallback(aMidiInHandle: PHMIDIIN; aMsg: Cardinal; aInstance, aMidiData, aTimeStamp: integer);stdcall;
begin
  //Hier verarbeitest du das Zeug, alles wichtige ist in aMidiData enthalten
end;

//Gibt dir eine Liste der MIDI-Geräte aus in eine Listbox names lbmidi, der Index des Eintrags entspricht der Gerätenummer, die du dann an InitMidi weitergeben kannst.
procedure ListMidiDevices;
    function GetMidiDeviceName(id:Integer):String;
    var caps: TMidiInCaps;
    begin
      midiInGetDevCaps(id,@caps, sizeof(TMidiInCaps));
      result:=caps.szPname;
    end;
  var count:Integer;
    i: Integer;
    midiname:String;
  begin
    count:=midiInGetNumDevs;
    lbMidi.Items.Clear;
    for i := 0 to count - 1 do
    begin
      midiname:=GetMidiDeviceName(i);
      lbMidi.Items.Add(midiname);
    end;
  end;
Aber natürlich kannst du das auch eleganter in eine Klasse kapseln

Die MIDI Daten(aMidiData) sind in Wikipedia sehr gut erklärt: http://de.wikipedia.org/wiki/MIDI#Protokoll
Was der BeatDetector genau sendet weiß ich nicht mehr, das siehst du wenn du die Daten checkst aber recht schnell.
Ich glaube es war erst ein Note On, dann ein Note Off in sehr kurzem Abstand.

Viel Erfolg,
Benjamin
Benjamin
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:38 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz