home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 November / CDVD1105.ISO / Software / Freeware / programare / bass / c / 3dtest / 3dtest.c next >
Encoding:
C/C++ Source or Header  |  2005-09-14  |  11.3 KB  |  395 lines

  1. // BASS 3D Test, copyright (c) 1999-2005 Ian Luck.
  2.  
  3. #include <windows.h>
  4. #include <commctrl.h>
  5. #include <math.h>
  6. #include "bass.h"
  7. #include "3dtest.h"
  8.  
  9. HWND win=NULL;
  10.  
  11. /* channel (sample/music) info structure */
  12. typedef struct {
  13.     DWORD channel;            // the channel
  14.     BASS_3DVECTOR pos,vel;    // position,velocity
  15.     int dir;                // direction of the channel
  16. } Channel;
  17.  
  18. Channel *chans=NULL;        // the channels
  19. int chanc=0,chan=-1;        // number of channels, current channel
  20. HBRUSH brush1,brush2;    // brushes
  21.  
  22. #define TIMERPERIOD    50        // timer period (ms)
  23. #define MAXDIST        50        // maximum distance of the channels (m)
  24. #define SPEED        12        // speed of the channels' movement (m/s)
  25.  
  26. /* Display error dialogs */
  27. void Error(char *es)
  28. {
  29.     char mes[200];
  30.     sprintf(mes,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
  31.     MessageBox(win,mes,"Error",0);
  32. }
  33.  
  34. /* Messaging macros */
  35. #define ITEM(id) GetDlgItem(win,id)
  36. #define MESS(id,m,w,l) SendDlgItemMessage(win,id,m,(WPARAM)w,(LPARAM)l)
  37. #define LM(m,w,l) MESS(ID_LIST,m,w,l)
  38. #define EM(m,w,l) MESS(ID_EAX,m,w,l)
  39.  
  40. void CALLBACK Update(HWND win, UINT m, UINT i, DWORD t)
  41. {
  42.     HDC dc;
  43.     RECT r;
  44.     int c,x,y,cx,cy;
  45.     int save;
  46.     HPEN pen;
  47.  
  48.     win=ITEM(ID_DISPLAY);
  49.     dc=GetDC(win);
  50.     save=SaveDC(dc);
  51.     GetClientRect(win,&r);
  52.     cx=r.right/2;
  53.     cy=r.bottom/2;
  54.  
  55.     /* Draw center circle */
  56.     SelectObject(dc,GetStockObject(GRAY_BRUSH));
  57.     Ellipse(dc,cx-4,cy-4,cx+4,cy+4);
  58.  
  59.     pen=CreatePen(PS_SOLID,2,GetSysColor(COLOR_BTNFACE));
  60.     SelectObject(dc,pen);
  61.  
  62.     for (c=0;c<chanc;c++) {
  63.         /* If the channel's playing then update it's position */
  64.         if (BASS_ChannelIsActive(chans[c].channel)==BASS_ACTIVE_PLAYING) {
  65.             /* Check if channel has reached the max distance */
  66.             if (chans[c].pos.z>=MAXDIST || chans[c].pos.z<=-MAXDIST)
  67.                 chans[c].vel.z=-chans[c].vel.z;
  68.             if (chans[c].pos.x>=MAXDIST || chans[c].pos.x<=-MAXDIST)
  69.                 chans[c].vel.x=-chans[c].vel.x;
  70.             /* Update channel position */
  71.             chans[c].pos.z+=chans[c].vel.z*TIMERPERIOD/1000;
  72.             chans[c].pos.x+=chans[c].vel.x*TIMERPERIOD/1000;
  73.             BASS_ChannelSet3DPosition(chans[c].channel,&chans[c].pos,NULL,&chans[c].vel);
  74.         }
  75.         /* Draw the channel position indicator */
  76.         x=cx+(int)((cx-7)*chans[c].pos.x/MAXDIST);
  77.         y=cy-(int)((cy-7)*chans[c].pos.z/MAXDIST);
  78.         if (chan==c)
  79.             SelectObject(dc,brush1);
  80.         else
  81.             SelectObject(dc,brush2);
  82.         Ellipse(dc,x-6,y-6,x+6,y+6);
  83.     }
  84.     /* Apply the 3D changes */
  85.     BASS_Apply3D();
  86.  
  87.     RestoreDC(dc,save);
  88.     DeleteObject(pen);
  89.     ReleaseDC(win,dc);
  90. }
  91.  
  92. /* Update the button states */
  93. void UpdateButtons()
  94. {
  95.     int a;
  96.     EnableWindow(ITEM(ID_REMOVE),chan==-1?FALSE:TRUE);
  97.     EnableWindow(ITEM(ID_PLAY),chan==-1?FALSE:TRUE);
  98.     EnableWindow(ITEM(ID_STOP),chan==-1?FALSE:TRUE);
  99.     for (a=0;a<5;a++)
  100.         EnableWindow(ITEM(ID_LEFT+a),chan==-1?FALSE:TRUE);
  101.     if (chan!=-1) {
  102.         MESS(ID_LEFT,BM_SETCHECK,chans[chan].dir==ID_LEFT?BST_CHECKED:BST_UNCHECKED,0);
  103.         MESS(ID_RIGHT,BM_SETCHECK,chans[chan].dir==ID_RIGHT?BST_CHECKED:BST_UNCHECKED,0);
  104.         MESS(ID_FRONT,BM_SETCHECK,chans[chan].dir==ID_FRONT?BST_CHECKED:BST_UNCHECKED,0);
  105.         MESS(ID_BEHIND,BM_SETCHECK,chans[chan].dir==ID_BEHIND?BST_CHECKED:BST_UNCHECKED,0);
  106.         MESS(ID_NONE,BM_SETCHECK,!chans[chan].dir?BST_CHECKED:BST_UNCHECKED,0);
  107.     }
  108. }
  109.  
  110. BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
  111. {
  112.     static OPENFILENAME ofn;
  113.     static char path[MAX_PATH];
  114.  
  115.     switch (m) {
  116.         case WM_COMMAND:
  117.             switch (LOWORD(w)) {
  118.                 case ID_EAX:
  119.                     /* Change the EAX environment */
  120.                     if (HIWORD(w)==CBN_SELCHANGE) {
  121.                         int s=EM(CB_GETCURSEL,0,0);
  122.                         if (!s)
  123.                             BASS_SetEAXParameters(-1,0,-1,-1); // off (volume=0)
  124.                         else
  125.                             BASS_SetEAXParameters(s-1,-1,-1,-1);
  126.                     }
  127.                     break;
  128.                 case ID_LIST:
  129.                     /* Change the selected channel */
  130.                     if (HIWORD(w)!=LBN_SELCHANGE) break;
  131.                     chan=LM(LB_GETCURSEL,0,0);
  132.                     if (chan==LB_ERR) chan=-1;
  133.                     UpdateButtons();
  134.                     break;
  135.                 case ID_LEFT:
  136.                     chans[chan].dir=ID_LEFT;
  137.                     /* Make the channel move past the left of you */
  138.                     /* Set speed in m/s */
  139.                     chans[chan].vel.z=SPEED;
  140.                     chans[chan].vel.x=0;
  141.                     /* Set positon to the left */
  142.                     chans[chan].pos.x=-6;
  143.                     /* Reset display */
  144.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  145.                     break;
  146.                 case ID_RIGHT:
  147.                     chans[chan].dir=ID_RIGHT;
  148.                     /* Make the channel move past the right of you */
  149.                     chans[chan].vel.z=SPEED;
  150.                     chans[chan].vel.x=0;
  151.                     /* Set positon to the right */
  152.                     chans[chan].pos.x=6;
  153.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  154.                     break;
  155.                 case ID_FRONT:
  156.                     chans[chan].dir=ID_FRONT;
  157.                     /* Make the channel move past the front of you */
  158.                     chans[chan].vel.x=SPEED;
  159.                     chans[chan].vel.z=0;
  160.                     /* Set positon to in front */
  161.                     chans[chan].pos.z=6;
  162.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  163.                     break;
  164.                 case ID_BEHIND:
  165.                     chans[chan].dir=ID_BEHIND;
  166.                     /* Make the channel move past the back of you */
  167.                     chans[chan].vel.x=SPEED;
  168.                     chans[chan].vel.z=0;
  169.                     /* Set positon to behind */
  170.                     chans[chan].pos.z=-6;
  171.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  172.                     break;
  173.                 case ID_NONE:
  174.                     chans[chan].dir=0;
  175.                     /* Make the channel stop moving */
  176.                     chans[chan].vel.x=chans[chan].vel.z=0;
  177.                     break;
  178.                 case ID_ADD:
  179.                     {
  180.                         char file[MAX_PATH]="";
  181.                         DWORD newchan;
  182.                         ofn.lpstrFile=file;
  183.                         if (GetOpenFileName(&ofn)) {
  184.                             memcpy(path,file,ofn.nFileOffset);
  185.                             path[ofn.nFileOffset-1]=0;
  186.                             /* Load a music or sample from "file" */
  187.                             if ((newchan=BASS_MusicLoad(FALSE,file,0,0,BASS_MUSIC_RAMP|BASS_MUSIC_LOOP|BASS_MUSIC_3D,0))
  188.                                 || (newchan=BASS_SampleLoad(FALSE,file,0,0,1,BASS_SAMPLE_LOOP|BASS_SAMPLE_3D|BASS_SAMPLE_MONO))) {
  189.                                 Channel *c;
  190.                                 chanc++;
  191.                                 chans=(Channel*)realloc((void*)chans,chanc*sizeof(Channel));
  192.                                 c=chans+chanc-1;
  193.                                 memset(c,0,sizeof(Channel));
  194.                                 c->channel=newchan;
  195.                                 BASS_SampleGetChannel(newchan,FALSE); // initialize sample channel
  196.                                 LM(LB_ADDSTRING,0,file);
  197.                             } else
  198.                                 Error("Can't load file (note samples must be mono)");
  199.                         }
  200.                     }
  201.                     break;
  202.                 case ID_REMOVE:
  203.                     {
  204.                         Channel *c=chans+chan;
  205.                         BASS_SampleFree(c->channel);
  206.                         BASS_MusicFree(c->channel);
  207.                         memcpy(c,c+1,(chanc-chan-1)*sizeof(Channel));
  208.                         chanc--;
  209.                         LM(LB_DELETESTRING,chan,0);
  210.                         chan=-1;
  211.                         UpdateButtons();
  212.                         InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  213.                     }
  214.                     break;
  215.                 case ID_PLAY:
  216.                     BASS_ChannelPlay(chans[chan].channel,FALSE);
  217.                     break;
  218.                 case ID_STOP:
  219.                     BASS_ChannelPause(chans[chan].channel);
  220.                     break;
  221.                 case IDCANCEL:
  222.                     DestroyWindow(h);
  223.                     break;
  224.             }
  225.             break;
  226.  
  227.         case WM_HSCROLL:
  228.             if (l) {
  229.                 int pos=SendMessage((HWND)l,TBM_GETPOS,0,0);
  230.                 switch (GetDlgCtrlID((HWND)l)) {
  231.                     case ID_ROLLOFF: // change the rolloff factor
  232.                         BASS_Set3DFactors(-1,pow(2,(pos-10)/5.0),-1);
  233.                         break;
  234.                     case ID_DOPPLER: // change the doppler factor
  235.                         BASS_Set3DFactors(-1,-1,pow(2,(pos-10)/5.0));
  236.                         break;
  237.                 }
  238.             }
  239.             break;
  240.  
  241.         case WM_INITDIALOG:
  242.             win=h;
  243.             brush1=CreateSolidBrush(0xff);
  244.             brush2=CreateSolidBrush(0);
  245.  
  246.             EM(CB_ADDSTRING,0,"Off");
  247.             EM(CB_ADDSTRING,0,"Generic");
  248.             EM(CB_ADDSTRING,0,"Padded Cell");
  249.             EM(CB_ADDSTRING,0,"Room");
  250.             EM(CB_ADDSTRING,0,"Bathroom");
  251.             EM(CB_ADDSTRING,0,"Living Room");
  252.             EM(CB_ADDSTRING,0,"Stone Room");
  253.             EM(CB_ADDSTRING,0,"Auditorium");
  254.             EM(CB_ADDSTRING,0,"Concert Hall");
  255.             EM(CB_ADDSTRING,0,"Cave");
  256.             EM(CB_ADDSTRING,0,"Arena");
  257.             EM(CB_ADDSTRING,0,"Hangar");
  258.             EM(CB_ADDSTRING,0,"Carpeted Hallway");
  259.             EM(CB_ADDSTRING,0,"Hallway");
  260.             EM(CB_ADDSTRING,0,"Stone Corridor");
  261.             EM(CB_ADDSTRING,0,"Alley");
  262.             EM(CB_ADDSTRING,0,"Forest");
  263.             EM(CB_ADDSTRING,0,"City");
  264.             EM(CB_ADDSTRING,0,"Mountains");
  265.             EM(CB_ADDSTRING,0,"Quarry");
  266.             EM(CB_ADDSTRING,0,"Plain");
  267.             EM(CB_ADDSTRING,0,"Parking Lot");
  268.             EM(CB_ADDSTRING,0,"Sewer Pipe");
  269.             EM(CB_ADDSTRING,0,"Under Water");
  270.             EM(CB_ADDSTRING,0,"Drugged");
  271.             EM(CB_ADDSTRING,0,"Dizzy");
  272.             EM(CB_ADDSTRING,0,"Psychotic");
  273.             EM(CB_SETCURSEL,0,0);
  274.  
  275.             MESS(ID_ROLLOFF,TBM_SETRANGE,FALSE,MAKELONG(0,20));
  276.             MESS(ID_ROLLOFF,TBM_SETPOS,TRUE,10);
  277.             MESS(ID_DOPPLER,TBM_SETRANGE,FALSE,MAKELONG(0,20));
  278.             MESS(ID_DOPPLER,TBM_SETPOS,TRUE,10);
  279.  
  280.             SetTimer(h,1,TIMERPERIOD,&Update);
  281.             GetCurrentDirectory(MAX_PATH,path);
  282.             memset(&ofn,0,sizeof(ofn));
  283.             ofn.lStructSize=sizeof(ofn);
  284.             ofn.hwndOwner=h;
  285.             ofn.nMaxFile=MAX_PATH;
  286.             ofn.lpstrInitialDir=path;
  287.             ofn.Flags=OFN_HIDEREADONLY|OFN_EXPLORER;
  288.             ofn.lpstrFilter="wav/aif/mo3/xm/mod/s3m/it/mtm/umx\0*.wav;*.aif;*.mo3;*.xm;*.mod;*.s3m;*.it;*.mtm;*.umx\0"
  289.                 "All files\0*.*\0\0";
  290.             return 1;
  291.  
  292.         case WM_DESTROY:
  293.             KillTimer(h,1);
  294.             DeleteObject(brush1);
  295.             DeleteObject(brush2);
  296.             if (chans) free(chans);
  297.             PostQuitMessage(0);
  298.             break;
  299.     }
  300.     return 0;
  301. }
  302.  
  303.  
  304. // Simple device selector dialog stuff begins here
  305. BOOL CALLBACK devicedialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
  306. {
  307.     switch (m) {
  308.         case WM_COMMAND:
  309.             switch (LOWORD(w)) {
  310.                 case ID_DEVLIST:
  311.                     if (HIWORD(w)!=LBN_DBLCLK) break;
  312.                 case IDOK:
  313.                     {
  314.                         int device=SendDlgItemMessage(h,ID_DEVLIST,LB_GETCURSEL,0,0);
  315.                         device=SendDlgItemMessage(h,ID_DEVLIST,LB_GETITEMDATA,device,0); // get device #
  316.                         EndDialog(h,device);
  317.                     }
  318.                     break;
  319.             }
  320.             break;
  321.  
  322.         case WM_INITDIALOG:
  323.             {
  324.                 char text[100],*d;
  325.                 int c,idx;
  326.                 for (c=1;d=BASS_GetDeviceDescription(c);c++) { // device 1 = 1st real device
  327.                     strcpy(text,d);
  328.                     /* Check if the device supports 3D */
  329.                     if (!BASS_Init(c,44100,BASS_DEVICE_3D,h,NULL))
  330.                         continue; // no 3D support
  331.                     if (BASS_GetEAXParameters(NULL,NULL,NULL,NULL))
  332.                         strcat(text," [EAX]"); // it has EAX
  333.                     BASS_Free();
  334.                     idx=SendDlgItemMessage(h,ID_DEVLIST,LB_ADDSTRING,0,(int)text);
  335.                     SendDlgItemMessage(h,ID_DEVLIST,LB_SETITEMDATA,idx,c); // store device #
  336.                     
  337.                 }
  338.                 SendDlgItemMessage(h,ID_DEVLIST,LB_SETCURSEL,0,0);
  339.             }
  340.             return 1;
  341.     }
  342.     return 0;
  343. }
  344. // Device selector stuff ends here
  345.  
  346. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
  347. {
  348.     MSG msg;
  349.     int device;
  350.  
  351.     /* Check that BASS 2.2 was loaded */
  352.     if (BASS_GetVersion()!=MAKELONG(2,2)) {
  353.         MessageBox(0,"BASS version 2.2 was not loaded","Incorrect BASS.DLL",0);
  354.         return 0;
  355.     }
  356.  
  357.     { // enable trackbar support
  358.         INITCOMMONCONTROLSEX cc={sizeof(cc),ICC_BAR_CLASSES};
  359.         InitCommonControlsEx(&cc);
  360.     }
  361.  
  362.     /* Create the main window */
  363.     if (!CreateDialog(hInstance,MAKEINTRESOURCE(1000),NULL,&dialogproc)) {
  364.         Error("Can't create window");
  365.         return 0;
  366.     }
  367.  
  368.     /* Let the user choose an output device */
  369.     device=DialogBox(hInstance,(char*)2000,win,&devicedialogproc);
  370.  
  371.     /* Initialize the output device with 3D support */
  372.     if (!BASS_Init(device,44100,BASS_DEVICE_3D,win,NULL)) {
  373.         Error("Can't initialize output device");
  374.         EndDialog(win,0);
  375.         return 0;
  376.     }
  377.  
  378.     /* Use meters as distance unit, real world rolloff, real doppler effect */
  379.     BASS_Set3DFactors(1,1,1);
  380.     /* Turn EAX off (volume=0), if error then EAX is not supported */
  381.     if (BASS_SetEAXParameters(-1,0,-1,-1))
  382.         EnableWindow(GetDlgItem(win,ID_EAX),TRUE);
  383.  
  384.     while (GetMessage(&msg,NULL,0,0)>0) {
  385.         if (!IsDialogMessage(win,&msg)) {
  386.             TranslateMessage(&msg);
  387.             DispatchMessage(&msg);
  388.         }
  389.     }
  390.     
  391.     BASS_Free();
  392.  
  393.     return 0;
  394. }
  395.