]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/rsx_lib.cpp
Initial revision
[taylor/freespace2.git] / src / sound / rsx_lib.cpp
1 /*
2  * $Logfile: /Freespace2/code/Sound/rsx_lib.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C module for RSX sound lib
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:10  root
11  * Initial revision
12  *
13  * 
14  * 2     10/07/98 10:54a Dave
15  * Initial checkin.
16  * 
17  * 1     10/07/98 10:51a Dave
18  * 
19  * 3     10/14/97 11:33p Lawrance
20  * get RSX implemented
21  * 
22  * 1     10/14/97 12:58p Lawrance
23  * 
24  * 1     10/14/97 10:35a Lawrance
25  *
26  * $NoKeywords: $
27  */
28
29 #define INITGUID
30 #include "pstypes.h"
31 #include <windows.h>
32 #include <rsx.h>
33 #include "rsx_lib.h"
34 #include "sound.h"
35 #include "osapi.h"
36
37 // gloabl variable to keep track of initalized status for RSX
38 int rsx_initialized = 0;
39
40 ////////////////////////////////////////////
41 // Global RSX data
42 ////////////////////////////////////////////
43 IUnknown                                        *lpRSXUnk;
44 //IRSX2                                         *lpRSX;
45 IRSX                                            *lpRSX;
46 IRSXDirectListener      *lpDL;
47
48 RSXENVIRONMENT                  rsxEnv;
49
50 IRSXCachedEmitter               *lpCE[MAX_SOUNDS];
51
52 // initialize the listener.  Return -1 if failed to init listener, otherwise return 0
53 int rsx_init_listener()
54 {
55 //      HRESULT hr;
56
57         // Create a listener and save the IRSXDirectListener interface
58         RSXDIRECTLISTENERDESC rsxDL;            // listener description
59
60         rsxDL.cbSize = sizeof(RSXDIRECTLISTENERDESC);
61 //      rsxDL.hMainWnd = NULL;
62         rsxDL.hMainWnd = (HWND)os_get_window();
63         rsxDL.dwUser = 0;
64         rsxDL.lpwf = NULL;
65
66 /*
67         hr = CoCreateInstance(CLSID_RSXDIRECTLISTENER, NULL, CLSCTX_INPROC_SERVER, IID_IRSXDirectListener, (void **) &lpDL);
68         if ( SUCCEEDED(hr) ) {
69                 hr = lpDL->Initialize(&rsxDL, lpRSXUnk);
70                 if ( SUCCEEDED(hr) )
71                         return 0;
72                 else {
73                         Warning(LOCATION,"Unable to create the RSX listener\n");
74                         return -1;
75                 }
76         } else {
77                 Warning(LOCATION,"Unable to create the RSX listener\n");
78                 return -1;
79         }
80 */
81
82         if( SUCCEEDED(lpRSX->CreateDirectListener(&rsxDL, &lpDL, NULL)) ) {
83                 return 0;
84         } else {
85                 return -1;
86         }
87 }
88
89 // initialize the environment.  lpRSX must be non-null.  Return -1 if there is
90 // an error, otherwise return 0
91 int rsx_init_environment()
92 {
93         Assert(lpRSX != NULL);
94
95         rsxEnv.cbSize = sizeof(RSXENVIRONMENT);
96         rsxEnv.dwFlags = RSXENVIRONMENT_SPEEDOFSOUND;
97         rsxEnv.fSpeedOfSound = 200.0f;
98         if ( lpRSX->SetEnvironment(&rsxEnv) == S_OK )
99                 return 0;
100         else
101                 return -1;
102 }
103
104 // init the RSX sound system.  Return -1 if a failure occurs, otherwise return 0
105 int rsx_init()
106 {
107         HRESULT hr;
108         int             i;
109
110         if ( rsx_initialized )
111                 return 0;
112
113         // Initialize COM Library
114         hr  = CoInitialize(NULL);
115
116         // Specify the class Id for RSX and the interface ID for the IRSX2 interface (use IID_IRSX20 if using IRSX)
117         hr = CoCreateInstance(CLSID_RSX20, NULL, CLSCTX_INPROC_SERVER, IID_IRSX20, (void **) &lpRSX);
118         if ( !SUCCEEDED(hr) ) {
119                 Warning(LOCATION,"Unable to create the RSX interface\n");
120                 return -1;
121         }
122 /*
123 //      hr = CoCreateInstance(CLSID_RSX20, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **) &lpRSXUnk);
124         // Query the object for an IUnknown interface
125    hr = lpRSX->QueryInterface(IID_IUnknown, (void**)&lpRSXUnk);
126         if ( !SUCCEEDED(hr) ) {
127                 Warning(LOCATION,"Unable to create the RSX Unknown interface\n");
128                 return -1;
129         }
130 */
131
132         if ( rsx_init_environment() == -1 ) {
133                 Warning(LOCATION,"Unable to initialize the RSX environment\n");
134                 return -1;
135         }
136
137         if ( rsx_init_listener() == -1 ) {
138                 Warning(LOCATION,"Unable to initialize the RSX direct listener\n");
139                 return -1;
140         }
141
142         for ( i = 0; i < MAX_SOUNDS; i++ ) {
143                 if ( lpCE[i] != NULL ) {
144                         lpCE[i]->Release();
145                         lpCE[i] = NULL;
146                 }
147         }
148         
149         rsx_initialized = 1;
150         return 0;
151 }
152
153 // called once per frame to update the listener position and orientation
154 void rsx_update_listener(vector *pos, matrix *orient)
155 {
156         HRESULT hr;
157         RSXVECTOR3D u, v;
158
159         if ( !rsx_initialized )
160                 return;
161
162         u.x = pos->x;
163         u.y = pos->y;
164         u.z = pos->z;
165         hr = lpDL->SetPosition(&u);
166         if (hr != S_OK)
167                 Warning(LOCATION,"Unable to set position for the RSX listener\n");
168                 
169         u.x = orient->fvec.x;
170         u.y = orient->fvec.y;
171         u.z = orient->fvec.z;
172
173         v.x = orient->uvec.x;
174         v.y = orient->uvec.y;
175         v.z = orient->uvec.z;
176         
177         hr = lpDL->SetOrientation(&u, &v);
178         if (hr != S_OK)
179                 Warning(LOCATION,"Unable to set orientation for the RSX listener\n");
180 }
181
182 // uninitialize the RSX sound system
183 void rsx_close()
184 {
185         int i;
186
187         for(i = 0; i < MAX_SOUNDS; i++){
188                 if ( lpCE[i] != NULL) {
189                         lpCE[i]->Release();
190                         lpCE[i] = NULL;
191                 }
192         }
193
194         // TODO: release the channels
195     
196         // Release the listener
197         if ( lpDL ) {
198                 lpDL->Release();
199                 lpDL = NULL;
200         }
201
202         // Release RSX
203         if( lpRSX ) {
204                 lpRSX->Release();
205       lpRSX = NULL;
206         }
207
208         CoUninitialize();
209 }
210
211 // return index into lpCE[] array, this is the Sounds[].sid member used to link the game-level
212 // description of the sound to the low-level cached emitter
213 int rsx_create_cached_emitter(char *filename, int is_3d, int use_doppler, int min, int max, float max_volume)
214 {
215         RSXCACHEDEMITTERDESC    rsxCE;  
216         RSXEMITTERMODEL         rsxModel;
217         int                                             ce_index;
218 //      HRESULT                                 hr;
219
220         ZeroMemory(&rsxCE, sizeof(RSXCACHEDEMITTERDESC));
221         rsxCE.cbSize = sizeof(RSXCACHEDEMITTERDESC);
222         strcpy(rsxCE.szFilename, filename);
223
224         ZeroMemory(&rsxModel, sizeof(RSXEMITTERMODEL));
225         rsxModel.cbSize = sizeof(RSXEMITTERMODEL);
226
227         for ( ce_index = 0; ce_index < MAX_SOUNDS; ce_index++ ) {
228                 if ( lpCE[ce_index] == NULL )
229                         break;
230         }
231
232         if ( ce_index == MAX_SOUNDS ) {
233                 Warning(LOCATION, "RSX has exceeded the maximum number of sounds\n");
234                 return -1;
235         } 
236
237         if ( is_3d ) {
238                 rsxCE.dwFlags |= RSXEMITTERDESC_NOREVERB;       // no reverb by default
239                 if ( !use_doppler )
240                         rsxCE.dwFlags |= RSXEMITTERDESC_NODOPPLER;
241
242                 rsxModel.fIntensity     = max_volume;           
243 //              rsxModel.fIntensity     = 1.0f;         
244                 rsxModel.fMinBack               = i2fl(min);
245                 rsxModel.fMinFront      = i2fl(min);
246                 rsxModel.fMaxBack               = i2fl(max);
247                 rsxModel.fMaxFront      = i2fl(max);
248         } else {
249                 rsxCE.dwFlags = RSXEMITTERDESC_NOSPATIALIZE | RSXEMITTERDESC_NOATTENUATE | RSXEMITTERDESC_NODOPPLER | RSXEMITTERDESC_NOREVERB;
250                 rsxModel.fIntensity     = max_volume;           
251         }
252
253 /*
254         hr = CoCreateInstance(CLSID_RSXCACHEDEMITTER, NULL, CLSCTX_INPROC_SERVER, IID_IRSXCachedEmitter, (void **) &lpCE[ce_index]);
255         if ( FAILED(hr) ) {
256                 Warning(LOCATION, "Creating an RSX cached emitter failed\n");
257                 return -1;
258         }
259
260         hr = lpCE[ce_index]->Initialize(&rsxCE, lpRSXUnk);
261         if ( FAILED(hr) ) {
262                 Warning(LOCATION, "Initialization of an RSX cached emitter failed\n");
263                 return -1;
264         }
265 */
266
267         if( !SUCCEEDED(lpRSX->CreateCachedEmitter(&rsxCE, &lpCE[ce_index], NULL)) ) {
268                 Warning(LOCATION, "Could not create a RSX cached emitter\n");
269                 return -1;
270         }
271         
272         lpCE[ce_index]->SetModel(&rsxModel);
273         return ce_index;
274 }
275
276 int rsx_play_3d(int sid, float priority, float volume, vector *pos, vector *sound_fvec)
277 {
278         RSXQUERYMEDIAINFO qmi;
279         qmi.cbSize = sizeof(RSXQUERYMEDIAINFO);
280         lpCE[sid]->QueryMediaState(&qmi);
281
282    if ( qmi.dwControl == RSX_PLAY )
283                 return -1;
284
285         lpCE[sid]->SetPosition((RSXVECTOR3D*)pos);
286 //      lpCE[sid]->SetOrientation((RSXVECTOR3D*)sound_fvec);
287         lpCE[sid]->ControlMedia(RSX_PLAY, 1, 0.0f);
288         return 1;
289 }
290
291 int rsx_play( int sid, float priority, float volume)
292 {
293         RSXQUERYMEDIAINFO qmi;
294         HRESULT                         hr;
295
296         qmi.cbSize = sizeof(RSXQUERYMEDIAINFO);
297         lpCE[sid]->QueryMediaState(&qmi);
298
299    if ( qmi.dwControl == RSX_PLAY )
300                 return -1;
301
302         hr = lpCE[sid]->ControlMedia(RSX_PLAY, 1, 0.0f);
303         if ( hr != S_OK ) {
304                 Warning(LOCATION, "rsx_play() failure\n");
305                 return -1;
306         }
307         return 1;
308 }
309
310
311 void rsx_unload_buffer(int sid)
312 {
313         if ( sid != -1 ) {
314                 if ( lpCE[sid] != NULL ) {
315                         lpCE[sid]->Release();
316                         lpCE[sid] = NULL;
317                 }
318         }
319 }