home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 May / PCFMay2001.iso / Xenon / ModBass / c / 3dtest.c next >
Encoding:
C/C++ Source or Header  |  2000-01-18  |  16.4 KB  |  564 lines

  1. /* BASS 3D Test, copyright (c) 1999-2000 Ian Luck.
  2. ==================================================
  3. Other source: 3dtest.rc
  4. Imports: bass.lib, kernel32.lib, user32.lib, comdlg32.lib, gdi32.lib
  5. */
  6.  
  7. #include <windows.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <math.h>
  11. #include "bass.h"
  12. #include "3dtest.h"
  13.  
  14. static HWND win=NULL;
  15. static HINSTANCE inst;
  16.  
  17. /* channel (sample/music) info structure */
  18. typedef struct {
  19.     HSAMPLE sample;            // sample handle (NULL if it's a MOD music)
  20.     DWORD channel;            // the channel
  21.     BASS_3DVECTOR pos,vel;    // position,velocity
  22.     int dir;                // direction of the channel
  23. } Channel;
  24.  
  25. static Channel *chans=NULL;        // the channels
  26. static int chanc=0,chan=-1;        // number of channels, current channel
  27. static HBRUSH brush1,brush2;    // brushes
  28.  
  29. #define TIMERPER    50            // timer period (ms)
  30. #define MAXDIST        500.0        // maximum distance of the channels (m)
  31. #define SPEED        5.0            // speed of the channels' movement (m/s)
  32.  
  33. /* Display error dialogs */
  34. static void Error(char *es)
  35. {
  36.     char mes[200];
  37.     sprintf(mes,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
  38.     MessageBox(win,mes,"Error",0);
  39. }
  40.  
  41. /* Messaging macros */
  42. #define ITEM(id) GetDlgItem(win,id)
  43. #define MESS(id,m,w,l) SendDlgItemMessage(win,id,m,(WPARAM)w,(LPARAM)l)
  44. #define LM(m,w,l) MESS(ID_LIST,m,w,l)
  45. #define EM(m,w,l) MESS(ID_EAX,m,w,l)
  46.  
  47. void CALLBACK Update(HWND win, UINT m, UINT i, DWORD t)
  48. {
  49.     HDC dc;
  50.     RECT r;
  51.     int c,x,y,cx,cy;
  52.     int save;
  53.     HPEN pen;
  54.  
  55.     win=ITEM(ID_DISPLAY);
  56.     dc=GetDC(win);
  57.     save=SaveDC(dc);
  58.     GetClientRect(win,&r);
  59.     cx=r.right/2;
  60.     cy=r.bottom/2;
  61.  
  62.     /* Draw center circle */
  63.     SelectObject(dc,GetStockObject(GRAY_BRUSH));
  64.     Ellipse(dc,cx-4,cy-4,cx+4,cy+4);
  65.  
  66.     pen=CreatePen(PS_SOLID,2,GetSysColor(COLOR_BTNFACE));
  67.     SelectObject(dc,pen);
  68.  
  69.     for (c=0;c<chanc;c++) {
  70.         /* If the channel's playing then update it's position */
  71.         if (BASS_ChannelIsActive(chans[c].channel)) {
  72.             /* Check if channel has reached the max distance */
  73.             if (chans[c].pos.z>=MAXDIST || chans[c].pos.z<=-MAXDIST)
  74.                 chans[c].vel.z=-chans[c].vel.z;
  75.             if (chans[c].pos.x>=MAXDIST || chans[c].pos.x<=-MAXDIST)
  76.                 chans[c].vel.x=-chans[c].vel.x;
  77.             /* Update channel position */
  78.             chans[c].pos.z+=chans[c].vel.z*(float)TIMERPER/1000.0;
  79.             chans[c].pos.x+=chans[c].vel.x*(float)TIMERPER/1000.0;
  80.             BASS_ChannelSet3DPosition(chans[c].channel,&chans[c].pos,NULL,&chans[c].vel);
  81.         }
  82.         /* Draw the channel position indicator */
  83.         x=cx+(int)((float)cx*chans[c].pos.x/(float)(MAXDIST+45));
  84.         y=cy-(int)((float)cy*chans[c].pos.z/(float)(MAXDIST+45));
  85.         if (chan==c)
  86.             SelectObject(dc,brush1);
  87.         else
  88.             SelectObject(dc,brush2);
  89.         Ellipse(dc,x-6,y-6,x+6,y+6);
  90.     }
  91.     /* Apply the 3D changes */
  92.     BASS_Apply3D();
  93.  
  94.     RestoreDC(dc,save);
  95.     DeleteObject(pen);
  96.     ReleaseDC(win,dc);
  97. }
  98.  
  99. /* Update the button states */
  100. static void UpdateButtons()
  101. {
  102.     int a;
  103.     EnableWindow(ITEM(ID_REMOVE),chan==-1?FALSE:TRUE);
  104.     EnableWindow(ITEM(ID_PLAY),chan==-1?FALSE:TRUE);
  105.     EnableWindow(ITEM(ID_STOP),chan==-1?FALSE:TRUE);
  106.     for (a=0;a<5;a++)
  107.         EnableWindow(ITEM(ID_LEFT+a),chan==-1?FALSE:TRUE);
  108.     if (chan!=-1) {
  109.         MESS(ID_LEFT,BM_SETCHECK,chans[chan].dir==ID_LEFT?BST_CHECKED:BST_UNCHECKED,0);
  110.         MESS(ID_RIGHT,BM_SETCHECK,chans[chan].dir==ID_RIGHT?BST_CHECKED:BST_UNCHECKED,0);
  111.         MESS(ID_FRONT,BM_SETCHECK,chans[chan].dir==ID_FRONT?BST_CHECKED:BST_UNCHECKED,0);
  112.         MESS(ID_BEHIND,BM_SETCHECK,chans[chan].dir==ID_BEHIND?BST_CHECKED:BST_UNCHECKED,0);
  113.         MESS(ID_NONE,BM_SETCHECK,!chans[chan].dir?BST_CHECKED:BST_UNCHECKED,0);
  114.     }
  115. }
  116.  
  117. BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
  118. {
  119.     static OPENFILENAME ofn;
  120.     static char path[MAX_PATH];
  121.  
  122.     switch (m) {
  123.         case WM_COMMAND:
  124.             switch (LOWORD(w)) {
  125.                 case ID_EAX:
  126.                     /* Change the EAX environment */
  127.                     if (HIWORD(w)==CBN_SELCHANGE) {
  128.                         int s=EM(CB_GETCURSEL,0,0);
  129.                         switch (s) {
  130.                             case 0:
  131.                                 BASS_SetEAXParameters(-1,0.0,-1.0,-1.0);
  132.                                 break;
  133.                             case 1:
  134.                                 BASS_SetEAXParameters(EAX_PRESET_GENERIC);
  135.                                 break;
  136.                             case 2:
  137.                                 BASS_SetEAXParameters(EAX_PRESET_PADDEDCELL);
  138.                                 break;
  139.                             case 3:
  140.                                 BASS_SetEAXParameters(EAX_PRESET_ROOM);
  141.                                 break;
  142.                             case 4:
  143.                                 BASS_SetEAXParameters(EAX_PRESET_BATHROOM);
  144.                                 break;
  145.                             case 5:
  146.                                 BASS_SetEAXParameters(EAX_PRESET_LIVINGROOM);
  147.                                 break;
  148.                             case 6:
  149.                                 BASS_SetEAXParameters(EAX_PRESET_STONEROOM);
  150.                                 break;
  151.                             case 7:
  152.                                 BASS_SetEAXParameters(EAX_PRESET_AUDITORIUM);
  153.                                 break;
  154.                             case 8:
  155.                                 BASS_SetEAXParameters(EAX_PRESET_CONCERTHALL);
  156.                                 break;
  157.                             case 9:
  158.                                 BASS_SetEAXParameters(EAX_PRESET_CAVE);
  159.                                 break;
  160.                             case 10:
  161.                                 BASS_SetEAXParameters(EAX_PRESET_ARENA);
  162.                                 break;
  163.                             case 11:
  164.                                 BASS_SetEAXParameters(EAX_PRESET_HANGAR);
  165.                                 break;
  166.                             case 12:
  167.                                 BASS_SetEAXParameters(EAX_PRESET_CARPETEDHALLWAY);
  168.                                 break;
  169.                             case 13:
  170.                                 BASS_SetEAXParameters(EAX_PRESET_HALLWAY);
  171.                                 break;
  172.                             case 14:
  173.                                 BASS_SetEAXParameters(EAX_PRESET_STONECORRIDOR);
  174.                                 break;
  175.                             case 15:
  176.                                 BASS_SetEAXParameters(EAX_PRESET_ALLEY);
  177.                                 break;
  178.                             case 16:
  179.                                 BASS_SetEAXParameters(EAX_PRESET_FOREST);
  180.                                 break;
  181.                             case 17:
  182.                                 BASS_SetEAXParameters(EAX_PRESET_CITY);
  183.                                 break;
  184.                             case 18:
  185.                                 BASS_SetEAXParameters(EAX_PRESET_MOUNTAINS);
  186.                                 break;
  187.                             case 19:
  188.                                 BASS_SetEAXParameters(EAX_PRESET_QUARRY);
  189.                                 break;
  190.                             case 20:
  191.                                 BASS_SetEAXParameters(EAX_PRESET_PLAIN);
  192.                                 break;
  193.                             case 21:
  194.                                 BASS_SetEAXParameters(EAX_PRESET_PARKINGLOT);
  195.                                 break;
  196.                             case 22:
  197.                                 BASS_SetEAXParameters(EAX_PRESET_SEWERPIPE);
  198.                                 break;
  199.                             case 23:
  200.                                 BASS_SetEAXParameters(EAX_PRESET_UNDERWATER);
  201.                                 break;
  202.                             case 24:
  203.                                 BASS_SetEAXParameters(EAX_PRESET_DRUGGED);
  204.                                 break;
  205.                             case 25:
  206.                                 BASS_SetEAXParameters(EAX_PRESET_DIZZY);
  207.                                 break;
  208.                             case 26:
  209.                                 BASS_SetEAXParameters(EAX_PRESET_PSYCHOTIC);
  210.                                 break;
  211.                         }
  212.                     }
  213.                     return 1;
  214.                 case ID_A3DON:
  215.                     /* If A3D hi-freq absorbtion is switched on, set the absorbtion value
  216.                         ... else turn it off */
  217.                     if (MESS(ID_A3DON,BM_GETCHECK,0,0))
  218.                         BASS_SetA3DHFAbsorbtion(pow(2.0,(float)(MESS(ID_A3DHF,SBM_GETPOS,0,0)-10)/2.0));
  219.                     else
  220.                         BASS_SetA3DHFAbsorbtion(0.0);
  221.                     return 1;
  222.                 case ID_LIST:
  223.                     /* Change the selected channel */
  224.                     if (HIWORD(w)!=LBN_SELCHANGE) break;
  225.                     chan=LM(LB_GETCURSEL,0,0);
  226.                     if (chan==LB_ERR) chan=-1;
  227.                     UpdateButtons();
  228.                     return 1;
  229.                 case ID_LEFT:
  230.                     if (HIWORD(w)!=BN_CLICKED) break;
  231.                     chans[chan].dir=ID_LEFT;
  232.                     /* Make the channel move past the left of you */
  233.                     /* Set speed in m/s */
  234.                     chans[chan].vel.z=SPEED*1000.0/(float)TIMERPER;
  235.                     chans[chan].vel.x=0.0;
  236.                     /* Set positon to the left */
  237.                     chans[chan].pos.x=-40.0;
  238.                     /* Reset display */
  239.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  240.                     return 1;
  241.                 case ID_RIGHT:
  242.                     if (HIWORD(w)!=BN_CLICKED) break;
  243.                     chans[chan].dir=ID_RIGHT;
  244.                     /* Make the channel move past the right of you */
  245.                     chans[chan].vel.z=SPEED*1000.0/(float)TIMERPER;
  246.                     chans[chan].vel.x=0.0;
  247.                     /* Set positon to the right */
  248.                     chans[chan].pos.x=40.0;
  249.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  250.                     return 1;
  251.                 case ID_FRONT:
  252.                     if (HIWORD(w)!=BN_CLICKED) break;
  253.                     chans[chan].dir=ID_FRONT;
  254.                     /* Make the channel move past the front of you */
  255.                     chans[chan].vel.x=SPEED*1000.0/(float)TIMERPER;
  256.                     chans[chan].vel.z=0.0;
  257.                     /* Set positon to in front */
  258.                     chans[chan].pos.z=40.0;
  259.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  260.                     return 1;
  261.                 case ID_BEHIND:
  262.                     if (HIWORD(w)!=BN_CLICKED) break;
  263.                     chans[chan].dir=ID_BEHIND;
  264.                     /* Make the channel move past the back of you */
  265.                     chans[chan].vel.x=SPEED*1000.0/(float)TIMERPER;
  266.                     chans[chan].vel.z=0.0;
  267.                     /* Set positon to behind */
  268.                     chans[chan].pos.z=-40.0;
  269.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  270.                     return 1;
  271.                 case ID_NONE:
  272.                     if (HIWORD(w)!=BN_CLICKED) break;
  273.                     chans[chan].dir=0;
  274.                     /* Make the channel stop moving */
  275.                     chans[chan].vel.x=chans[chan].vel.z=0.0;
  276.                     return 1;
  277.                 case ID_ADD:
  278.                     {
  279.                         char file[MAX_PATH]="";
  280.                         DWORD newchan;
  281.                         ofn.lpstrFile=file;
  282.                         if (GetOpenFileName(&ofn)) {
  283.                             memcpy(path,file,ofn.nFileOffset);
  284.                             path[ofn.nFileOffset-1]=0;
  285.                             /* Load a music from "file" with 3D enabled, and make it loop & use ramping */
  286.                             if (newchan=BASS_MusicLoad(FALSE,file,0,0,BASS_MUSIC_RAMP|BASS_MUSIC_LOOP|BASS_MUSIC_3D)) {
  287.                                 Channel *c;
  288.                                 chanc++;
  289.                                 chans=(Channel*)realloc((void*)chans,chanc*sizeof(Channel));
  290.                                 c=chans+chanc-1;
  291.                                 memset(c,0,sizeof(Channel));
  292.                                 c->channel=newchan;
  293.                                 LM(LB_ADDSTRING,0,file);
  294.                                 /* Set the min/max distance to 15/1000 meters */
  295.                                 BASS_ChannelSet3DAttributes(newchan,-1,35.0,1000.0,-1,-1,-1);
  296.                             } else
  297.                             /* Load a sample from "file" with 3D enabled, and make it loop */
  298.                             if (newchan=BASS_SampleLoad(FALSE,file,0,0,1,BASS_SAMPLE_LOOP|BASS_SAMPLE_3D|BASS_SAMPLE_VAM)) {
  299.                                 Channel *c;
  300.                                 BASS_SAMPLE sam;
  301.                                 chanc++;
  302.                                 chans=(Channel*)realloc((void*)chans,chanc*sizeof(Channel));
  303.                                 c=chans+chanc-1;
  304.                                 memset(c,0,sizeof(Channel));
  305.                                 c->sample=newchan;
  306.                                 LM(LB_ADDSTRING,0,file);
  307.                                 /* Set the min/max distance to 15/1000 meters */
  308.                                 BASS_SampleGetInfo(newchan,&sam);
  309.                                 sam.mindist=35.0;
  310.                                 sam.maxdist=1000.0;
  311.                                 BASS_SampleSetInfo(newchan,&sam);
  312.                             } else
  313.                                 Error("Can't load file");
  314.                         }
  315.                     }
  316.                     return 1;
  317.                 case ID_REMOVE:
  318.                     {
  319.                         Channel *c=chans+chan;
  320.                         if (c->sample)
  321.                             BASS_SampleFree(c->sample);
  322.                         else
  323.                             BASS_MusicFree(c->channel);
  324.                         memcpy(c,c+1,(chanc-chan-1)*sizeof(Channel));
  325.                         chanc--;
  326.                         LM(LB_DELETESTRING,chan,0);
  327.                         chan=-1;
  328.                         UpdateButtons();
  329.                         InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  330.                     }
  331.                     return 1;
  332.                 case ID_PLAY:
  333.                     {
  334.                         if (chans[chan].sample) {
  335.                             if (!chans[chan].channel)
  336.                                 chans[chan].channel=BASS_SamplePlay3D(chans[chan].sample,&chans[chan].pos,NULL,&chans[chan].vel);
  337.                         } else
  338.                             BASS_MusicPlay(chans[chan].channel);
  339.                     }
  340.                     return 1;
  341.                 case ID_STOP:
  342.                     BASS_ChannelStop(chans[chan].channel);
  343.                     if (chans[chan].sample) chans[chan].channel=0;
  344.                     return 1;
  345.                 case IDCANCEL:
  346.                     DestroyWindow(h);
  347.                     return 1;
  348.             }
  349.             break;
  350.  
  351.         case WM_HSCROLL:
  352.             {
  353.                 int a=SendMessage(l,SBM_GETPOS,0,0);
  354.                 switch (LOWORD(w)) {
  355.                     case SB_THUMBTRACK:
  356.                     case SB_THUMBPOSITION:
  357.                         a=HIWORD(w);
  358.                         break;
  359.                     case SB_LINELEFT:
  360.                         a=max(a-1,0);
  361.                         break;
  362.                     case SB_LINERIGHT:
  363.                         a=min(a+1,20);
  364.                         break;
  365.                     case SB_PAGELEFT:
  366.                         a=max(a-5,0);
  367.                         break;
  368.                     case SB_PAGERIGHT:
  369.                         a=min(a+5,20);
  370.                         break;
  371.                 }
  372.                 PostMessage(l,SBM_SETPOS,a,1);
  373.                 switch (GetDlgCtrlID(l)) {
  374.                     case ID_A3DHF:
  375.                         /* If A3D hi-freq absorbtion is on, change the setting */
  376.                         if (MESS(ID_A3DON,BM_GETCHECK,0,0))
  377.                             BASS_SetA3DHFAbsorbtion(pow(2.0,(float)(a-10)/2.0));
  378.                         break;
  379.                     case ID_ROLLOFF:
  380.                         /* change the rolloff factor */
  381.                         BASS_Set3DFactors(-1.0,pow(2.0,(float)(a-10)/4.0),-1.0);
  382.                         break;
  383.                     case ID_DOPPLER:
  384.                         /* change the doppler factor */
  385.                         BASS_Set3DFactors(-1.0,-1.0,pow(2.0,(float)(a-10)/4.0));
  386.                         break;
  387.                 }
  388.             }
  389.             return 1;
  390.  
  391.         case WM_INITDIALOG:
  392.             win=h;
  393.             brush1=CreateSolidBrush(0xff);
  394.             brush2=CreateSolidBrush(0);
  395.  
  396.             EM(CB_ADDSTRING,0,"Off");
  397.             EM(CB_ADDSTRING,0,"Generic");
  398.             EM(CB_ADDSTRING,0,"Padded Cell");
  399.             EM(CB_ADDSTRING,0,"Room");
  400.             EM(CB_ADDSTRING,0,"Bathroom");
  401.             EM(CB_ADDSTRING,0,"Living Room");
  402.             EM(CB_ADDSTRING,0,"Stone Room");
  403.             EM(CB_ADDSTRING,0,"Auditorium");
  404.             EM(CB_ADDSTRING,0,"Concert Hall");
  405.             EM(CB_ADDSTRING,0,"Cave");
  406.             EM(CB_ADDSTRING,0,"Arena");
  407.             EM(CB_ADDSTRING,0,"Hangar");
  408.             EM(CB_ADDSTRING,0,"Carpeted Hallway");
  409.             EM(CB_ADDSTRING,0,"Hallway");
  410.             EM(CB_ADDSTRING,0,"Stone Corridor");
  411.             EM(CB_ADDSTRING,0,"Alley");
  412.             EM(CB_ADDSTRING,0,"Forest");
  413.             EM(CB_ADDSTRING,0,"City");
  414.             EM(CB_ADDSTRING,0,"Mountains");
  415.             EM(CB_ADDSTRING,0,"Quarry");
  416.             EM(CB_ADDSTRING,0,"Plain");
  417.             EM(CB_ADDSTRING,0,"Parking Lot");
  418.             EM(CB_ADDSTRING,0,"Sewer Pipe");
  419.             EM(CB_ADDSTRING,0,"Under Water");
  420.             EM(CB_ADDSTRING,0,"Drugged");
  421.             EM(CB_ADDSTRING,0,"Dizzy");
  422.             EM(CB_ADDSTRING,0,"Psychotic");
  423.             EM(CB_SETCURSEL,0,0);
  424.  
  425.             MESS(ID_A3DHF,SBM_SETRANGE,0,20);
  426.             MESS(ID_A3DHF,SBM_SETPOS,10,0);
  427.             MESS(ID_ROLLOFF,SBM_SETRANGE,0,20);
  428.             MESS(ID_ROLLOFF,SBM_SETPOS,10,0);
  429.             MESS(ID_DOPPLER,SBM_SETRANGE,0,20);
  430.             MESS(ID_DOPPLER,SBM_SETPOS,10,0);
  431.  
  432.             SetTimer(h,1,TIMERPER,&Update);
  433.             GetCurrentDirectory(MAX_PATH,path);
  434.             memset(&ofn,0,sizeof(ofn));
  435.             ofn.lStructSize=sizeof(ofn);
  436.             ofn.hwndOwner=h;
  437.             ofn.hInstance=inst;
  438.             ofn.nMaxFile=MAX_PATH;
  439.             ofn.lpstrInitialDir=path;
  440.             ofn.Flags=OFN_HIDEREADONLY|OFN_EXPLORER;
  441.             ofn.lpstrFilter="wav/mo3/xm/mod/s3m/it/mtm\0*.wav;*.mo3;*.xm;*.mod;*.s3m;*.it;*.mtm\0"
  442.                 "All files\0*.*\0\0";
  443.             return 1;
  444.  
  445.         case WM_DESTROY:
  446.             KillTimer(h,1);
  447.             DeleteObject(brush1);
  448.             DeleteObject(brush2);
  449.             if (chans) free(chans);
  450.             PostQuitMessage(0);
  451.             return 1;
  452.     }
  453.     return 0;
  454. }
  455.  
  456.  
  457. // Simple device selector dialog stuff begins here
  458. int device;        // selected device
  459. BOOL lowqual;    // low quality option
  460.  
  461. BOOL CALLBACK devicedialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
  462. {
  463.     switch (m) {
  464.         case WM_COMMAND:
  465.             switch (LOWORD(w)) {
  466.                 case ID_DEVLIST:
  467.                     if (HIWORD(w)==LBN_SELCHANGE)
  468.                         device=SendMessage(l,LB_GETCURSEL,0,0);
  469.                     else if (HIWORD(w)==LBN_DBLCLK)
  470.                         EndDialog(h,0);
  471.                     break;
  472.                 case ID_LOWQUAL:
  473.                     lowqual=SendDlgItemMessage(h,ID_LOWQUAL,BM_GETCHECK,0,0);
  474.                     break;
  475.                 case IDOK:
  476.                     EndDialog(h,0);
  477.                     return 1;
  478.             }
  479.             break;
  480.  
  481.         case WM_INITDIALOG:
  482.             {
  483.                 char text[100],*d;
  484.                 int c;
  485.                 for (c=0;BASS_GetDeviceDescription(c,&d);c++) {
  486.                     strcpy(text,d);
  487.                     /* Check if the device supports A3D or EAX */
  488.                     if (!BASS_Init(c,44100,BASS_DEVICE_A3D,h)) {
  489.                         if (!BASS_Init(c,44100,BASS_DEVICE_3D,h))
  490.                             continue; // no 3D support
  491.                     } else
  492.                         strcat(text," [A3D]"); // it has A3D
  493.                     if (BASS_GetEAXParameters(NULL,NULL,NULL,NULL))
  494.                         strcat(text," [EAX]"); // it has EAX
  495.                     BASS_Free();
  496.                     SendDlgItemMessage(h,ID_DEVLIST,LB_ADDSTRING,0,text);
  497.                 }
  498.                 SendDlgItemMessage(h,ID_DEVLIST,LB_SETCURSEL,0,0);
  499.             }
  500.             device=lowqual=0;
  501.             return 1;
  502.     }
  503.     return 0;
  504. }
  505. // Device selector stuff ends here
  506.  
  507. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
  508. {
  509.     MSG msg;
  510.     inst=hInstance;
  511.  
  512.     /* Check that BASS 0.8 was loaded */
  513.     if (BASS_GetVersion()!=MAKELONG(0,8)) {
  514.         MessageBox(0,"BASS version 0.8 was not loaded","Incorrect BASS.DLL",0);
  515.         return 0;
  516.     }
  517.  
  518.     /* Create the main window */
  519.     if (!CreateDialog(hInstance,MAKEINTRESOURCE(1000),NULL,&dialogproc)) {
  520.         Error("Can't create window");
  521.         return 0;
  522.     }
  523.  
  524.     /* Let the user choose an output device */
  525.     DialogBox(inst,2000,win,&devicedialogproc);
  526.  
  527.     /* Initialize the output device with A3D (syncs not used) */
  528.     if (!BASS_Init(device,lowqual?22050:44100,BASS_DEVICE_NOSYNC|BASS_DEVICE_A3D,win)) {
  529.         /* no A3D, so try without... */
  530.         if (!BASS_Init(device,lowqual?22050:44100,BASS_DEVICE_NOSYNC|BASS_DEVICE_3D,win)) {
  531.             Error("Can't initialize output device");
  532.             EndDialog(win,0);
  533.             return 0;
  534.         }
  535.     } else {
  536.         /* enable A3D HF absorbtion option */
  537.         EnableWindow(GetDlgItem(win,ID_A3DON),TRUE);
  538.         EnableWindow(GetDlgItem(win,ID_A3DHF),TRUE);
  539.         BASS_SetA3DHFAbsorbtion(0.0);
  540.     }
  541.  
  542.     /* Use meters as distance unit, real world rolloff, real doppler effect */
  543.     BASS_Set3DFactors(1.0,1.0,1.0);
  544.     /* Turn EAX off (volume=0.0), if error then EAX is not supported */
  545.     if (BASS_SetEAXParameters(-1,0.0,-1.0,-1.0))
  546.         EnableWindow(GetDlgItem(win,ID_EAX),TRUE);
  547.     BASS_Start();    /* Start digital output */
  548.             
  549.     while (1) {
  550.         if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
  551.             if (!GetMessage(&msg, NULL, 0, 0))
  552.                 break;
  553.             TranslateMessage(&msg);
  554.             DispatchMessage(&msg);
  555.         } else
  556.             WaitMessage();
  557.     }
  558.     
  559.     BASS_Stop();
  560.     BASS_Free();
  561.  
  562.     return 0;
  563. }
  564.