Advertisement
Guest User

Untitled

a guest
Jan 19th, 2016
282
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     BASS spectrum analyser example
  3.     Copyright (c) 2002-2014 Un4seen Developments Ltd.
  4. */
  5.  
  6. #include <windows.h>
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include <malloc.h>
  10. #include "bass.h"
  11.  
  12. #define SPECWIDTH 368   // display width
  13. #define SPECHEIGHT 127  // height (changing requires palette adjustments too)
  14.  
  15. HWND win=NULL;
  16. DWORD timer=0;
  17.  
  18. DWORD chan;
  19.  
  20. HDC specdc=0;
  21. HBITMAP specbmp=0;
  22. BYTE *specbuf;
  23.  
  24. int specmode=0,specpos=0; // spectrum mode (and marker pos for 3D mode)
  25.  
  26. // display error messages
  27. void Error(const char *es)
  28. {
  29.     char mes[200];
  30.     sprintf(mes,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
  31.     MessageBox(win,mes,0,0);
  32. }
  33.  
  34. // select a file to play, and play it
  35. BOOL PlayFile()
  36. {
  37.     char file[MAX_PATH]="";
  38.     OPENFILENAME ofn={0};
  39.     ofn.lStructSize=sizeof(ofn);
  40.     ofn.hwndOwner=win;
  41.     ofn.nMaxFile=MAX_PATH;
  42.     ofn.lpstrFile=file;
  43.     ofn.Flags=OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_EXPLORER;
  44.     ofn.lpstrTitle="Select a file to play";
  45.     ofn.lpstrFilter="playable files\0*.mo3;*.xm;*.mod;*.s3m;*.it;*.mtm;*.umx;*.mp3;*.mp2;*.mp1;*.ogg;*.wav;*.aif\0All files\0*.*\0\0";
  46.     if (!GetOpenFileName(&ofn)) return FALSE;
  47.  
  48.     if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_SAMPLE_LOOP))
  49.         && !(chan=BASS_MusicLoad(FALSE,file,0,0,BASS_MUSIC_RAMP|BASS_SAMPLE_LOOP,1))) {
  50.         Error("Can't play file");
  51.         return FALSE; // Can't load the file
  52.     }
  53.  
  54.     BASS_ChannelPlay(chan,FALSE);
  55.  
  56.     return TRUE;
  57. }
  58.  
  59. // update the spectrum display - the interesting bit :)
  60. void CALLBACK UpdateSpectrum(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
  61. {
  62.     HDC dc;
  63.     int x,y,y1;
  64.  
  65.     if (specmode==3) { // waveform
  66.         int c;
  67.         float *buf;
  68.         BASS_CHANNELINFO ci;
  69.         memset(specbuf,0,SPECWIDTH*SPECHEIGHT);
  70.         BASS_ChannelGetInfo(chan,&ci); // get number of channels
  71.         buf=alloca(ci.chans*SPECWIDTH*sizeof(float)); // allocate buffer for data
  72.         BASS_ChannelGetData(chan,buf,(ci.chans*SPECWIDTH*sizeof(float))|BASS_DATA_FLOAT); // get the sample data (floating-point to avoid 8 & 16 bit processing)
  73.         for (c=0;c<ci.chans;c++) {
  74.             for (x=0;x<SPECWIDTH;x++) {
  75.                 int v=(1-buf[x*ci.chans+c])*SPECHEIGHT/2; // invert and scale to fit display
  76.                 if (v<0) v=0;
  77.                 else if (v>=SPECHEIGHT) v=SPECHEIGHT-1;
  78.                 if (!x) y=v;
  79.                 do { // draw line from previous sample...
  80.                     if (y<v) y++;
  81.                     else if (y>v) y--;
  82.                     specbuf[y*SPECWIDTH+x]=c&1?127:1; // left=green, right=red (could add more colours to palette for more chans)
  83.                 } while (y!=v);
  84.             }
  85.         }
  86.     }
  87.     else {
  88.         float fft[1024];
  89.         BASS_ChannelGetData(chan,fft,BASS_DATA_FFT2048); // get the FFT data
  90.  
  91.         if (!specmode) { // "normal" FFT
  92.             memset(specbuf,0,SPECWIDTH*SPECHEIGHT);
  93.             for (x=0;x<SPECWIDTH/2;x++) {
  94. #if 1
  95.                 y=sqrt(fft[x+1])*3*SPECHEIGHT-4; // scale it (sqrt to make low values more visible)
  96. #else
  97.                 y=fft[x+1]*10*SPECHEIGHT; // scale it (linearly)
  98. #endif
  99.                 if (y>SPECHEIGHT) y=SPECHEIGHT; // cap it
  100.                 if (x && (y1=(y+y1)/2)) // interpolate from previous to make the display smoother
  101.                     while (--y1>=0) specbuf[y1*SPECWIDTH+x*2-1]=y1+1;
  102.                 y1=y;
  103.                 while (--y>=0) specbuf[y*SPECWIDTH+x*2]=y+1; // draw level
  104.             }
  105.         } else if (specmode==1) { // logarithmic, combine bins
  106.             int b0=0;
  107.             memset(specbuf,0,SPECWIDTH*SPECHEIGHT);
  108. #define BANDS 28
  109.             for (x=0;x<BANDS;x++) {
  110.                 float peak=0;
  111.                 int b1=pow(2,x*10.0/(BANDS-1));
  112.                 if (b1<=b0) b1=b0+1; // make sure it uses at least 1 FFT bin
  113.                 if (b1>1023) b1=1023;
  114.                 for (;b0<b1;b0++)
  115.                     if (peak<fft[1+b0]) peak=fft[1+b0];
  116.                 y=sqrt(peak)*3*SPECHEIGHT-4; // scale it (sqrt to make low values more visible)
  117.                 if (y>SPECHEIGHT) y=SPECHEIGHT; // cap it
  118.                 while (--y>=0)
  119.                     memset(specbuf+y*SPECWIDTH+x*(SPECWIDTH/BANDS),y+1,SPECWIDTH/BANDS-2); // draw bar
  120.             }
  121.         } else { // "3D"
  122.             for (x=0;x<SPECHEIGHT;x++) {
  123.                 y=sqrt(fft[x+1])*3*127; // scale it (sqrt to make low values more visible)
  124.                 if (y>127) y=127; // cap it
  125.                 specbuf[x*SPECWIDTH+specpos]=128+y; // plot it
  126.             }
  127.             // move marker onto next position
  128.             specpos=(specpos+1)%SPECWIDTH;
  129.             for (x=0;x<SPECHEIGHT;x++) specbuf[x*SPECWIDTH+specpos]=255;
  130.         }
  131.     }
  132.  
  133.     // update the display
  134.     dc=GetDC(win);
  135.     BitBlt(dc,0,0,SPECWIDTH,SPECHEIGHT,specdc,0,0,SRCCOPY);
  136.     ReleaseDC(win,dc);
  137. }
  138.  
  139. // window procedure
  140. LRESULT CALLBACK SpectrumWindowProc(HWND h, UINT m, WPARAM w, LPARAM l)
  141. {
  142.     switch (m) {
  143.         case WM_PAINT:
  144.             if (GetUpdateRect(h,0,0)) {
  145.                 PAINTSTRUCT p;
  146.                 HDC dc;
  147.                 if (!(dc=BeginPaint(h,&p))) return 0;
  148.                 BitBlt(dc,0,0,SPECWIDTH,SPECHEIGHT,specdc,0,0,SRCCOPY);
  149.                 EndPaint(h,&p);
  150.             }
  151.             return 0;
  152.  
  153.         case WM_LBUTTONUP:
  154.             specmode=(specmode+1)%4; // change spectrum mode
  155.             memset(specbuf,0,SPECWIDTH*SPECHEIGHT); // clear display
  156.             return 0;
  157.  
  158.         case WM_CREATE:
  159.             win=h;
  160.             // initialize BASS
  161.             if (!BASS_Init(-1,44100,0,win,NULL)) {
  162.                 Error("Can't initialize device");
  163.                 return -1;
  164.             }
  165.             if (!PlayFile()) { // start a file playing
  166.                 BASS_Free();
  167.                 return -1;
  168.             }
  169.             { // create bitmap to draw spectrum in (8 bit for easy updating)
  170.                 BYTE data[2000]={0};
  171.                 BITMAPINFOHEADER *bh=(BITMAPINFOHEADER*)data;
  172.                 RGBQUAD *pal=(RGBQUAD*)(data+sizeof(*bh));
  173.                 int a;
  174.                 bh->biSize=sizeof(*bh);
  175.                 bh->biWidth=SPECWIDTH;
  176.                 bh->biHeight=SPECHEIGHT; // upside down (line 0=bottom)
  177.                 bh->biPlanes=1;
  178.                 bh->biBitCount=8;
  179.                 bh->biClrUsed=bh->biClrImportant=256;
  180.                 // setup palette
  181.                 for (a=1;a<128;a++) {
  182.                     pal[a].rgbGreen=256-2*a;
  183.                     pal[a].rgbRed=2*a;
  184.                 }
  185.                 for (a=0;a<32;a++) {
  186.                     pal[128+a].rgbBlue=8*a;
  187.                     pal[128+32+a].rgbBlue=255;
  188.                     pal[128+32+a].rgbRed=8*a;
  189.                     pal[128+64+a].rgbRed=255;
  190.                     pal[128+64+a].rgbBlue=8*(31-a);
  191.                     pal[128+64+a].rgbGreen=8*a;
  192.                     pal[128+96+a].rgbRed=255;
  193.                     pal[128+96+a].rgbGreen=255;
  194.                     pal[128+96+a].rgbBlue=8*a;
  195.                 }
  196.                 // create the bitmap
  197.                 specbmp=CreateDIBSection(0,(BITMAPINFO*)bh,DIB_RGB_COLORS,(void**)&specbuf,NULL,0);
  198.                 specdc=CreateCompatibleDC(0);
  199.                 SelectObject(specdc,specbmp);
  200.             }
  201.             // start update timer (40hz)
  202.             timer=timeSetEvent(25,25,(LPTIMECALLBACK)&UpdateSpectrum,0,TIME_PERIODIC);
  203.             break;
  204.  
  205.         case WM_DESTROY:
  206.             if (timer) timeKillEvent(timer);
  207.             BASS_Free();
  208.             if (specdc) DeleteDC(specdc);
  209.             if (specbmp) DeleteObject(specbmp);
  210.             PostQuitMessage(0);
  211.             break;
  212.     }
  213.     return DefWindowProc(h, m, w, l);
  214. }
  215.  
  216. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
  217. {
  218.     WNDCLASS wc={0};
  219.     MSG msg;
  220.  
  221.     // check the correct BASS was loaded
  222.     if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
  223.         MessageBox(0,"An incorrect version of BASS.DLL was loaded",0,MB_ICONERROR);
  224.         return 0;
  225.     }
  226.  
  227.     // register window class and create the window
  228.     wc.lpfnWndProc = SpectrumWindowProc;
  229.     wc.hInstance = hInstance;
  230.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  231.     wc.lpszClassName = "BASS-Spectrum";
  232.     if (!RegisterClass(&wc) || !CreateWindow("BASS-Spectrum",
  233.             "BASS spectrum example (click to switch mode)",
  234.             WS_POPUPWINDOW|WS_CAPTION|WS_VISIBLE, 200, 200,
  235.             SPECWIDTH+2*GetSystemMetrics(SM_CXDLGFRAME),
  236.             SPECHEIGHT+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYDLGFRAME),
  237.             NULL, NULL, hInstance, NULL)) {
  238.         Error("Can't create window");
  239.         return 0;
  240.     }
  241.     ShowWindow(win, SW_SHOWNORMAL);
  242.  
  243.     while (GetMessage(&msg,NULL,0,0)>0) {
  244.         TranslateMessage(&msg);
  245.         DispatchMessage(&msg);
  246.     }
  247.  
  248.     return 0;
  249. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement