123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711 |
- #include <windows.h>
- #include <commctrl.h>
- #include <math.h>
- #include <stdio.h>
- #include "draw.h"
- #include "wnd.h"
- #include "r_defs.h"
- #include "render.h"
- #include "vis.h"
- #include "cfgwnd.h"
- #include "resource.h"
- #include "bpm.h"
- #include "../Agave/Language/api_language.h"
- int refineBeat(int isBeat);
- BOOL TCHistStep(BeatType *t, DWORD _Avg, int *_halfDiscriminated, int *_hdPos, DWORD *_lastTC, DWORD TC, int Type);
- void InsertHistStep(BeatType *t, DWORD TC, int Type, int i);
- void CalcBPM(void);
- BOOL ReadyToLearn(void);
- BOOL ReadyToGuess(void);
- void doubleBeat(void);
- void halfBeat(void);
- void ResetAdapt(void);
- void SliderStep(int Ctl, int *slide);
- void initBpm(void);
- extern int g_fakeinit;
- int cfg_smartbeat=0;
- int cfg_smartbeatsticky=1;
- int cfg_smartbeatresetnewsong=1;
- int cfg_smartbeatonlysticky=0;
- int sticked=0;
- int arbVal, skipVal;
- int Bpm, Confidence, Confidence1, Confidence2;
- DWORD lastTC;
- DWORD lastTC2;
- BeatType TCHist[8];
- BeatType TCHist2[8];
- int Smoother[8];
- int halfDiscriminated[8];
- int halfDiscriminated2[8];
- int hdPos;
- int hdPos2;
- int smPtr, smSize;
- int TCHistPtr;
- int TCHistSize;
- int offIMax;
- int lastBPM;
- int insertionCount;
- DWORD predictionLastTC;
- DWORD Avg;
- DWORD Avg2;
- int skipCount;
- int inInc, outInc;
- int inSlide, outSlide;
- int oldInSlide, oldOutSlide;
- int oldsticked;
- char txt[256];
- int halfCount, doubleCount;
- int TCUsed;
- int predictionBpm;
- int oldDisplayBpm, oldDisplayConfidence;
- int bestConfidence;
- char lastSongName[256];
- HWND winampWnd;
- int forceNewBeat;
- int betterConfidenceCount;
- int topConfidenceCount;
- int stickyConfidenceCount;
- BOOL doResyncBpm=FALSE;
- BOOL CALLBACK DlgProc_Bpm(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
- {
- switch (uMsg)
- {
- case WM_INITDIALOG:
- inInc = 1;
- outInc = 1;
- inSlide = 0;
- outSlide = 0;
- oldDisplayBpm=-1;
- oldDisplayConfidence=-1;
- oldInSlide=-1;
- oldOutSlide=-1;
- if (cfg_smartbeat) CheckDlgButton(hwndDlg,IDC_BPMADV,BST_CHECKED); else CheckDlgButton(hwndDlg,IDC_BPMSTD,BST_CHECKED);
- if (cfg_smartbeatsticky) CheckDlgButton(hwndDlg,IDC_STICKY,BST_CHECKED);
- if (cfg_smartbeatresetnewsong) CheckDlgButton(hwndDlg,IDC_NEWRESET,BST_CHECKED); else CheckDlgButton(hwndDlg,IDC_NEWADAPT,BST_CHECKED);
- if (cfg_smartbeatonlysticky) CheckDlgButton(hwndDlg,IDC_ONLYSTICKY,BST_CHECKED);
- SendDlgItemMessage(hwndDlg, IDC_IN, TBM_SETTICFREQ, 1, 0);
- SendDlgItemMessage(hwndDlg, IDC_IN, TBM_SETRANGE, TRUE, MAKELONG(0, 8));
- SendDlgItemMessage(hwndDlg, IDC_OUT, TBM_SETTICFREQ, 1, 0);
- SendDlgItemMessage(hwndDlg, IDC_OUT, TBM_SETRANGE, TRUE, MAKELONG(0, 8));
- if (predictionBpm)
- {
- ShowWindow(GetDlgItem(hwndDlg, IDC_STICK), sticked ? SW_HIDE : SW_NORMAL);
- ShowWindow(GetDlgItem(hwndDlg, IDC_UNSTICK), sticked ? SW_NORMAL : SW_HIDE);
- }
- else
- {
- ShowWindow(GetDlgItem(hwndDlg, IDC_STICK), SW_HIDE);
- ShowWindow(GetDlgItem(hwndDlg, IDC_UNSTICK), SW_HIDE);
- }
- SetTimer(hwndDlg, 0, 50, NULL);
- return 1;
- case WM_TIMER:
- {
- if (oldInSlide != inSlide) {
- SendDlgItemMessage(hwndDlg, IDC_IN, TBM_SETPOS, TRUE, inSlide); oldInSlide=inSlide; }
- if (oldOutSlide != outSlide) {
- SendDlgItemMessage(hwndDlg, IDC_OUT, TBM_SETPOS, TRUE, outSlide); oldOutSlide=outSlide; }
- if (oldDisplayBpm != predictionBpm || oldsticked != sticked) {
- char lBuf[16];
- wsprintf(txt, predictionBpm ? "%d%s" : WASABI_API_LNGSTRING_BUF(IDS_LEARNING,lBuf,16), predictionBpm, cfg_smartbeatsticky && sticked ? WASABI_API_LNGSTRING(IDS_GOT_IT) : "");
- SetDlgItemText(hwndDlg, IDC_BPM, txt);
- oldDisplayBpm=predictionBpm;
- oldsticked=sticked;
- if (predictionBpm)
- {
- ShowWindow(GetDlgItem(hwndDlg, IDC_STICK), sticked ? SW_HIDE : SW_NORMAL);
- ShowWindow(GetDlgItem(hwndDlg, IDC_UNSTICK), sticked ? SW_NORMAL : SW_HIDE);
- }
- else
- {
- ShowWindow(GetDlgItem(hwndDlg, IDC_STICK), SW_HIDE);
- ShowWindow(GetDlgItem(hwndDlg, IDC_UNSTICK), SW_HIDE);
- }
- }
- if (oldDisplayConfidence != Confidence) {
- wsprintf(txt, "%d%%", Confidence);
- SetDlgItemText(hwndDlg, IDC_CONFIDENCE, txt);
- oldDisplayConfidence=Confidence;
- }
- }
- return 0;
- case WM_COMMAND:
- if ((LOWORD(wParam) == IDC_BPMSTD) ||
- (LOWORD(wParam) == IDC_BPMADV) ||
- (LOWORD(wParam) == IDC_NEWRESET) ||
- (LOWORD(wParam) == IDC_NEWADAPT) ||
- (LOWORD(wParam) == IDC_ONLYSTICKY) ||
- (LOWORD(wParam) == IDC_STICKY))
- {
- cfg_smartbeat=IsDlgButtonChecked(hwndDlg,IDC_BPMADV)?1:0;
- cfg_smartbeatsticky=IsDlgButtonChecked(hwndDlg,IDC_STICKY)?1:0;
- cfg_smartbeatresetnewsong=IsDlgButtonChecked(hwndDlg,IDC_NEWRESET)?1:0;
- cfg_smartbeatonlysticky=IsDlgButtonChecked(hwndDlg,IDC_ONLYSTICKY)?1:0;
- oldsticked=-1;
- }
- if (LOWORD(wParam) == IDC_2X)
- doubleBeat();
- if (LOWORD(wParam) == IDC_DIV2)
- halfBeat();
- if (LOWORD(wParam) == IDC_RESET)
- ResetAdapt();
- if (LOWORD(wParam) == IDC_STICK)
- {
- sticked=1;
- stickyConfidenceCount=0;
- }
- if (LOWORD(wParam) == IDC_UNSTICK)
- {
- sticked=0;
- stickyConfidenceCount=0;
- }
- return 0;
- case WM_DESTROY:
- KillTimer(hwndDlg, 0);
- return 0;
- }
- return 0;
- }
- void initBpm(void)
- {
- if (g_fakeinit) return;
- TCUsed=0;
- *txt=0;
- betterConfidenceCount=0;
- topConfidenceCount=0;
- forceNewBeat=0;
- hdPos=0;
- hdPos2=0;
- inSlide=0;
- outSlide=0;
- oldDisplayBpm=-1;
- oldDisplayConfidence=-1;
- oldInSlide=0;
- oldOutSlide=0;
- Bpm = 0;
- Avg = 0;
- Avg2 = 0;
- smPtr = 0;
- smSize = 8;
- offIMax = 8;
- insertionCount = 0;
- predictionLastTC = 0;
- Confidence = 0;
- Confidence1 = 0;
- Confidence2 = 0;
- halfCount=0;
- doubleCount=0;
- TCHistSize = 8;
- predictionBpm=0;
- lastTC=GetTickCount();
- stickyConfidenceCount=0;
- memset(TCHist, 0, TCHistSize*sizeof(BeatType));
- memset(Smoother, 0, smSize*sizeof(int));
- memset(halfDiscriminated, 0, TCHistSize*sizeof(int));
- memset(halfDiscriminated2, 0, TCHistSize*sizeof(int));
- winampWnd = FindWindow("Winamp v1.x", NULL);
- *lastSongName=0;
- sticked=0;
- oldsticked=-1;
- }
- BOOL songChanged(DWORD TCNow)
- {
- static DWORD lastCheck=0;
- if (TCNow > lastCheck+1000)
- {
- char songName[256];
- lastCheck=TCNow;
- GetWindowText(winampWnd, songName, 255);
- if (strcmp(songName, lastSongName))
- {
- strcpy(lastSongName, songName);
- return TRUE;
- }
- }
- return FALSE;
- }
- void ResetAdapt(void)
- {
- *txt=0;
- TCUsed=0;
- hdPos=0;
- Avg = 0;
- Confidence=0;
- Confidence1=0;
- Confidence2=0;
- betterConfidenceCount=0;
- topConfidenceCount=0;
- Bpm = 0;
- smPtr = 0;
- smSize = 8;
- offIMax = 8;
- insertionCount = 0;
- predictionLastTC = 0;
- halfCount=0;
- doubleCount=0;
- TCHistSize = 8;
- predictionBpm=0;
- bestConfidence=0;
- lastTC=GetTickCount();
- sticked=0;
- oldsticked=-1;
- stickyConfidenceCount=0;
- memset(TCHist, 0, TCHistSize*sizeof(BeatType));
- memset(TCHist2, 0, TCHistSize*sizeof(BeatType));
- memset(Smoother, 0, smSize*sizeof(int));
- memset(halfDiscriminated, 0, TCHistSize*sizeof(int));
- }
- void InsertHistStep(BeatType *t, DWORD TC, int Type, int i)
- {
- if (i >= TCHistSize) return;
- if (t == TCHist && insertionCount < TCHistSize*2) insertionCount++;
- memmove(t+i+1, t+i, sizeof(BeatType)*(TCHistSize-(i+1)));
- t[0].TC = TC;
- t[0].Type = Type;
- }
- void doubleBeat(void)
- {
- int i;
- int iv[8];
- if (sticked && Bpm > MIN_BPM) return;
- for (i=0;i<TCHistSize-1;i++)
- iv[i] = TCHist[i].TC - TCHist[i+1].TC;
- for (i=1;i<TCHistSize;i++)
- TCHist[i].TC = TCHist[i-1].TC-iv[i-1]/2;
- Avg /= 2;
- Bpm *= 2;
- doubleCount=0;
- memset(Smoother, 0, smSize*sizeof(int));
- memset(halfDiscriminated, 0, TCHistSize*sizeof(int));
- }
- void halfBeat(void)
- {
- int i;
- int iv[8];
- if (sticked && Bpm < MIN_BPM) return;
- for (i=0;i<TCHistSize-1;i++)
- iv[i] = TCHist[i].TC - TCHist[i+1].TC;
- for (i=1;i<TCHistSize;i++)
- TCHist[i].TC = TCHist[i-1].TC-iv[i-1]*2;
- Avg *= 2;
- Bpm /= 2;
- halfCount=0;
- memset(Smoother, 0, smSize*sizeof(int));
- memset(halfDiscriminated, 0, TCHistSize*sizeof(int));
- }
- BOOL TCHistStep(BeatType *t, DWORD _Avg, int *_halfDiscriminated, int *_hdPos, DWORD *_lastTC, DWORD TC, int Type)
- {
- int i=0;
- int offI;
- DWORD thisLen;
- BOOL learning = ReadyToLearn();
- thisLen = TC-lastTC;
- if (thisLen < Avg/2 - Avg*0.2)
- {
- if (learning)
- {
- if (labs(Avg - (TC - t[1].TC)) < labs(Avg - (t[0].TC - t[1].TC)))
- {
- t[0].TC = TC;
- t[0].Type = Type;
- return TRUE;
- }
- }
- return FALSE;
- }
- if (learning)
- for (offI=2;offI<offIMax;offI++)
- if ((float)labs((Avg/offI)-thisLen) < (float)(Avg/offI)*0.2)
- {
- _halfDiscriminated[(*_hdPos)++]=1;
- (*_hdPos)%=8;
- return FALSE;
- }
- _halfDiscriminated[hdPos++]=0;
- (*_hdPos)%=8;
- *_lastTC = TC;
- InsertHistStep(t, TC, Type, 0);
- return TRUE;
- }
- BOOL ReadyToLearn(void)
- {
- int i;
- for (i=0;i<TCHistSize;i++)
- if (TCHist[i].TC==0) return FALSE;
- return TRUE;
- }
- BOOL ReadyToGuess(void)
- {
- return insertionCount == TCHistSize*2;
- }
- void newBpm(int thisBpm)
- {
- Smoother[smPtr++] = thisBpm;
- smPtr %= smSize;
- }
- int GetBpm(void)
- {
- int i;
- int smN=0;
- int smSum=0;
- for (i=0;i<smSize;i++)
- if (Smoother[i] > 0) {
- smSum += Smoother[i];
- smN++;
- }
- if (smN) return smSum / smN;
- return 0;
- }
- void CalcBPM(void)
- {
- int i;
- int hdCount=0;
- int r=0;
- int totalTC=0, totalN=0;
- float rC, etC;
- int v;
- double sc=0;
- int mx=0;
- float et;
- int smSum=0, smN=0;
- if (!ReadyToLearn())
- return;
- for (i=0;i<TCHistSize-1;i++)
- totalTC += TCHist[i].TC - TCHist[i+1].TC;
- Avg = totalTC/(TCHistSize-1);
- for (i=0;i<TCHistSize;i++)
- if (TCHist[i].Type == BEAT_REAL)
- r++;
- rC = (float)min((float)((float)r / (float)TCHistSize) * 2, 1);
- for (i=0;i<TCHistSize-1;i++)
- {
- v = TCHist[i].TC - TCHist[i+1].TC;
- mx = max(mx, v);
- sc += v*v;
- }
- et = (float)sqrt(sc / (TCHistSize-1) - Avg*Avg);
- etC = 1 - ((float)et / (float)mx);
- Confidence = max(0, (int)(((rC * etC) * 100.0) - 50) * 2);
- Confidence1 = (int)(rC * 100);
- Confidence2 = (int)(etC * 100);
- totalTC=0;
- for (i=0;i<TCHistSize-1;i++)
- {
- v += TCHist[i].TC - TCHist[i+1].TC;
- if (labs(Avg-v) < et)
- {
- totalTC += v;
- totalN++;
- v = 0;
- }
- else
- if ((float)v > Avg)
- v = 0;
- }
- TCUsed = totalN;
- if (totalN)
- Avg = totalTC/totalN;
- if (ReadyToGuess())
- {
- if (Avg)
- Bpm = 60000 / Avg;
- if (Bpm != lastBPM)
- {
- newBpm(Bpm);
- lastBPM = Bpm;
- if (cfg_smartbeatsticky && predictionBpm && Confidence >= ((predictionBpm < 90) ? STICKY_THRESHOLD_LOW : STICKY_THRESHOLD))
- {
- stickyConfidenceCount++;
- if (stickyConfidenceCount >= MIN_STICKY)
- sticked=1;
- }
- else
- stickyConfidenceCount=0;
- }
- Bpm = GetBpm();
-
- for (i=0;i<TCHistSize;i++)
- if (halfDiscriminated[i]) hdCount++;
- if (hdCount >= TCHistSize/2)
- {
- if (Bpm * 2 < MAX_BPM)
- {
- doubleBeat();
- memset(halfDiscriminated, 0, TCHistSize*sizeof(int));
- }
- }
- if (Bpm > 500 || Bpm < 0)
- {
- ResetAdapt();
- }
- if (Bpm < MIN_BPM)
- {
- if (++doubleCount > 4)
- doubleBeat();
- }
- else
- doubleCount=0;
- if (Bpm > MAX_BPM)
- {
- if (++halfCount > 4)
- halfBeat();
- }
- else
- halfCount=0;
- }
- }
- void SliderStep(int Ctl, int *slide)
- {
- *slide += Ctl == IDC_IN ? inInc : outInc;
- if (!*slide || *slide == 8) (Ctl == IDC_IN ? inInc : outInc) *= -1;
- }
- int refineBeat(int isBeat)
- {
- BOOL accepted=FALSE;
- BOOL predicted=FALSE;
- BOOL resyncin=FALSE;
- BOOL resyncout=FALSE;
- if (isBeat)
- SliderStep(IDC_IN, &inSlide);
- DWORD TCNow = GetTickCount();
- if (songChanged(TCNow))
- {
- bestConfidence=(int)((float)bestConfidence*0.5);
- sticked=0;
- stickyConfidenceCount=0;
- if (cfg_smartbeatresetnewsong)
- ResetAdapt();
- }
-
- if (Bpm && TCNow > predictionLastTC + (60000 / Bpm))
- predicted = TRUE;
- if (isBeat)
- accepted = TCHistStep(TCHist, Avg, halfDiscriminated, &hdPos, &lastTC, TCNow, BEAT_REAL);
-
- CalcBPM();
-
-
-
-
-
-
- if ((accepted || predicted) && !sticked && (!predictionBpm || predictionBpm > MAX_BPM || predictionBpm < MIN_BPM))
- {
- if (Confidence >= bestConfidence)
- {
- forceNewBeat=1;
- }
- if (Confidence >= 50)
- {
- topConfidenceCount++;
- if (topConfidenceCount == TOP_CONF_ADOPT)
- {
- forceNewBeat=1;
- topConfidenceCount=0;
- }
- }
- if (forceNewBeat)
- {
- forceNewBeat=0;
- bestConfidence = Confidence;
- predictionBpm=Bpm;
- }
- }
- if (!sticked) predictionBpm = Bpm;
- Bpm=predictionBpm;
- if (predictionBpm && accepted && !predicted)
- {
- int b=0;
- if (TCNow > predictionLastTC + (60000 / predictionBpm)*0.7)
- {
- resyncin = TRUE;
- b = (int)((float)predictionBpm * 1.01);
- }
- if (TCNow < predictionLastTC + (60000 / predictionBpm)*0.3)
- {
- resyncout = TRUE;
- b = (int)((float)predictionBpm * 0.98);
- }
- if (!sticked && doResyncBpm && (resyncin || resyncout))
- {
- newBpm(b);
- predictionBpm = GetBpm();
- }
- }
- if (resyncin)
- {
- predictionLastTC = TCNow;
- SliderStep(IDC_OUT, &outSlide);
- doResyncBpm=TRUE;
- return ((cfg_smartbeat && !cfg_smartbeatonlysticky) || (cfg_smartbeat && cfg_smartbeatonlysticky && sticked)) ? 1 : isBeat;
- }
- if (predicted)
- {
- predictionLastTC = TCNow;
- if (Confidence > 25) TCHistStep(TCHist, Avg, halfDiscriminated, &hdPos, &lastTC, TCNow, BEAT_GUESSED);
- SliderStep(IDC_OUT, &outSlide);
- doResyncBpm=FALSE;
- return ((cfg_smartbeat && !cfg_smartbeatonlysticky) || (cfg_smartbeat && cfg_smartbeatonlysticky && sticked)) ? 1 : isBeat;
- }
- if (resyncout)
- {
- predictionLastTC = TCNow;
- doResyncBpm=TRUE;
- return ((cfg_smartbeat && !cfg_smartbeatonlysticky) || (cfg_smartbeat && cfg_smartbeatonlysticky && sticked)) ? 0 : isBeat;
- }
- return ((cfg_smartbeat && !cfg_smartbeatonlysticky) || (cfg_smartbeat && cfg_smartbeatonlysticky && sticked)) ? (predictionBpm ? 0 : isBeat) : isBeat;
- }
|