[alg/c++] Beatdetectie bij muziek

Pagina: 1
Acties:
  • 234 views sinds 30-01-2008
  • Reageer

  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Ik ben atm een programma zoals Atomixmp3 aan het maken, en maak daarbij gebruik van de BASS-library om muziek af te spelen. So far so good, want snelheid aanpassen enzo met een slidertje lukt allemaal wel.

Nu zit er in Atomixmp3 ook iets waarmee je twee spelende bestanden qua bpm (en dus snelheid) op elkaar kan afstemmen. Nou wil ik ook zoiets maken, maar ik heb geen idee hoe ik het beste beats kan gaan detecteren :/ BASS biedt de mogelijkheid om zogenaamde 'DSPPROCS' te koppelen aan een channel, zodat er steeds een functie wordt aangeroepen:

C++:
1
void CALLBACK DSP(HDSP handle,DWORD channel,void *buffer,DWORD length,DWORD user);


Is er iemand die een idee heeft over hoe dit aan te pakken?? (links naar open-source pakketten die dit hebben mogen ook, kan ik wat code doorspitten *D)

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 21-02 00:06

dusty

Celebrate Life!

Hoe herken je een beat normaal?

Hoe denk jij dan dat een beat automatisch door de computer kan laten herkennen?

:)

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
dusty schreef op 14 January 2003 @ 17:08:
Hoe herken je een beat normaal?

Hoe denk jij dan dat een beat automatisch door de computer kan laten herkennen?

:)
Meestal de lage tonen :) Zover kwam ik ook nog wel ;) Het probleem is, ik zou niet weten hoe ik daar aan moet komen (dus hoe ik die hoge van de lage kan splitten enzo) in een functie met de hierboven genoemde parameters :) Als iemand daar een antwoord op heeft, dan kan ik inderdaad es gaan proberen :)

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 21-02 00:06

dusty

Celebrate Life!

Je krijgt een stream terug, ga eens kijken wat er in die stream staat :P

Immers is een lage toon een lage frequentie, voordat je het weet zou je alle lage tonen makkelijk kunnen vinden in de stream.

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
dusty schreef op 14 januari 2003 @ 17:13:
Je krijgt een stream terug, ga eens kijken wat er in die stream staat :P

Immers is een lage toon een lage frequentie, voordat je het weet zou je alle lage tonen makkelijk kunnen vinden in de stream.
Je bedoelt die void* buffer? Hmm, altijd gedacht dat daar geluidssterktes oid in stonden ipv frequenties :P ik ga es even kijken denk ik

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 21-02 00:06

dusty

Celebrate Life!

Geluid bestaat niet alleen uit geluidssterkte, netzoals hij niet alleen uit frequentie bestaat.

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
dusty schreef op 14 January 2003 @ 17:26:
Geluid bestaat niet alleen uit geluidssterkte, netzoals hij niet alleen uit frequentie bestaat.
Uitleg......?? Kun je me alsjeblieft nog een zetje in de goeie richting geven?

  • DaCoTa
  • Registratie: April 2002
  • Laatst online: 14:08
Je hebt eerst een frequentieanalyse nodig. Zoiets als een Fast Fourier zal wel makkelijk te vinden zijn, maar is kwalitatief niet echt hoogstaand. Als je dat hebt, heb je een soort ritme-detectie nodig. Kijken welke (lage) tonen er het meest duidelijk repeterend zijn. Maar eerst beginnen met FFT.

Extra info: FFT is een omzetting van het tijdsdomein naar frequentiedomein. In het tijdsdomein heb je inderdaad alleen maar een reeks met geluidssterktes. Als je een bepaalde reeks neemt van - bijvoorbeeld - 10ms, dan kun je dat omrekenen naar een frequentiespectrum. Dan krijg je een soort histrogram van de opbouw van het geluid in die 10ms. Als je je gehele muziekstuk zo opdeelt, krijg je dus een verloop van frequenties en zul je bepaalde freqenties repeterend terugzien.

Dit is een beetje lame-mans-terms, het is een paar jaartjes geleden dat ik deze stof gehad heb, dus het is een beetje weggezakt, maar met google moet je een heel eind komen, waarschijnlijk tot kant-en-klare FFT sourcecode.

Als je dit hebt, moet je de volgende stap maken, het bepalen van de BPM. Je moet dan een klusteralgoritme loslaten op alle duidelijke frequenties van je muziekstuk. Als je alleen in het lage frequentie segment kijkt, dan haal je met wat zoekwerk de beat er wel uit.

[ Voor 63% gewijzigd door DaCoTa op 14-01-2003 17:46 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
DaCoTa schreef op 14 January 2003 @ 17:37:
Je hebt eerst een frequentieanalyse nodig. Zoiets als een Fast Fourier zal wel makkelijk te vinden zijn, maar is kwalitatief niet echt hoogstaand. Als je dat hebt, heb je een soort ritme-detectie nodig. Kijken welke (lage) tonen er het meest duidelijk repeterend zijn. Maar eerst beginnen met FFT.
Kwaliteit lijkt me nou net niet het grootste probleem eigenlijk ;) Ik zag mensen op andere sites ook al met de term FFT smijten, maar wat is het precies?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Hier: http://www.library.cornell.edu/nr/bookcpdf.html
Hoofdstuk 12 (en 13)

deze gaat iets sneller: http://lib-www.lanl.gov/numerical/bookcpdf.html

[ Voor 34% gewijzigd door Zoijar op 14-01-2003 17:46 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Ik heb geen Acrobat hier, maar ik zal er straks even naar kijken via een andere PC :) Ben niet zo'n wiskunde-freak verder, en na veel browsen op onder andere het forum van BASS zelf denk ik niet dat dit een 1-2-3 te maken dingetje is eigenlijk :/ Ik quote vanaf datzelfe forum:
I even dare to say I think the source-code for a *good*, *generic* beat-detector (depends on your defenition ofcourse) would probably be larger than the entire BASS-sourcecode

And in case you just want a *simple* beat-detector - just grab the lower frequencies of the FFT-data and you have your bassdrum-detection...
Link naar het draadje: http://www.un4seen.com/mu...ay&num=1025821514&start=0

  • Reefer
  • Registratie: Mei 2000
  • Laatst online: 21-02-2025

Reefer

madness

//offtopic
En als je dit niet gaat lukken kun je altijd nog een knop inbouwen waarop je met de maat kan meeklikken en zo het bpm bepalen

A Breakbeat A Day Keeps Religion Away.


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
Ik ben zelf ook al een tijdje bezig met m'n eigen bpm detectie voor mijn dj programma djDecks en ik moet zeggen dat het ondertussen best wel redelijk goed werkt.
Op deze site kan je mijn ocx downloaden die aan de hand van het spectrum van de muziek (dus nadat je de fft hebt uitgevoerd) de bpm kan bepalen.
Ik ben momenteel bezig aan een dll die de bpm detectie doet, en ook de fft analyze uitvoert.
Deze gaat standaard wel voor de fmod library werken, maar waarschijnlijk ook bruikbaar zijn in bass.

Hoe ik de detectie heb aangepakt is eerst een fft analyze doen per 1024 samples, zodat je dus een array krijgt waar ipv 1024 samples, 512 frequencywaardes instaan, van 1-22050Hz (oftewel je sampling frequentie/2).
Als de eerste waardes in deze array dus groot worden, betekend dit dat de lage tonen op dat moment sterk aanwezig zijn.

Je kan dus in de laagste waarden zoeken naar pieken, en aannemen dat elke piek een beat is.
Met behulp van de tijd tussen 2 beats kan je dan de bpm bepalen.

Omdat dit niet erg exact is, zal je beter de tijd tussen 10 beats nemen en delen door 10.
Je zal waarschijnlijk ook de gevonden beats moeten bekijken en beats die te dicht bij een andere beat liggen verwijderen, en mogelijk veronderstellen dat er tussen twee beats met te grote tijd ertussen zich toch een beat bevond die niet gededecteerd werd.

Hopelijk heeft dit je al een beetje op weg geholpen!

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Reefer schreef op 14 January 2003 @ 18:08:
//offtopic
En als je dit niet gaat lukken kun je altijd nog een knop inbouwen waarop je met de maat kan meeklikken en zo het bpm bepalen
Das een optie...... je zou zelfs de BPM in een ID3-tag kunnen opslaan ofzo :) Magoed, ik zal eens kijken naar wat Adion heeft gezegd hierboven.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een bassdrum bestaat niet alleen uit lage tonen. Vooral het begin van de 'kick' is een mix van heel veel frequenties. De wat langere drums sterven wel uit in lage tonen, maar het gaat nou juist om het begin. Dit begin is heel goed te zien als je naar de samples kijkt, er is namelijk een abrupte verandering in amplitude.

Dit geldt overigens ook voor de snaredrum, die ook heel erg bijdraagt aan het bepalen van de beats (er is nog meer dan oempe oempe oempe muziek ;)). Als je al die snelle veranderingen registreert dan kan je op een gegeven moment een herhalend patroon ontdekken. Een periode is een aantal beats (meestal 4, 8 of 16), dus de bpm daaruit halen is niet direct te bepalen, maar je kunt wel een schatting maken aan de hand van het soort nummer

Over het algemeen ligt de bpm tussen de 120 en de 240. Een waarde groter dan 240 zal je dus net zo lang door 2 kunnen delen tot het hiertussen ligt, en een waarde kleiner dan 120 kun je vermenigvuldigen met 2

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
OK, net iets ontdekt wat de zaak alweer wat versimpelt: ik kan via de BASS-API zo aan een FFT komen:
quote: BASS Api Docs
BASS_ChannelGetData
Retrieves the immediate sample data (or an FFT representation of it) of a playing stream, or MOD music channel. Can also be used with the recording channel.

DWORD WINAPI BASS_ChannelGetData(
DWORD handle,
void *buffer,
DWORD length
);


Parameters
handle The channel handle... a HMUSIC, HSTREAM, or RECORDCHAN.
buffer Location to write the data... can be NULL when handle = RECORDCHAN, to discard the requested amount of data from the recording buffer.
length Number of bytes wanted, or one of the following flags.
BASS_DATA_FFT512 512 sample FFT (returns 256 floating-point values)
BASS_DATA_FFT1024 1024 sample FFT (returns 512 floating-point values)
BASS_DATA_FFT2048 2048 sample FFT (returns 1024 floating-point values)
BASS_DATA_FFT512S stereo 512 sample FFT (returns 512 floating-point values)
BASS_DATA_FFT1024S stereo 1024 sample FFT (returns 1024 floating-point values)
BASS_DATA_FFT2048S stereo 2048 sample FFT (returns 2048 floating-point values)
BASS_DATA_AVAILABLE Query the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be NULL when using this flag.


Return value
If an error occurs, -1 is returned, use BASS_ErrorGetCode to get the error code. If successful, the number of bytes actually read from the channel will be returned, or the number of bytes available when using the BASS_DATA_AVAILABLE flag.

Error codes
BASS_ERROR_HANDLE handle is not a valid channel.
BASS_ERROR_NOPLAY The channel is not playing, or is stalled (internet file stream). When handle is a "decoding channel", this indicates that it has reached the end.
BASS_ERROR_ILLPARAM length is invalid.
BASS_ERROR_NOTAVAIL Stereo FFT data is being requested, but the channel is mono. Or the BASS_DATA_AVAILABLE flag was used with a decoding channel.
BASS_ERROR_MEM There is insufficent memory.
BASS_ERROR_BUFLOST Should not happen, but... PLEASE REPORT IT IF YOU DO GET THIS ERROR!


Remarks
This function can only return as much data as has been written to the channel's buffer, so it'll not always be possible to get the amount of data requested, especially if you request large amounts. If you really do need large amounts, then increase the buffer lengths (BASS_SetBufferLength). The BASS_DATA_AVAILABLE flag can be used to check how much data a channel's buffer contains.

When retrieving the sample data from a "decoding channel" (BASS_STREAM_DECODE or BASS_MUSIC_DECODE was used at creation), there are no intermediate buffers involved, so as much data as is available can be decoded in one go. But if there are other channels playing at the same time, then requesting too large amounts could cause the playing channels to skip.

Unless requesting FFT data, the returned sample data is in the standard Windows PCM format: 8-bit samples are unsigned, 16-bit samples are signed.

When requesting FFT data, floating-point values ranging from 0 to 1 are returned. Only the first half of the FFT is useful, so that's what BASS returns. For example with a 2048 sample FFT, it'll return 1024 values - the 1st value being the DC component, the 2nd the amplitude at 1/2048 of the channel's sample rate, then the amplitude at 2/2048, 3/2048, etc... A Hanning window is applied to the sample data to reduce leakage.

Stereo channels may have mono or stereo FFT performed. When requesting mono FFT data, the left and right channels are combined. When requesting stereo FFT data, separate left and right FFT are performed (therefore twice the processing), and the return values are interleaved (left,right,left,etc...).

This function is most useful if you wish to visualize (eg. spectrum analyze) the sound
Scheelt alweer een hoop volgens mij...

  • DaCoTa
  • Registratie: April 2002
  • Laatst online: 14:08
.oisyn schreef op 14 January 2003 @ 18:29:Over het algemeen ligt de bpm tussen de 120 en de 240. Een waarde groter dan 240 zal je dus net zo lang door 2 kunnen delen tot het hiertussen ligt, en een waarde kleiner dan 120 kun je vermenigvuldigen met 2
Of je kunt gaan zoeken naar een herhalen patroon op een iets grotere schaal, zodat je inderdaad het ritme van het nummer te pakken hebt.

  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Adion schreef op 14 January 2003 @ 18:20:
Ik ben zelf ook al een tijdje bezig met m'n eigen bpm detectie voor mijn dj programma djDecks en ik moet zeggen dat het ondertussen best wel redelijk goed werkt.
Op deze site kan je mijn ocx downloaden die aan de hand van het spectrum van de muziek (dus nadat je de fft hebt uitgevoerd) de bpm kan bepalen.
Ik ben momenteel bezig aan een dll die de bpm detectie doet, en ook de fft analyze uitvoert.
Deze gaat standaard wel voor de fmod library werken, maar waarschijnlijk ook bruikbaar zijn in bass.

Hoe ik de detectie heb aangepakt is eerst een fft analyze doen per 1024 samples, zodat je dus een array krijgt waar ipv 1024 samples, 512 frequencywaardes instaan, van 1-22050Hz (oftewel je sampling frequentie/2).
Als de eerste waardes in deze array dus groot worden, betekend dit dat de lage tonen op dat moment sterk aanwezig zijn.

Je kan dus in de laagste waarden zoeken naar pieken, en aannemen dat elke piek een beat is.
Met behulp van de tijd tussen 2 beats kan je dan de bpm bepalen.

Omdat dit niet erg exact is, zal je beter de tijd tussen 10 beats nemen en delen door 10.
Je zal waarschijnlijk ook de gevonden beats moeten bekijken en beats die te dicht bij een andere beat liggen verwijderen, en mogelijk veronderstellen dat er tussen twee beats met te grote tijd ertussen zich toch een beat bevond die niet gededecteerd werd.

Hopelijk heeft dit je al een beetje op weg geholpen!
* MisterData is dan maar begonnen met een poging :)
Ik heb nu dus een float[512] met daarin de waardes waar je het over hebt. Maar wat bedoel je precies met 'eerste waardes' ? van 0-128 ofzo?

Verder, hoe kan ik het beste een piek vinden? Ik kan van alle waardes het gemiddelde berekenen en dan kijken welke er (ver) boven zitten, maar hoever is ver? maw, met welke parameters kriig je de beste resultaten?

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
Met de eerste waardes bedoel ik van 0-5 ongeveer.
Als je namelijk even uitrekend : 22050Hz verdeeld over 512 waardes betekend 43Hz per waarde.
De eerste 6 nemen betekend dus het gebied tot 260Hz ongeveer, en daar zitten de meest regelmatige en detecteerbare beats (in techno, house, trance, ... muziek dan toch)

Een piek vinden kan je doen door gewoon een maximum bij te houden, als er een waarde boven 0.9 * maximum uitkomt kan je dat als beat rekenen.
Om te zorgen dat je maximum actueel blijft doorheen het nummer kan je het maximum langzaam opnieuw laten dalen, tenzij natuurlijk dat het overschreven wordt door een nieuw maximum.

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Goed, ik heb nu een methode die peeks filtert (of tenminste zou moeten, ik heb het nog niet geprobeerd) en eentje die uit de piek-gegevens de BPM berekent:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class CBPMInfo {
    public: 
        float lastpeeks[10]; // laatste peeks die zijn gedetecteerd
        float lastpeekspos[10]; // posities van de laatste peeks, milliseconden?
        int coffset;
        float bpm; // BPM zoals de methode dat heeft geschat
        unsigned int certaincy; // hoe zeker zijn we van onze zaak? 0-100
        
        CBPMInfo() {
            coffset = 0;
            bpm = 0.0f;
            certaincy = 0;
            for(int a=0;a<10;a++) {
                lastpeeks[a] = 0.0f;
            }
        }

        ~CBPMInfo() {
            bpm = 0;
            coffset = 0;
            certaincy = -1;
        }

        inline void RegisterPeek(float peek, float curpos) {
            lastpeeks[coffset] = peek;
            lastpeekspos[coffset] = curpos;

            coffset++;
            if(coffset==11) {
                coffset = 0;
            }
        }

        inline void CalcBPM() {
            // nu es kijken wat we met die pieken kunnen
            float timeBetweenFirstAndLast = lastpeekspos[coffset] - lastpeekspos[0];
            bpm = 60* timeBetweenFirstAndLast / coffset;
        }
};


Heb het maar gewoon even vies in de .h file gedaan, ik weet dat ik alle methodes normaalgesproken in een .cpp moet douwen, maarja dat doe ik later wel

Hier nog even mijn piekfilterfunctie:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
void CALLBACK BEATDETECT(HDSP handle, DWORD channel, void* buffer, DWORD user) {
    // here we go.....
    CJukeboxView* view = (CJukeboxView*)user;


    if(!(handle==view->_playerA||handle==view->_playerB)) {
        return;
    }

    float curpos = BASS_BASS_ChannelBytes2Seconds(channel,BASS_ChannelGetPosition(channel));


    CBPMInfo* info;
    // even kijken waar we de info in kunnen planten
    if(handle==view->_playerA) {
        info = &view->_bpmA;    
    }
    else {
        info = &view->_bpmB;
    }

    // FFT'tje maken alsof het nix is.....
    float fft[512];
    BASS_ChannelGetData(handle, &fft, BASS_DATA_FFT1024);

    // nu es even kijken of we een piek ergens hebben
    float med, total;
    float highest, lowest;

    // pieken eruitfilteren
    for(int a=0;a<6;a++) {
        float c = fft[a];
        total += c;
        if(highest<c) {
            highest = c;
        }
        if(lowest>c) {
            lowest = c;
        }
    }
    med = total/6;

    float peek = 0;
    for(a=0;a<128;a++) {
        float c = fft[a];
        if(c>med&&c<highest&&c>peek) {
            // we have a peek!
            peek = c;
        }
    }

    if(peek==0) {
        // nix gevonden, dus we weten het niet zeker
        return;
    }
    else {
        // we hebben een peek, even aanmelden bij onze grote vriend CBPMInfo, die doet de rest als het goed is
        info->RegisterPeek(peek, curpos);
    }
}


Voor de kenners: CJukeboxView verwijst naar een door de WTL-classwizard gegenereerde class waarin alle informatie over de twee players (A en B) wordt bijgehouden.

Wat ik van jullie wil weten: gaat dit werken? Ben ik op de goede manier bezig?

[ Voor 4% gewijzigd door MisterData op 14-01-2003 20:04 . Reden: uhmzz ResetFlangerParams heeft niet echt veel met BPM te maken :O ]


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
In het begin gebruik je enkel de laagste waarden, maar daarna zoek je alsnog je maximum in de hogere frequenties ook?
Ik zou gewoon in je eerte for lus (van 0 tot 5) doen :

if (c > highest * 0.9)
peek = c;

Je moet er dan nog wel aan denken dat je het stijgen en het dalen zelf eigenlijk niet mee mag tellen.
Dus als highest = 1, en je krijgt achtereenvolgens :
0.5 0.9 0.95 .098 0.94 0.8, dan wil je eigenlijk enkel een beat registreren bij 0.98

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Adion schreef op 14 januari 2003 @ 20:12:
In het begin gebruik je enkel de laagste waarden, maar daarna zoek je alsnog je maximum in de hogere frequenties ook?
Ik zou gewoon in je eerte for lus (van 0 tot 5) doen :

if (c > highest * 0.9)
peek == c;

Je moet er dan nog wel aan denken dat je het stijgen en het dalen zelf eigenlijk niet mee mag tellen.
Dus als highest = 1, en je krijgt achtereenvolgens :
0.5 0.9 0.95 .098 0.94 0.8, dan wil je eigenlijk enkel een beat registreren bij 0.98
Klopt, de tweede for loop moet dezelfde parameters hebben als de loop daarvoor :) Verder: waarom highest*0.9? Kan ik niet gewoon simpelweg de hoogste pakken? Het gaat er toch om dat ik van een setje samples (1024) een spectrum krijg (das die fft array), en dat ik moet uitmaken of het een beat is of niet?

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
highest * 0.9 heb ik zelf gedaan omdat niet alle beats exact hetzelfde zijn, als 1 je maximum is wil het niet zeggen dat ELKE beat tot 1 zal geraken, sommigen zullen slechts tot 0.95 komen bijvoorbeeld.

Waar ik zelf veel uit geleerd heb is gewoon de 5 laagste fft waardes telkens naar een file schrijven, zodat je een file hebt die per callback 1 regel schrijft zoals :
0.5 0.4 0.59 0.8 0.4

Als je dit een dertigtal seconden laat doen bij een aantal 'eenvoudige' liedjes, en je opent daarna de file in excel ofzo, en je maakt er een grafiekje van, wordt het iets duidelijker hoe de pieken er praktisch uitzien enzo.

edit:
Ik zie net dat je in jou code highest enzo lokaal hebt gedefinieerd, maar op die manier kan je natuurlijk nooit de waardes die je op 1 moment hebt vergelijken met de waardes op een volgend moment

[ Voor 16% gewijzigd door Adion op 14-01-2003 20:23 ]

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Adion schreef op 14 januari 2003 @ 20:19:
highest * 0.9 heb ik zelf gedaan omdat niet alle beats exact hetzelfde zijn, als 1 je maximum is wil het niet zeggen dat ELKE beat tot 1 zal geraken, sommigen zullen slechts tot 0.95 komen bijvoorbeeld.
ik snap :)
edit:
Ik zie net dat je in jou code highest enzo lokaal hebt gedefinieerd, maar op die manier kan je natuurlijk nooit de waardes die je op 1 moment hebt vergelijken met de waardes op een volgend moment
Ik begrijp dat ik die highest-waarde het beste gewoon bij de CBPMInfo-class erbij kan donderen?

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
ja, dat lijkt me inderdaad het beste

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Een 512-point sample heeft een range van -22Khz tot +22Khz, niet 0-22 Khz. Dus 1/512 daarvan is ongeveer 100 Hz. Een BPM van 120-240 is 2-4 Hz, dus dat valt zeker in samples 0 en 1. Kortom, als je het zo opzet werkt het niet.

Wat je wel kunt doen is een 5000-punt gemiddelde te nemen, en dat als signaal te Fourier Transformeren. Daardoor krijg je een range van -4.4 Hz tot +4.4 Hz. 1/512 daarvan is al minder dan 0.02 Hz.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
MSalters schreef op 14 January 2003 @ 22:21:
Een 512-point sample heeft een range van -22Khz tot +22Khz, niet 0-22 Khz. Dus 1/512 daarvan is ongeveer 100 Hz. Een BPM van 120-240 is 2-4 Hz, dus dat valt zeker in samples 0 en 1. Kortom, als je het zo opzet werkt het niet.

Wat je wel kunt doen is een 5000-punt gemiddelde te nemen, en dat als signaal te Fourier Transformeren. Daardoor krijg je een range van -4.4 Hz tot +4.4 Hz. 1/512 daarvan is al minder dan 0.02 Hz.
Nou snap ik het niet meer....:?

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Elk punt in een FFT komt overeen met de energie in een frequentieband, en halverwege de range switch je van de hoogst naar de laagste frequentie. Voor je audio is dat typisch 0 -+22 Khz gevolgd door -22 Khz - 0. Dat wil dus zeggen dat de eerste float de energie geeft in frequentieband 0 tot(22000/256) Hz, de tweede in (22000/256) tot 2*(22000/256), etcetera. Dat is dus 0 tot 86 Hz, 86-172 Hz, etcetera.

120 BPM is 2 Hz, 240 BPM is 4 Hz. Er is dus geen verschil in de eerste float van de 512-punts FFT, alleen het volume heeft invloed.
Wat je dus wil bereiken id dat je hoogste relevante frequentie midden in je FFT uitkomt. Dit bereik je door je input sequence te verkorten. Als je een nieuw signaal produceert waarbij de lengte de helft is, en elk punt het gemiddelde van 2 punten naast elkaar, dan is je hooste frequentie gehalveerd:

code:
1
2
-1  0   1   2   1   0  -1  -2  -1   0   1   2   1   0  -1  -2  -1   0
 -0.5    1.5     0.5    -1.5    -0.5     1.5     0.5    -1.5    -0,5

De frequentie van de bovenste regel is 1/8, de frequentie van de onderste 1/4.

Als je N punten middelt, dan neemt je hoogste frequentie met een factor N af. In jouw geval is je hoogste input frequentie 22 Khz, je hooste output frequentie moet ongeveer 240BPM = 4 Hz zijn dus je moet ca. 5500 punten middelen. Dan is elke float in je 512-punts FFT dus de energie van een frequentieband van ( 8 Hz/512 )=(4 Hz/256 ).

[ Voor 3% gewijzigd door MSalters op 15-01-2003 10:33 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
Je uitleg klopt niet 100%.
Ten eerste staat bij de uitleg in bass :
BASS_DATA_FFT1024 1024 sample FFT (returns 512 floating-point values)

Dus van 1024 samples doet hij een fft, maar hij geeft slechts 512 waardes terug, zijnde het spectrum tussen 1 en 22kHz

Ten tweede klopt het niet dat je kan gaan zoeken naar een frequentie van 2Hz, want een fft zoekt naar sinussen/cosinussen, en NIET naar beats.
Een beat ziet er namelijk als volgt uit (ongeveer dan) :
code:
1
___/\___/\____/\____

Terwijl een sinus zich over het hele gebied verspreid.
Komt daar nog bij dat om zo'n lage frequenties nauwkeurig te bepalen een toch wel tamelijk grote fft nodig is.

Mijn methode werkt door het spectrum te gebruiken om lage tonen (hoorbare bassen) te zoeken, en niet om een herhalend patroon te zoeken.

Het zoeken naar een herhalend patroon is in mijn versie een tweede stap, namelijk herhaling zoeken in de gevonden beats.

Er bestaat wel een methode gelijkaardig aan een fft genaamd een waveform transform, waarbij je zelf een golfvorm kan opgeven om naar te zoeken, in plaats van een sinus/cosinus.
Het nadeel hiervan is dat niet alle beats hetzelfde zijn of klinken, en dat deze methode waarschijnlijk erg intensief is en mogelijk niet realtime gebruikt kan worden.

edit:
Ik heb de uitleg van MSalters nog eens doorgelezen, en ik snap nu wel de werkwijze, en ik zie nu wel dat die ook wel kan werken. Het lijkt mij wel dat het zou kunnen dat juist omdat je een gemiddelde van 5000 punten neemt, je waardes tijdens een beat minder duidelijk zouden kunnen zijn, omdat je bijvoorbeeld voor punt 1 een eerste helft van een beat, en voor punt 2 de tweede helft krijgt. Dit betekend dat de beat er minder duidelijk uit gaat springen.
Een tweede nadeel van deze werkwijze is dat je informatie verliest over WANNEER de beat plaats vond, wat in veel programma's minstens zo nuttige informatie is (denk maar aan het automatisch matchen van 2 liedjes, of lichten die je niet alleen even snel, maar ook op hetzelfde moment wilt doen flitsen)


Nog maar even een edit :
Ik heb even gedaan wat ik een paar posts geleden gezegd heb: van elke nieuwe fft (van 1024 samples) heb ik de laagste waarden samen met de tijd in milliseconden in een file geschreven.
Deze heb ik geopend in excel en daar een scatter-plot van gemaakt.
Het resultaat :
Afbeeldingslocatie: http://users.esstec.be/adion/temp/bpmdetect.gif
Dit stelt de bas van seconde 5 tot 10 van dj tiesto - lethal industry voor.
De eerste beat ligt op 5250 milliseconden, 4 beats later zitten we aan 7050 ongeveer. Het verschil is 1800 ms, of 450 per beat.
Er zijn 60000 milliseconden in een minuut, dus 60000/450 = 133.333 bpm.
De werkelijke bpm van dit nummer is 135 bpm, dus gezien ik de waardes slechts geschat heb aan de hand van deze tekening, kan je aannemen dat als je de echte waardes gebruikt, en eventueel ook meer als 4 beats telt, dat je al snel een goede benadering uitkomt.

[ Voor 44% gewijzigd door Adion op 15-01-2003 13:40 ]

VirtualDJ 2026 - Fast Image Resizer - Instagram


Verwijderd

Okee, om mezelf een hele hoop typewerk te besparen :

Heb je mijn posts op het BASS-forum al gelezen ?
Ik heb daar een behoorlijk uitgebreide lezing over beatdetectie gegeven.
Ik zag dat er ergens in het begin van deze thread ook al naar een uitspraak van mij verwezen was...


Anyway, lees het werk van Masataka Goto over Onset-detectie etc., danben je al een heel eind.

Denk niet dat beatdetectie iets simpels is, tenzij je het alleen wilt gebruiken voor standaard house-muziek (dan is een lowpass-filter meestal al voldoende).

Beatprediction gaat dan weer een stapje verder natuurlijk - je kan het zo moeilijk maken als je zelf wilt.

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
Ik heb jou posts eens opgezocht en gelezen, en het klopt inderdaad dat beat detectie meer is dan alleen maar bass-detectie.
Ik wil echter wel zeggen dat het voor de meeste muziek die je wilt beatmatchen en beatmixen goed genoeg werkt.
Je zegt ook in je post dat hiphop gemakkelijk te detecteren is, maar dat vond ik tot nog toe moeilijker omdat de bassdrum bij hiphop zelden 4/4 verdeeld is.
Hoe heb je dit dan opgelost? Waar ik al heb aan zitten denken is van een reeks gevonden beats over elkaar te schuiven en te kijken waar je een herhaling van een patroon hebt.
Ditzelfde kun je dan ook herhalen voor de hihats, en zo zou je tot een redelijk zeker resultaat kunnen komen.

Zelf gebruik ik op dit moment 2 methodes, de eerste is gewoon gebaseerd op bass detecteren, en de 2de zet eerst het spectrum om van 512 waardes naar 16 waardes, en dan zoek ik in elk van die 16 waardes naar herhalingen (dus je doorloopt alle bpm's van 80 tot 200 bijvoorbeeld, en je maakt het verschil tussen de samples in de eerste 4 maten en in de volgende 4 maten)
Met deze methode komen ook dnb, rnb, rock, hiphop enzo bij de lijst van genres die ik tamelijk goed kan detecteren.
Alleen muziek zonder echte vorm van herhalend ritme lukken nog totaal niet.

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
Hartstikke goed, wist niet dat er ook BASS-guru's hier rondhingen _/-\o_ Dankzij jullie uitleg ben ik alweer een heel eind (alhoewel ik merk dat als je er lang mee bezig bent je dan fouten gaat maken B) 8)7). Ik ga es kijken of ik iets in excel kan maken met die getallen, zoals Adion al voorstelde. Verder hoeft het natuurlijk niet 100% te werken, tis geen professioneel software-pakket wat ik aan het schrijven ben ;) Zodra ik iets werkend heb post ik hier natuurlijk nog wel een screenshotje oid.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Systemen&Signalen was m'n eerste vakje aan TU Delft, gegeven door m'n latere afstudeerprof, en daarna heb ik m'n eerste grote zelfstandige practicum gedaan over frequentie-zoeken, dus ik ken dit nog wel.
Dus:
Een "beat" is inderdaad geen scherpe sinus is. Het is een combinatie van een aantal sinussen, "boventonen". Dus een 2Hz beat heeft een kleinere peak bij 4 Hz, nog kleiner bij 6Hz, 8Hz etc. De verhouding bepaalt de vorm van een enkele piek, maar dat is niet relevant.
Sterker nog, als niet elke piek hetzelfde is (zie grafiekje) dan heeft dat nauwelijks invloed op de exacte locatie van de 2/4/6/8 Hz pieken ->minder gevoelig.

Zoals mijn voorbeeld laat zien raak je inderdaad door het middelen de scherpste pieken kwijt. Dan maakt helemaal niets uit nadat je de Fourier Transformatie hebt gedaan - scherpe pieken in de Fourier Transformatie worden alleen veroorzaakt door een periodiciteit.

De exacte locatie van de pieken volgt in principe uit de phase van de piek; een FFT levert eigenlijk 2 floats per frequenteiband op waarbij de tweede float een shift aangeeft. ( = verhouding sinus/cosinus, sinus begint op 0, cosinus begint op 1 )
Maar je kunt natuurlijk ook gewoon een parabool fitten aan de piek, en kijken waar de top zit, als je FFT formule weigert die tweede float terug te geven.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Oh, Adion, over je edit: Wat jij beschrijft, dat een beat precies op de grens van twee samples valt, dat is dus de reden dat je >2 samples/frequentie nodig hebt. Daardoor krijg je maar 512 floats terug bij een 1024-point sample, met relatieve frequenties 0/512, 1/512 t/m 255/512, dus net minder dan de helft van de sample frequentie
Voor google: dit heet de Nyquist frequentie.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
Heb je deze methode ooit effectief getest of ken je een programma dat deze methode gebruikt om de bpm te detecteren?
Ik zit nu in de examens, maar als ik daarna nog eens wat tijd heb denk ik wel dat ik deze methode eens ga proberen.

Edit:
Wat ik met de vorige edit bedoelde was het volgende:
Zoals je op mijn grafiek ziet is een beat gemiddeld ongeveer 200 milliseconden lang.
Als je nu van 5000 samples het gemiddelde neemt dan heb je een gemiddelde over 125 ms ongeveer (1024 samples = 23... ms)
Stel dat de 5000 samples nu juist overeen komen met het eerste deel van een beat en de volgende 5000 met het 2de deel, dan zal het gemiddelde van beiden ongeveer 0.6 ofzo zijn, je krijgt dus 0.2 0.6 0.6 0.2 ofzoiets als waardes rond die beat, waar je dus achteraf een fft op gaat doen.
Als nu die 5000 samples op de beat liggen, is het gemiddelde daar waarschijnlijk 0.8 en krijg je dus 0.2 0.3 0.8 0.2 als waardes die naar je fft zullen gaan.
Ik weet niet tot in hoeverre dit uitmaakt, maar ik verwacht toch dat dit de fft niet gaat verduidelijken?
Het is dus misschien interessanter van over 2000 samples gemiddeldes te nemen, maar dan wel op een groter data-gebied de fft doen?

[ Voor 68% gewijzigd door Adion op 15-01-2003 20:57 ]

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Adion, ik geloof dat je het kernidee van een FFT mist. Een FFT doe je niet op een piek, een FFT doe je op het hele signaal. Juist doordat de ene piek net op een grens valt, en een andere niet, kun je een piekafstand bepalen met een resolutie groter dan de samplefrequentie.

In je signaal zou de beat-beat afstand 1000 ms / (135 bpm / 60 ) = 444 ms moeten zijn, ik denk dat je ergens een factor 2 hebt gemist. Je hebt tenslotte ook 5000 msec signaal met 11 beats, 5000/11 != 200.
Je sample grootte moet dus ca. <200 ms zijn volgens het Nyquist criterium, dat is 5 Hz. Omdat je normaal gesproken niet weet dat het 135 BPM is, alleen dat het <240 BPM is moet je kleinere samples nemen, 240 BPM=4 Hz signaal = 8Hz sampling = (44Khz/8Hz) = 5000 points/sample, 125 msec.

Als je daar een 512-punt FFT mee maakt heb je dus een FFT van een minuut input, en gebruik je 135 pieken en (135*134/2) = 2345 piek-piek afstanden. Vandaar dat je met de FFT een resolutie van zo'n 4Hz/256 cq. 8Hz/512 haalt, zo nauwkeurig krijg je het anders niet.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
Ik ga het nog eens grondig moeten bestuderen voor ik het helemaal snap denk ik :)

De beat-afstand is inderdaad 444 ms, maar de beat zelf duurt maar een 200 ms, je hebt dus 200 ms beat, 200 ms stilte, 200 ms beat, 200 ms beat, ...

Je originele 44KHz sample data gaat dus (als er enkel een beat zou zijn) 200 ms (~8000 samples) hoger zijn, en 200 ms lager (bij de stilte dus)

Om met een 512-punt fft toch een nauwkeurig frequentiegebied van 8/512 Hz te kunnen bepalen, beperk je de sampling frequentie tot 8Hz door het gemiddelde te nemen over 5000 input-samples (down-sampling dus).

Als deze 5000 punten midden in het hoogtepunt van de beat liggen, dan zal die 8Hz sample een erg hoge waarde hebben, liggen deze punten echter zo dat ze slechts een deel van de oppervlakte onder de beat nemen, dan zal het gemiddelde (samen met nog wat stilte van voor de beat) veel lager liggen.
Misschien verduidelijkt het volgende wat ik er niet helemaal aan snap :
Oorspronkelijke Samples : _____/--\_____/--\_____/--\_____/--\___
Downsampling intervallen: _|__|__|__|__|__|__|__|__|__|__|__|__
Samples @ 8Hz _______: __ .0_.7_.3_.0_ .8_.2_.0_ .9_.0_.1_.8_.0

Ik vraag me dus voornamelijk af of een fft met deze waardes nog wel duidelijk genoeg herhalingen gaat vinden.
Of komt dit toch nog goed omdat er 512 van dit soort samples zijn, die over 512 samples wel duidelijk herhalen?

Zoals ik al gezegd heb moet ik misschien wel alles nog eens nalezen en daarna eens proberen deze methode te implementeren en kijken of er inderdaad nauwkeurige resultaten uitkomen.

edit:
Door het schrijven van dit bericht is denk ik het principe van fft me al iets duidelijker geworden, maar ik zou toch eerst nog eens moeten testen wat een fft doet met een opeenvolging van pieken


Edit2: Waar ik ook nog aan denk: hoe moet je het gemiddelde nemen? Normaalgezien is sampledata namelijk signed van -2^15 tot +2^15, maar omdat geluid uit golven bestaat, gaat het gemiddelde over een grotere tijd (dus > laagst hoorbare frequentie = +- 20Hz) 0 zijn...
Moet dus het gemiddelde van de absolute waardes genomen worden?

Edit3: Deze methode werkt dus inderdaad.
Ik heb nog niets echt geprogrammeerd, maar ik heb in cool edit eens een liedje geopend, het gedownsampled naar 16Hz, en hierop een fft analyze van 2048 samples gedaan, dan tussen 1 en 4 Hz de hoogste top gekozen, en dit vermenigvuldigt met 60.
1 liedje was techno, en daar vond ik 138 bpm, wat klopte, en het 2de is drum'n bass, en ik vond 175 bpm, wat ook klopt denk ik.
De methode had wel enkel success als ik bij het downsamplen de pre-filter optie aanzet.
Volgens de help over deze optie voorkomt deze optie dat er 'valse' lage tonen worden gegenereerd, maar er staat niet echt op welke manier dit voorkomen wordt.
Ik vrees dus dat enkel het gemiddelde nemen niet voldoende zal zijn, maar dat er ook nog een filter over moet.

[ Voor 40% gewijzigd door Adion op 16-01-2003 17:09 ]

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

[nohtml]
MSalters schreef op 15 January 2003 @ 10:31:
120 BPM is 2 Hz, 240 BPM is 4 Hz. Er is dus geen verschil in de eerste float van de 512-punts FFT, alleen het volume heeft invloed.
volgens mij klopt het niet wat je zegt. Of tenminste, wat je zegt klopt wel, maar is niet toepasbaar voor het probleem van beatdetectie ;)

Nou heb ik me er nog niet echt in verdiept, dus misschien lul ik maar wat, maar je moet de beats niet zien als een toon ergens tussen de 2 en 4 Hz. Het is natuurlijk waar dat de tikken van de bassdrum idd ongeveer tussen de 2 en de 4 Hz liggen, maar er zal geen toon op die frequentie te horen zijn. Het is dan ook totaal niet van belang om dat frequentiebereik te controleren. Waar het om ging is dat je de bassdrum eruit filtert, wat voornamelijk uit lage tonen bestaat. Als je dan de opgaande flank van die tonen neemt heb je ongeveer een idee van wanneer het begin van de bassdrum ongeveer te horen is. Dit doe je voor zo'n zeg 5 tot 10 seconden aan muziek, zodat je er een ritme in kan ontdekken. Een zo'n herhaling van dat ritme is een sequence, en een sequence bestaat over het algemeen uit 4, 8 of 16 beats (mits het een 4/4e maat is, wat over het algemeen altijd zo is bij moderne muziek :)).

Maar goed, wat ik dus wil zeggen is dat het me totaal niet van belang lijkt om zo'n laag frequentiebereik te analyseren omdat je daar simpelweg niets mee opschiet

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MisterData
  • Registratie: September 2001
  • Laatst online: 22-08 19:41
* MisterData has lost it :/

Als ik weer es wat tijd heb stort ik me er wel weer op ;)

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Adion schreef op 16 January 2003 @ 16:29:
Ik ga het nog eens grondig moeten bestuderen voor ik het helemaal snap denk ik :)

De beat-afstand is inderdaad 444 ms, maar de beat zelf duurt maar een 200 ms, je hebt dus 200 ms beat, 200 ms stilte, 200 ms beat, 200 ms beat, ...

Je originele 44KHz sample data gaat dus (als er enkel een beat zou zijn) 200 ms (~8000 samples) hoger zijn, en 200 ms lager (bij de stilte dus)

Om met een 512-punt fft toch een nauwkeurig frequentiegebied van 8/512 Hz te kunnen bepalen, beperk je de sampling frequentie tot 8Hz door het gemiddelde te nemen over 5000 input-samples (down-sampling dus).

Als deze 5000 punten midden in het hoogtepunt van de beat liggen, dan zal die 8Hz sample een erg hoge waarde hebben, liggen deze punten echter zo dat ze slechts een deel van de oppervlakte onder de beat nemen, dan zal het gemiddelde (samen met nog wat stilte van voor de beat) veel lager liggen.
Misschien verduidelijkt het volgende wat ik er niet helemaal aan snap :
Oorspronkelijke Samples : _____/--\_____/--\_____/--\_____/--\___
Downsampling intervallen: _|__|__|__|__|__|__|__|__|__|__|__|__
Samples @ 8Hz _______: __ .0_.7_.3_.0_ .8_.2_.0_ .9_.0_.1_.8_.0

Ik vraag me dus voornamelijk af of een fft met deze waardes nog wel duidelijk genoeg herhalingen gaat vinden.
Of komt dit toch nog goed omdat er 512 van dit soort samples zijn, die over 512 samples wel duidelijk herhalen?
Precies; het zijn de herhalingen die het spectrum zuiver houden. Zou je een enkele piek hebben, dan wordt het fourierspectrum volledig uitgemeerd (geen periode meer), zijn het er twee, dan is het spectrum bijna volledig uitgesmeerd, en heb je oneindig veel (identieke) beats dan heb je volledig zuivere pieken.
Edit2: Waar ik ook nog aan denk: hoe moet je het gemiddelde nemen? Normaalgezien is sampledata namelijk signed van -2^15 tot +2^15, maar omdat geluid uit golven bestaat, gaat het gemiddelde over een grotere tijd (dus > laagst hoorbare frequentie = +- 20Hz) 0 zijn...
Moet dus het gemiddelde van de absolute waardes genomen worden?
Dat naar 0 middelen is dus precies waardoor de frequenties >4 Hz verdwijnen, maar die hebben niets met de beat te maken. Opzet dus.
Edit3: Deze methode werkt dus inderdaad.
Ik heb nog niets echt geprogrammeerd, maar ik heb in cool edit eens een liedje geopend, het gedownsampled naar 16Hz, en hierop een fft analyze van 2048 samples gedaan, dan tussen 1 en 4 Hz de hoogste top gekozen, en dit vermenigvuldigt met 60.
1 liedje was techno, en daar vond ik 138 bpm, wat klopte, en het 2de is drum'n bass, en ik vond 175 bpm, wat ook klopt denk ik.
De methode had wel enkel success als ik bij het downsamplen de pre-filter optie aanzet. Volgens de help over deze optie voorkomt deze optie dat er 'valse' lage tonen worden gegenereerd, maar er staat niet echt op welke manier dit voorkomen wordt. Ik vrees dus dat enkel het gemiddelde nemen niet voldoende zal zijn, maar dat er ook nog een filter over moet.
Ik gok dat punten dicht bij de grens minder zwaar worden gewogen bij de middeling (=filter) voordat je op die gemiddelden de FFT loslaat. Dat heeft (maar da's echt ingewikkeld, en ik twijfel zelf ook) te maken met wiskundige afrondverschijnselen/beperkte precisie. Het maakt nogal uit in welk sample een piek precies valt, maar als je'm uitfiltert heeft de piek weinig impact.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
.oisyn schreef op 16 januari 2003 @ 18:05:
volgens mij klopt het niet wat je zegt. Of tenminste, wat je zegt klopt wel, maar is niet toepasbaar voor het probleem van beatdetectie ;)
Vervelend he , die edits later dat het wel werkt >:)
Nou heb ik me er nog niet echt in verdiept, dus misschien lul ik maar wat, maar je moet de beats niet zien als een toon ergens tussen de 2 en 4 Hz. Het is natuurlijk waar dat de tikken van de bassdrum idd ongeveer tussen de 2 en de 4 Hz liggen, maar er zal geen toon op die frequentie te horen zijn.
Dat is een kwestie van taalgebruik. Boven de 20 Hz noemen we het geluid, onder de 4 Hz Beats.
Het is dan ook totaal niet van belang om dat frequentiebereik te controleren. Waar het om ging is dat je de bassdrum eruit filtert, wat voornamelijk uit lage tonen bestaat. Als je dan de opgaande flank van die tonen neemt heb je ongeveer een idee van wanneer het begin van de bassdrum ongeveer te horen is. Dit doe je voor zo'n zeg 5 tot 10 seconden aan muziek, zodat je er een ritme in kan ontdekken.
Maar goed, wat ik dus wil zeggen is dat het me totaal niet van belang lijkt om zo'n laag frequentiebereik te analyseren omdat je daar simpelweg niets mee opschiet
Helaas werkt je methode lang niet altijd. Het is dat die techno zo'n ontzettend harde beats heeft, anders had je ze helemaal niet kunnen onderscheiden van normaal geluid.
Mijn methode werkt dus wel, omdat die beats nou eenmaal in dat frequentiebereik liggen. Voor het stukje van 5 seconden met 11 beats gebruik ik effectief 50 piek-piek afstanden, jouw methode gebruikt er maar 10.

Ter vergelijking: ik heb bij een Natuurkunde practicum de eigenfrequenties lopen bepalen van een geluidsgolf in een buis met vernauwing. Dat is een rottig effect; de boventonen zijn geen harmonischen meer. De methode die ik daar in eerste instantie voor gebruikte was om simpelweg een ruisgenerator er op te zetten. Aan de andere kant komt er ook ruis uit. Alleen, als je daar een FFT op los liet, dan zie je dat de ingangsruis "wit" was (vlak spectrum), terwijl de uitgangsruis wel pieken had. De reden van de pieken in die FFT was dezelfde als de piek in het FFT van jouw signaal: Bij een bepaalde tijd hoort een bepaalde frequentie. In mijn geval was dat de tijd die de golf nodig had om van de ene kant naar de andere door de vernauwing heen te lopen. In dit geval is het de tijd tussen beats. f=1/T, de wiskunde blijft hetzelfde ook als de T verschilt.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
MSalters schreef op 16 januari 2003 @ 21:07:
Helaas werkt je methode lang niet altijd. Het is dat die techno zo'n ontzettend harde beats heeft, anders had je ze helemaal niet kunnen onderscheiden van normaal geluid.
Mijn methode werkt dus wel, omdat die beats nou eenmaal in dat frequentiebereik liggen. Voor het stukje van 5 seconden met 11 beats gebruik ik effectief 50 piek-piek afstanden, jouw methode gebruikt er maar 10.
Steund zelfs jou methode niet op duidelijke herhalingen van 1 beat lang?
Stel dat je muziek hebt zonder duidelijk ritme, of een ritme dat slechts duidelijk wordt per 4 tellen?
In dat geval zou je moeten gaan kijken naar het gebied rond 0.5 tot 1 Hz, maar om daar nauwkeurige resultaten over te krijgen moet je over erg lange tijd kijken.
In sommige gevallen zou ik denken dat het dan efficienter werkt als je telkens de eerste beat van 4 tellen detecteert, en dan zelf de bpm uitrekend.
Enkel piano-muziek ofzo lijkt mij op het eerste zicht zelfs met jou methode bijna onmogelijk, en wat als er enkel hihats ofzo zijn?

Je moet er ook aan denken dat de topicstarter zocht naar bpm detectie in een dj programma, en dat mixende dj's toch meestal elektronische muziek spelen die in 95% van de gevallen ofzo een beat heeft die duidelijk genoeg is om op die manier te herkennen.

De methode die ik hiervoor al beschreef is dezelfde die ik in mijn eigen dj-programma gebruik. Ik tel zelf tot maximaal 100 beats (met ook nog een algoritme om 'valse' dubbele of ontbrekende beats in een patroon van 4 te herkennen) en als je de tijd tussen 100 beats neemt dan heb je al een behoorlijke nauwkeurigheid.
Ik doe deze detectie ook afzonderlijk voor de 5 laagste banden van het spectrum dat ik bereken, en kies dan degene eruit met het beste resultaat.
Met deze methode vind ik voor de meeste nummers de bpm wel.

Ik ga natuurlijk wel proberen of ik die andere methode ook kan implementeren om zo ook van de resterende nummers de bpm te kunnen bepalen.

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

MSalters schreef op 16 January 2003 @ 21:07:
Dat is een kwestie van taalgebruik. Boven de 20 Hz noemen we het geluid, onder de 4 Hz Beats.
zo bedoelde ik het niet helemaal. Stel ik laat een korte toon van 500 Hz 2x per seconde afspelen. In principe zijn er dan alleen tonen van 500 Hz te vinden. Of ook in 2 Hz.

Of begreep ik je al helemaal verkeerd en bedoelde je helemaal niet dat je die lage frequentie gaat analyseren dmv FFT?
Ter vergelijking: ik heb bij een Natuurkunde bla bla bla .... bla bla bla vernauwing heen te lopen. In dit geval is het de tijd tussen beats. f=1/T, de wiskunde blijft hetzelfde ook als de T verschilt.


ah, ik was iets te voorbarig met mijn bovenstaande opmerking. Tx voor de opheldering :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
.oisyn schreef op 16 January 2003 @ 21:59:
zo bedoelde ik het niet helemaal. Stel ik laat een korte toon van 500 Hz 2x per seconde afspelen. In principe zijn er dan alleen tonen van 500 Hz te vinden. Of ook in 2 Hz.
Ik denk dat je bedoelt dat je een sinus van 500 Hz vermenigvuldigt met een blokgolf van 2 Hz, toch? Vermenigvuldigen in Tijdsdomein <=> convolutie in frequentiedomein, dus je FFT is de FFT van een 2Hz blokgolf verschoven over +500 /-500Hz. ( FFT van de 500HZ sinus is namelijk een dubbele puls).

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

--8<--

Dan zou ik namelijk gewoon eerst een goed laagdoorlaatfilter op het signaal los laten die tot zo'n 10Hz gaat of zo (afhankelijk van de stijl muziek ;) ), dan zou je toch wel de beat-frequenties moeten hebben... En dan zou je daar een veel nauwkeurigere FFT op los kunnen laten. Als dat nodig is tenminste, maar misschien wil je gewoon het beat-signaal uitfilteren?

--8<--

[ Voor 58% gewijzigd door Verwijderd op 17-01-2003 15:35 . Reden: was al gezegd, had ik niet gezien ]


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 22-08 13:44
Als je alles goed gelezen had is dit precies wat MSalters voorstelde :
Een fft op 1024 waardes heeft inderdaad een nauwkeurigheid van samplefrequentie / 1024, dus als je de samplefrequentie verlaagd, verhoogd de nauwkeurigheid.

VirtualDJ 2026 - Fast Image Resizer - Instagram


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Verwijderd schreef op 17 January 2003 @ 13:01:
In elk geval geldt volgens mij, dat je nooit een frequentie betrouwbaar zou kunnen meten die lager is dan <samperate> / <aantal samples per meting>, dus als je een samplerate van 44.2 kHz hebt, en 2048 samples, dan moet je zeker niet verwachten dat je onder de 22Hz nog frequenties kan meten... Volgens mij moet je zelfs zo'n beetje 4x onder de laagste frequentie uitkomen die je wilt meten, anders heb je een nogal kleine betrouwbaarheid...
Omdat dat googlen een beetje tegenvalt: http://www.hsdal.ufl.edu/Projects/FoundDSP/Glossary.html

http://cnx.rice.edu/modules/m10791/latest/

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Nog even ter referentie :

Zoek op google naar papers van :
Masataka Goto
Simon Dixon

Ik heb heel veel gehad aan de verscheidene versies van Masataka Goto's research-papers.
Misschien heb je zelf heel andere ideeen over hoe je het zou moeten aanpakken,
maar het kan in ieder geval als inspiratie dienen.

Verwijderd

Adion schreef op 17 January 2003 @ 13:27:
Als je alles goed gelezen had is dit precies wat MSalters voorstelde :
Een fft op 1024 waardes heeft inderdaad een nauwkeurigheid van samplefrequentie / 1024, dus als je de samplefrequentie verlaagd, verhoogd de nauwkeurigheid.
Zry, overheen gelezen |:( Maar waar het me dus eigenlijk om ging is dat ik zo snel niets lees over iemand die hier een LF laagdoorlaatfilter aanraadt. Wel "in de gedaante van" downsampling, maar je kunt dus (daarnaast) een goed een laagdoorlaatfiltertje nemen uit de lib. Ligt er maar aan wat je toepassing is, of je upberhaupt een FFT nodig hebt, als je een signaal nodig hebt met de beatfrequentie om bijvoorbeeld een drum-computer mee te voeden, of een effectenpedaal (denk ik even in elektronica i.p.v. software) dan is het dus totaal onnodig om dit tijdsignaal van de beat nog op te zetten naar het frequentiebereik. - Het zal zeker wel leerzaam zijn voor de TS om zich dan nog in fourier transformaties te verdiepen, maar misschien helemaal niet nodig...

[ Voor 18% gewijzigd door Verwijderd op 17-01-2003 15:37 ]

Pagina: 1