Hopefully update for NaN Makefiles for the moving of SoundSystem.
[blender-staging.git] / intern / SoundSystem / fmod / SND_FmodDevice.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * SND_FmodDevice derived from SND_IAudioDevice
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #ifdef WIN32
39 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
40 #endif //WIN32
41
42 #include "SND_FmodDevice.h"
43 #include "SoundDefines.h"
44 #include "SND_Utils.h"
45
46 SND_FmodDevice::SND_FmodDevice()
47 {
48     /* Removed the functionality for checking if noaudio was provided on */
49     /* the commandline. */
50         m_dspunit = NULL;
51
52         m_audio = true;
53
54         // let's check if we can get fmod to initialize...
55         if (m_audio)
56         {
57                 signed char MinHardwareChannels = FSOUND_SetMinHardwareChannels(NUM_FMOD_MIN_HW_CHANNELS);
58                 signed char MaxHardwareChannels = FSOUND_SetMaxHardwareChannels(NUM_FMOD_MAX_HW_CHANNELS);
59
60                 if (FSOUND_Init(MIXRATE, NUM_SOURCES, 0))
61                 {
62                         m_max_channels = FSOUND_GetMaxChannels();
63                         m_num_hardware_channels = FSOUND_GetNumHardwareChannels();
64                         m_num_software_channels = NUM_SOURCES;
65
66                         // let's get us a wavecache
67                         m_wavecache = new SND_WaveCache();
68                         
69                         int i;
70                         for (i = 0; i < NUM_BUFFERS; i++)
71                                 m_buffers[i] = NULL;
72
73                         for (i = 0; i < NUM_SOURCES; i++)
74                         {
75                                 m_sources[i] = NULL;
76                                 m_frequencies[i] = 0;
77                                 m_channels[i] = 0;
78                         }
79                 }
80                 else
81                 {
82                         m_audio = false;
83                 }
84         }
85         
86 #ifdef ONTKEVER
87         int numdrivers = FSOUND_GetNumDrivers();
88         int output = FSOUND_GetOutput();
89         int oputputrate = FSOUND_GetOutputRate();
90         int mixer = FSOUND_GetMixer();
91
92         printf("maxchannels is: %d\n", m_max_channels);
93         printf("num hw channels is: %d\n", m_num_hardware_channels);
94         printf("num sw channels is: %d\n", m_num_software_channels);
95         printf("numdrivers is: %d\n", numdrivers);
96         printf("output is: %d\n", output);
97         printf("oputputrate is: %d\n", oputputrate);
98         printf("mixer is: %d\n", mixer);
99 #endif
100 }
101
102
103
104 SND_FmodDevice::~SND_FmodDevice()
105 {
106         // let's see if we used the cd. if not, just leave it alone
107         SND_CDObject* pCD = SND_CDObject::Instance();
108         
109         if (pCD)
110         {
111                 this->StopCD();
112                 SND_CDObject::DisposeSystem();
113         }
114
115         StopUsingDSP();
116
117         FSOUND_Close();
118 }
119
120
121
122 void SND_FmodDevice::UseCD() const
123 {
124         // only fmod has CD support, so only create it here
125         SND_CDObject::CreateSystem();
126 }
127
128
129
130 void SND_FmodDevice::MakeCurrent() const
131 {
132         // empty
133 }
134
135
136
137 SND_WaveSlot* SND_FmodDevice::LoadSample(const STR_String& name,
138                                                                                  void* memlocation,
139                                                                                  int size)
140 {
141         SND_WaveSlot* waveslot = NULL;
142         STR_String samplename = name;
143         
144         if (m_audio)
145         {
146                 /* first check if the sample is supported */
147                 if (SND_IsSampleValid(name, memlocation))
148                 {
149                         /* create the waveslot */
150                         waveslot = m_wavecache->GetWaveSlot(samplename);
151                         
152                         if (waveslot)
153                         {
154                                 int buffer = waveslot->GetBuffer();
155                                 
156                                 /* load the sample from memory? */
157                                 if (size && memlocation)
158                                 {
159                                         m_buffers[buffer] = FSOUND_Sample_Load(buffer, (char*)memlocation, FSOUND_LOADMEMORY, size);
160                                         
161                                         /* if the loading succeeded, fill the waveslot with info */
162                                         if (m_buffers[buffer])
163                                         {
164                                                 int sampleformat = SND_GetSampleFormat(memlocation);
165                                                 int numberofchannels = SND_GetNumberOfChannels(memlocation);
166                                                 int samplerate = SND_GetSampleRate(memlocation);
167                                                 int bitrate = SND_GetBitRate(memlocation);
168                                                 int numberofsamples = SND_GetNumberOfSamples(memlocation);
169                                                 
170                                                 waveslot->SetFileSize(size);
171                                                 waveslot->SetData(memlocation);
172                                                 waveslot->SetSampleFormat(sampleformat);
173                                                 waveslot->SetNumberOfChannels(numberofchannels);
174                                                 waveslot->SetSampleRate(samplerate);
175                                                 waveslot->SetBitRate(bitrate);
176                                                 waveslot->SetNumberOfSamples(numberofsamples);
177                                         }
178                                 }
179                                 /* or from file? */
180                                 else
181                                 {
182                                         m_buffers[buffer] = FSOUND_Sample_Load(buffer, samplename.Ptr(), FSOUND_LOOP_NORMAL, NULL);
183                                 }
184                                 
185 #ifdef ONTKEVER
186                                 int error = FSOUND_GetError();
187                                 printf("sample load: errornumber is: %d\n", error);
188 #endif
189                                 
190                                 /* if the loading succeeded, mark the waveslot */
191                                 if (m_buffers[buffer])
192                                 {
193                                         waveslot->SetLoaded(true);
194                                 }
195                                 /* or when it failed, free the waveslot */
196                                 else
197                                 {
198                                         m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer());
199                                         waveslot = NULL;
200                                 }
201                         }
202                 }
203         }
204         
205         return waveslot;
206 }
207
208
209
210
211 // listener's and general stuff //////////////////////////////////////////////////////
212
213
214
215 /* sets the global dopplervelocity */
216 void SND_FmodDevice::SetDopplerVelocity(MT_Scalar dopplervelocity) const
217 {
218         /* not supported by fmod */
219         FSOUND_3D_Listener_SetDopplerFactor(dopplervelocity);
220 }
221
222
223
224 /* sets the global dopplerfactor */
225 void SND_FmodDevice::SetDopplerFactor(MT_Scalar dopplerfactor) const
226 {
227         FSOUND_3D_Listener_SetDopplerFactor(dopplerfactor);
228 }
229
230
231
232 /* sets the global rolloff factor */
233 void SND_FmodDevice::SetListenerRollOffFactor(MT_Scalar rollofffactor) const
234 {
235         // not implemented in openal
236 }
237
238
239
240 void SND_FmodDevice::NextFrame() const
241 {
242         FSOUND_3D_Update();
243 }
244
245
246
247 // set the gain for the listener
248 void SND_FmodDevice::SetListenerGain(float gain) const
249 {
250         int fmod_gain = (int)(gain * 255);
251         FSOUND_SetSFXMasterVolume(fmod_gain);
252 }
253
254
255
256 void SND_FmodDevice::InitListener()
257 {
258         // initialize the listener with these values that won't change
259         // (as long as we can have only one listener)
260         // now we can superimpose all listeners on each other (for they
261         // have the same settings)
262         float lispos[3] = {0,0,0};
263         float lisvel[3] = {0,0,0};
264
265         FSOUND_3D_Listener_SetAttributes(lispos, lisvel, 0, -1, 0, 0, 0, 1);
266 }
267
268
269
270 // source playstate stuff ////////////////////////////////////////////////////////////
271
272
273
274 // check if the sound's still playing
275 int SND_FmodDevice::GetPlayState(int id)
276 {
277         int result = SND_STOPPED;
278
279         // klopt niet, fixen
280         signed char isplaying = FSOUND_IsPlaying(id);
281    
282         if (isplaying)
283         {
284                 result = SND_PLAYING;
285         }
286
287 /* hi reevan, just swap // of these 2 lines */
288 //    return result;
289         return 0;
290 }
291
292
293
294 /* sets the buffer */
295 void SND_FmodDevice::SetObjectBuffer(int id, unsigned int buffer)
296 {
297         m_sources[id] = m_buffers[buffer];
298 }
299
300
301
302 // make the source play
303 void SND_FmodDevice::PlayObject(int id)
304 {
305         m_channels[id] = FSOUND_PlaySound(FSOUND_FREE, m_sources[id]);
306         m_frequencies[id] = FSOUND_GetFrequency(m_channels[id]);
307 //      printf("fmod: play \n");
308 }
309
310
311
312 // make the source stop
313 void SND_FmodDevice::StopObject(int id) const
314 {
315         FSOUND_StopSound(m_channels[id]);
316 //      printf("fmod: stop \n");
317 }
318
319
320
321 // stop all sources
322 void SND_FmodDevice::StopAllObjects()
323 {
324         FSOUND_StopSound(FSOUND_ALL);
325 }
326
327
328
329 // pause the source
330 void SND_FmodDevice::PauseObject(int id) const
331 {
332         FSOUND_StopSound(m_channels[id]);
333 }
334
335
336
337 // source properties stuff ////////////////////////////////////////////////////////////
338
339
340
341 // give openal the object's pitch
342 void SND_FmodDevice::SetObjectPitch(int id, MT_Scalar pitch) const
343 {
344         pitch = pitch * m_frequencies[id];
345         char result = FSOUND_SetFrequency(m_channels[id], (int)pitch);
346 }
347
348
349
350 // give openal the object's gain
351 void SND_FmodDevice::SetObjectGain(int id, MT_Scalar gain) const
352 {
353         int vol = (int)(gain * 255);
354         FSOUND_SetVolume(m_channels[id], vol);
355 }
356
357
358
359 // give openal the object's looping
360 void SND_FmodDevice::SetObjectLoop(int id, unsigned int loopmode) const
361 {
362 //      printf("loopmode: %d\n", loopmode);
363         switch (loopmode)
364         {
365         case SND_LOOP_OFF:
366                 {
367 #ifndef __APPLE__
368                         char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_OFF);
369 #else
370                         char result = FSOUND_SetLoopMode(m_sources[id], FSOUND_LOOP_OFF);
371 #endif
372 //                      char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_OFF);
373                         break;
374                 }
375         case SND_LOOP_NORMAL:
376                 {
377 #ifndef __APPLE__
378                         char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_NORMAL);
379 #else
380                         char result = FSOUND_SetLoopMode(m_sources[id], FSOUND_LOOP_NORMAL);
381 #endif
382 //                      char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_NORMAL);
383                         break;
384                 }
385         case SND_LOOP_BIDIRECTIONAL:
386                 {
387 #ifndef __APPLE__
388                         char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_BIDI);
389 #else
390                         char result = FSOUND_SetLoopMode(m_sources[id], FSOUND_LOOP_BIDI);
391 #endif
392 //                      char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_NORMAL);
393                         break;
394                 }
395         default:
396                 break;
397         }
398 }
399
400
401
402 void SND_FmodDevice::SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const
403 {
404         FSOUND_Sample_SetLoopPoints(m_sources[id], loopstart, loopend);
405 }
406
407
408
409 void SND_FmodDevice::SetObjectMinGain(int id, MT_Scalar mingain) const
410 {
411         /* not supported by fmod */
412 }
413
414
415
416 void SND_FmodDevice::SetObjectMaxGain(int id, MT_Scalar maxgain) const
417 {
418         /* not supported by fmod */
419 }
420
421
422
423 void SND_FmodDevice::SetObjectRollOffFactor(int id, MT_Scalar rollofffactor) const
424 {
425         /* not supported by fmod */
426 }
427
428
429
430 void SND_FmodDevice::SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const
431 {
432         /* not supported by fmod */
433 }
434
435
436
437 // give openal the object's position
438 void SND_FmodDevice::ObjectIs2D(int id) const
439 {
440         float obpos[3] = {0,0,0};
441         float obvel[3] = {0,0,0};
442         
443         FSOUND_3D_SetAttributes(m_channels[id], obpos, obvel);
444 }
445
446
447
448 void SND_FmodDevice::SetObjectTransform(int id,
449                                                                                   const MT_Vector3& position,
450                                                                                   const MT_Vector3& velocity,
451                                                                                   const MT_Matrix3x3& orientation,
452                                                                                   const MT_Vector3& lisposition,
453                                                                                   const MT_Scalar& rollofffactor) const 
454 {
455         float obpos[3];
456         float obvel[3];
457
458         obpos[0] = (float)position[0] * (float)rollofffactor;   //x (l/r)
459         obpos[1] = (float)position[1] * (float)rollofffactor;
460         obpos[2] = (float)position[2] * (float)rollofffactor;
461
462         velocity.getValue(obvel);
463         FSOUND_3D_SetAttributes(m_channels[id], obpos, obvel);
464 }
465
466
467
468 // cd support stuff ////////////////////////////////////////////////////////////
469
470
471 void SND_FmodDevice::PlayCD(int track) const
472 {
473 #ifndef __APPLE__
474         signed char result = FSOUND_CD_Play(track);
475 #else
476         signed char result = FSOUND_CD_Play(0, track);
477 #endif
478
479 #ifdef ONTKEVER
480         printf("SND_FmodDevice::PlayCD(): track=%d, result=%d\n", track, (int)result);
481 #endif
482 }
483
484
485
486 void SND_FmodDevice::PauseCD(bool pause) const
487 {
488 #ifndef __APPLE__
489         signed char result = FSOUND_CD_SetPaused(pause);
490 #else
491         signed char result = FSOUND_CD_SetPaused(0, pause);
492 #endif
493
494 #ifdef ONTKEVER
495         printf("SND_FmodDevice::PauseCD(): pause=%d, result=%d\n", pause, (int)result);
496 #endif
497 }
498
499
500
501 void SND_FmodDevice::StopCD() const
502 {
503         SND_CDObject* pCD = SND_CDObject::Instance();
504
505         if (pCD)
506         {
507                 if (pCD->GetUsed())
508                 {
509 #ifndef __APPLE__
510                         signed char result = FSOUND_CD_Stop();
511 #else
512                         signed char result = FSOUND_CD_Stop(0);
513 #endif
514
515 #ifdef ONTKEVER
516                         printf("SND_FmodDevice::StopCD(): result=%d\n", (int)result);
517 #endif
518                 }
519         }
520 }
521
522
523
524 void SND_FmodDevice::SetCDPlaymode(int playmode) const
525 {
526 #ifndef __APPLE__
527         FSOUND_CD_SetPlayMode(playmode);
528 #else
529         FSOUND_CD_SetPlayMode(0, playmode);
530 #endif
531
532 #ifdef ONTKEVER
533         printf("SND_FmodDevice::SetCDPlaymode(): playmode=%d,\n", playmode);
534 #endif
535 }
536
537
538
539 void SND_FmodDevice::SetCDGain(MT_Scalar gain) const
540 {
541         int volume = gain * 255;
542 #ifndef __APPLE__
543         signed char result = FSOUND_CD_SetVolume(volume);
544 #else
545         signed char result = FSOUND_CD_SetVolume(0, volume);
546 #endif
547
548 #ifdef ONTKEVER
549         printf("SND_FmodDevice::SetCDGain(): gain=%f, volume=%d, result=%d\n", gain, volume, (int)result);
550 #endif
551 }
552
553
554
555 void SND_FmodDevice::StartUsingDSP()
556 {
557         m_dspunit = FSOUND_DSP_GetFFTUnit();
558
559         FSOUND_DSP_SetActive(m_dspunit, true);
560 }
561
562
563
564 float* SND_FmodDevice::GetSpectrum()
565 {
566         m_spectrum = FSOUND_DSP_GetSpectrum();
567
568         return m_spectrum;
569 }
570
571
572
573 void SND_FmodDevice::StopUsingDSP()
574 {
575         if (m_dspunit)
576                 FSOUND_DSP_SetActive(m_dspunit, false);
577 }