Al's Programming Resource Homepage  Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

sound.cpp

Go to the documentation of this file.
00001 #include "sound.h"
00002 #include "tll.h"
00003 #include "camera.h"
00004 #include "resource.rh"
00005 #include "mmgr.h"
00006 
00007 extern int device;
00008 extern BOOL lowqual;
00009 extern int SphereSector;
00010 extern VECTOR SpherePosition;
00011 extern int numSamples;
00012 extern int numChannels;
00013 extern LinkedList<SOUND_SAMPLE> SampleList;
00014 extern LinkedList<SOUND_CHANNEL> ChannelList;
00015 extern HWND hWnd;
00016 extern CAMERA* camera;
00017 extern CAMERA LastCam;
00018 extern int currentCamera;
00019 
00020 int SOUND_SAMPLE::Compare(const SOUND_SAMPLE& Sample)
00021 {
00022     if (linkPosition < Sample.linkPosition)
00023         return smaller;
00024       if (linkPosition > Sample.linkPosition)
00025         return bigger;
00026       else
00027         return same;
00028 }
00029 
00030 int SOUND_CHANNEL::Compare(const SOUND_CHANNEL& Channel)
00031 {
00032     if (linkPosition < Channel.linkPosition)
00033         return smaller;
00034       if (linkPosition > Channel.linkPosition)
00035         return bigger;
00036       else
00037         return same;
00038 }
00039 
00040 void InitializeBASS()
00041 {
00042     /* Check that BASS 1.4 was loaded */
00043     if (BASS_GetVersion() != MAKELONG(1, 4))
00044         MessageBox(0, "BASS version 1.4 was not loaded", "Incorrect BASS.DLL", 0);
00045 
00046     /* Initialize the output device (syncs not used) */
00047     if (!BASS_Init(device, lowqual?22050:44100, BASS_DEVICE_3D, hWnd))
00048         MessageBox(0, "Could not initialize output device", "Error", 0);
00049 
00050     /* Use meters as distance unit, real world rolloff, real doppler effect */
00051     BASS_Set3DFactors(1.0, 1.0, 1.0);
00052 
00053     /* Turn EAX off (volume=0.0), if error then EAX is not supported */
00054     BASS_SetEAXParameters(-1, 0.0, -1.0, -1.0);
00055 
00056     BASS_Start();    /* Start digital output */
00057 }
00058 
00059 
00060 void LoadSample(SOUND_SAMPLE* Sample)
00061 {
00062     /* Load a sample from a file */
00063     Sample->hSample = BASS_SampleLoad(FALSE, Sample->name, 0, 0, Sample->max, Sample->flags);
00064     if (Sample->hSample)
00065     {
00066         BASS_SAMPLE sampleInfo;
00067         BASS_SampleGetInfo(Sample->hSample, &sampleInfo);
00068 
00069         sampleInfo.volume = Sample->volume;
00070         sampleInfo.mindist = Sample->mindist;
00071         sampleInfo.maxdist = Sample->maxdist;
00072         BASS_SampleSetInfo(Sample->hSample, &sampleInfo);
00073 
00074         Sample->linkPosition = ++numSamples;
00075         SampleList.Insert(Sample);
00076     }
00077     else
00078         MessageBox(NULL,"Could not load sound sample","Error",MB_OK|MB_ICONERROR);
00079 }
00080 
00081 void CreateChannel(int SampleNumber)
00082 {
00083     SOUND_SAMPLE* Sample = SampleList.Get(SampleNumber);
00084     SOUND_CHANNEL* Channel = new SOUND_CHANNEL;
00085     Channel->hSample = Sample->hSample;
00086     Channel->linkPosition = ++numChannels;
00087     ChannelList.Insert(Channel);
00088 }
00089 
00090 void UpdateListener()
00091 {
00092     BASS_3DVECTOR Player;
00093     BASS_3DVECTOR Bass_Front;
00094     BASS_3DVECTOR Bass_Top;
00095     BASS_3DVECTOR Bass_Velocity;
00096 
00097     Player.x = camera[currentCamera].Position.x;       // Get the player's position
00098     Player.y = camera[currentCamera].Position.y;
00099     Player.z = camera[currentCamera].Position.z;
00100     VECTOR Front = camera[currentCamera].GetZUnit();   // Get the player's front vector
00101     VECTOR Top = camera[currentCamera].GetYUnit();     // Get the player's up vector
00102     Bass_Front.x = -Front.x;                           // Reverse the front vector for OpenGL
00103     Bass_Front.y = -Front.y;
00104     Bass_Front.z = -Front.z;
00105     Bass_Top.x = Top.x;
00106     Bass_Top.y = Top.y;
00107     Bass_Top.z = Top.z;
00108     Bass_Velocity.x = camera[currentCamera].Position.x - LastCam.Position.x;
00109     Bass_Velocity.y = camera[currentCamera].Position.y - LastCam.Position.y;
00110     Bass_Velocity.z = camera[currentCamera].Position.z - LastCam.Position.z;
00111 
00112     BASS_Set3DPosition(&Player, &Bass_Velocity, &Bass_Front, &Bass_Top);  // Make changes to the player position/orientation
00113 
00114     /* Apply the 3D changes */
00115     BASS_Apply3D();
00116 }
00117 
00118 void UpdateChannel(int ChannelNumber, VECTOR* Position, VECTOR* Orientation, VECTOR* Velocity)
00119 {
00120     SOUND_CHANNEL* Channel = ChannelList.Get(ChannelNumber);
00121 
00122     if (Position)
00123     {
00124         Channel->position.x = Position->x;
00125         Channel->position.y = Position->y;
00126         Channel->position.z = Position->z;
00127     }
00128     if (Orientation)
00129     {
00130         Channel->orientation.x = Orientation->x;
00131         Channel->orientation.y = Orientation->y;
00132         Channel->orientation.z = Orientation->z;
00133     }
00134     if (Velocity)
00135     {
00136         Channel->velocity.x = Velocity->x;
00137         Channel->velocity.y = Velocity->y;
00138         Channel->velocity.z = Velocity->z;
00139     }
00140 
00141     /* If the channel's playing then update it's position */
00142     if (BASS_ChannelIsActive(Channel->hChannel))
00143         BASS_ChannelSet3DPosition(Channel->hChannel, &Channel->position, NULL, &Channel->velocity);
00144 
00145     /* Apply the 3D changes */
00146     BASS_Apply3D();
00147 }
00148 
00149 void PlayChannel(int ChannelNumber)
00150 {
00151     SOUND_CHANNEL* Channel = ChannelList.Get(ChannelNumber);
00152     Channel->hChannel = BASS_SamplePlay3D(Channel->hSample, &Channel->position, NULL, &Channel->velocity);
00153 
00154     char temp[256];
00155     int result = BASS_ErrorGetCode();
00156     if (result)
00157     {
00158         sprintf(temp, "BASS error code No. %d", result);
00159         MessageBox(NULL, temp, "Error", MB_OK|MB_ICONERROR);
00160     }
00161 }
00162 
00163 VOID CALLBACK SoundTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
00164 {
00165     SOUND_CHANNEL* Channel = ChannelList.Get((int)idEvent);
00166     PlayChannel((int)idEvent);
00167     if ((Channel->looped && !Channel->intermittent) || !Channel->looped)
00168         KillTimer(hWnd, idEvent);
00169     if (Channel->looped && Channel->intermittent && Channel->random)
00170     {
00171         int randomtime = (rand()%(Channel->upperrand - Channel->lowerrand)) + Channel->lowerrand;
00172         SetTimer(hWnd, idEvent, randomtime,    (TIMERPROC)SoundTimerProc);
00173     }
00174 }
00175 
00176 void CreateSounds()
00177 {
00178     SOUND_SAMPLE* Sample;
00179     SOUND_CHANNEL* Channel;
00180     VECTOR Position;
00181 
00182 // engine sound
00183     Sample = new SOUND_SAMPLE;
00184     sprintf(Sample->name, "%s", "engine.wav");
00185     Sample->max = 10;
00186     Sample->volume = 100;
00187     Sample->mindist = 10.0;
00188     Sample->maxdist = 1000.0;
00189     Sample->flags = BASS_SAMPLE_OVER_DIST | BASS_SAMPLE_LOOP | BASS_SAMPLE_3D | BASS_SAMPLE_VAM;
00190     LoadSample(Sample);           // Load the sample and put it in the sample list
00191 
00192     CreateChannel(sample_engine); // Create a new channel with the sample and put it in the channel list
00193     Channel = ChannelList.Get(channel_engine);
00194     Channel->looped = true;
00195     Channel->intermittent = false;
00196     Channel->random = false;
00197     Channel->interval = 2000;
00198     Channel->idEvent = (unsigned int)channel_engine;
00199     SetTimer(hWnd, Channel->idEvent, Channel->interval, (TIMERPROC)SoundTimerProc);
00200 
00201 // water drips
00202     Sample = new SOUND_SAMPLE;
00203     sprintf(Sample->name, "%s", "waterdrop.wav");
00204     Sample->max = 10;
00205     Sample->volume = 20;
00206     Sample->mindist = 12.0;
00207     Sample->maxdist = 100.0;
00208     Sample->flags = BASS_SAMPLE_OVER_DIST | BASS_SAMPLE_MUTEMAX | BASS_SAMPLE_3D | BASS_SAMPLE_VAM;
00209     LoadSample(Sample);
00210 
00211     // 1st drip
00212     CreateChannel(sample_drip);
00213     Channel = ChannelList.Get(channel_drip1);
00214     Channel->looped = true;
00215     Channel->intermittent = true;
00216     Channel->random = false;
00217     Channel->interval = 1000;
00218     Channel->idEvent = (unsigned int)channel_drip1;
00219     SetTimer(hWnd, Channel->idEvent, Channel->interval, (TIMERPROC)SoundTimerProc);
00220     Position.x = 150.0;
00221     Position.y = -10.0;
00222     Position.z = -30.0;
00223     UpdateChannel(channel_drip1, &Position, NULL, NULL);
00224 
00225     // 2nd drip
00226     CreateChannel(sample_drip);
00227     Channel = ChannelList.Get(channel_drip2);
00228     Channel->looped = true;
00229     Channel->intermittent = true;
00230     Channel->random = true;
00231     Channel->lowerrand = 800;
00232     Channel->upperrand = 8000;
00233     Channel->interval = 1000;
00234     Channel->idEvent = (unsigned int)channel_drip2;
00235     SetTimer(hWnd, Channel->idEvent, Channel->interval, (TIMERPROC)SoundTimerProc);
00236     Position.x = 150.0;
00237     Position.y = -10.0;
00238     Position.z = -30.0;
00239     UpdateChannel(channel_drip2, &Position, NULL, NULL);
00240 
00241 // bird sound
00242     Sample = new SOUND_SAMPLE;
00243     sprintf(Sample->name, "%s", "bird.wav");
00244     Sample->max = 10;
00245     Sample->volume = 50;
00246     Sample->mindist = 10.0;
00247     Sample->maxdist = 100.0;
00248     Sample->flags = BASS_SAMPLE_OVER_DIST | BASS_SAMPLE_MUTEMAX | BASS_SAMPLE_3D | BASS_SAMPLE_VAM;
00249     LoadSample(Sample);
00250 
00251     CreateChannel(sample_bird);
00252     Channel = ChannelList.Get(channel_bird);
00253     Channel->looped = true;
00254     Channel->intermittent = true;
00255     Channel->random = true;
00256     Channel->lowerrand = 2000;
00257     Channel->upperrand = 25000;
00258     Channel->interval = 5000;
00259     Channel->idEvent = (unsigned int)channel_bird;
00260     SetTimer(hWnd, Channel->idEvent, Channel->interval, (TIMERPROC)SoundTimerProc);
00261     Position.x = 110.0;
00262     Position.y = 0.0;
00263     Position.z = 120.0;
00264     UpdateChannel(channel_bird, &Position, NULL, NULL);
00265 
00266 // car horn sound      (played on a keystroke so we don't set a timer)
00267     Sample = new SOUND_SAMPLE;
00268     sprintf(Sample->name, "%s", "carhorn.wav");
00269     Sample->max = 10;
00270     Sample->volume = 100;
00271     Sample->mindist = 10.0;
00272     Sample->maxdist = 1000.0;
00273     Sample->flags = BASS_SAMPLE_OVER_DIST | BASS_SAMPLE_3D | BASS_SAMPLE_VAM;
00274     LoadSample(Sample);
00275 
00276     CreateChannel(sample_carhorn);
00277 }
00278 
00279 // Portion Copyright (C) Ian Luck
00280 // Simple device selector dialog stuff begins here
00281 BOOL CALLBACK devicedialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
00282 {
00283     switch (m) {
00284         case WM_COMMAND:
00285             switch (LOWORD(w)) {
00286                 case ID_DEVLIST:
00287                     if (HIWORD(w)==LBN_SELCHANGE)
00288                         device=SendMessage((HWND)l,LB_GETCURSEL,0,0);
00289                     else if (HIWORD(w)==LBN_DBLCLK)
00290                         EndDialog(h,0);
00291                     break;
00292                 case ID_LOWQUAL:
00293                     lowqual=SendDlgItemMessage(h,ID_LOWQUAL,BM_GETCHECK,0,0);
00294                     break;
00295                 case IDOK:
00296                     EndDialog(h,0);
00297                     return 1;
00298             }
00299             break;
00300 
00301         case WM_INITDIALOG:
00302             {
00303                 char text[100],*d;
00304                 int c;
00305                 for (c=0;BASS_GetDeviceDescription(c,&d);c++) {
00306                     strcpy(text,d);
00307                     /* Check if the device supports 3D - don't bother with sync/update threads */
00308                     if (!BASS_Init(c,44100,BASS_DEVICE_3D|BASS_DEVICE_NOSYNC|BASS_DEVICE_NOTHREAD,h))
00309                         continue; // no 3D support
00310                     if (BASS_GetEAXParameters(NULL,NULL,NULL,NULL))
00311                         strcat(text," [EAX]"); // it has EAX
00312                     BASS_Free();
00313                     SendDlgItemMessage(h,ID_DEVLIST,LB_ADDSTRING,0,(LONG)text);
00314                 }
00315                 SendDlgItemMessage(h,ID_DEVLIST,LB_SETCURSEL,0,0);
00316             }
00317             device=lowqual=0;
00318             return 1;
00319     }
00320     return 0;
00321 }
00322 // Device selector stuff ends here

Generated on Fri Dec 23 05:21:39 2005 for Sound by doxygen1.2.15