df02d11ae391b8386b00d14026d9747a37f5b2e9
[blender.git] / intern / SoundSystem / openal / SND_OpenALDevice.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * SND_OpenALDevice derived from SND_IAudioDevice
29  */
30
31 #ifdef WIN32
32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
33 #endif //WIN32
34
35 #include "SND_OpenALDevice.h"
36 #ifndef __APPLE__
37 #include "SND_SDLCDDevice.h"
38 #endif
39 #include "SoundDefines.h"
40
41 #include "SND_Utils.h"
42
43 #ifdef APPLE_FRAMEWORK_FIX
44 #include <al.h>
45 #include <alc.h>
46 #else
47 #include <AL/al.h>
48 #include <AL/alc.h>
49 #endif
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #if defined(WIN32)
54 #include <io.h>
55 #else
56 #include <unistd.h>
57 #endif
58 #include <fcntl.h>
59
60 #include <signal.h>
61
62 /*************************** ALUT replacement *****************************/
63
64 /* instead of relying on alut, we just implement our own
65  * WAV loading functions, hopefully more reliable */
66
67 #include <stdlib.h>
68
69 typedef struct                                  /* WAV File-header */
70 {
71   ALubyte  Id[4];
72   ALsizei  Size;
73   ALubyte  Type[4];
74 } WAVFileHdr_Struct;
75
76 typedef struct                                  /* WAV Fmt-header */
77 {
78   ALushort Format;                              
79   ALushort Channels;
80   ALuint   SamplesPerSec;
81   ALuint   BytesPerSec;
82   ALushort BlockAlign;
83   ALushort BitsPerSample;
84 } WAVFmtHdr_Struct;
85
86 typedef struct                                                                  /* WAV FmtEx-header */
87 {
88   ALushort Size;
89   ALushort SamplesPerBlock;
90 } WAVFmtExHdr_Struct;
91
92 typedef struct                                  /* WAV Smpl-header */
93 {
94   ALuint   Manufacturer;
95   ALuint   Product;
96   ALuint   SamplePeriod;                          
97   ALuint   Note;                                  
98   ALuint   FineTune;                              
99   ALuint   SMPTEFormat;
100   ALuint   SMPTEOffest;
101   ALuint   Loops;
102   ALuint   SamplerData;
103   struct
104   {
105     ALuint Identifier;
106     ALuint Type;
107     ALuint Start;
108     ALuint End;
109     ALuint Fraction;
110     ALuint Count;
111   }      Loop[1];
112 } WAVSmplHdr_Struct;
113
114 typedef struct                                  /* WAV Chunk-header */
115 {
116   ALubyte  Id[4];
117   ALuint   Size;
118 } WAVChunkHdr_Struct;
119
120 static void *SND_loadFileIntoMemory(const char *filename, int *len_r)
121 {
122         FILE *fp= fopen(filename, "rb");
123         void *data;
124
125         if (!fp) {
126                 *len_r= -1;
127                 return NULL;
128         }
129
130         fseek(fp, 0L, SEEK_END);
131         *len_r= ftell(fp);
132         fseek(fp, 0L, SEEK_SET);
133
134         data= malloc(*len_r);
135         if (!data) {
136                 *len_r= -1;
137                 return NULL;
138         }
139
140         if (fread(data, *len_r, 1, fp)!=1) {
141                 *len_r= -1;
142                 free(data);
143                 return NULL;
144         }
145
146         return data;
147 }
148
149 #define TEST_SWITCH_INT(a) if(big_endian) { \
150     char s_i, *p_i; \
151     p_i= (char *)&(a); \
152     s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
153     s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
154
155 #define TEST_SWITCH_SHORT(a) if(big_endian) { \
156     char s_i, *p_i; \
157     p_i= (char *)&(a); \
158     s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
159
160 static int stream_read(void *out, ALbyte **stream, ALsizei size, ALsizei *memsize)
161 {
162         if(size <= *memsize) {
163                 memcpy(out, *stream, size);
164                 return 1;
165         }
166         else {
167                 memset(out, 0, size);
168                 return 0;
169         }
170 }
171
172 static int stream_skip(ALbyte **stream, ALsizei size, ALsizei *memsize)
173 {
174         if(size <= *memsize) {
175                 *stream += size;
176                 *memsize -= size;
177                 return 1;
178         }
179         else
180                 return 0;
181 }
182
183 ALvoid SND_alutLoadWAVMemory(ALbyte *memory,ALsizei memsize,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop)
184 {
185         WAVChunkHdr_Struct ChunkHdr;
186         WAVFmtExHdr_Struct FmtExHdr;
187         WAVFileHdr_Struct FileHdr;
188         WAVSmplHdr_Struct SmplHdr;
189         WAVFmtHdr_Struct FmtHdr;
190         ALbyte *Stream= memory;
191         int test_endian= 1;
192         int big_endian= !((char*)&test_endian)[0];
193         
194         *format=AL_FORMAT_MONO16;
195         *data=NULL;
196         *size=0;
197         *freq=22050;
198         *loop=AL_FALSE;
199
200         if(!Stream)
201                 return;
202  
203         stream_read(&FileHdr,&Stream,sizeof(WAVFileHdr_Struct),&memsize);
204         stream_skip(&Stream,sizeof(WAVFileHdr_Struct),&memsize);
205
206         TEST_SWITCH_INT(FileHdr.Size);
207         FileHdr.Size=((FileHdr.Size+1)&~1)-4;
208
209         while((FileHdr.Size!=0) && stream_read(&ChunkHdr,&Stream,sizeof(WAVChunkHdr_Struct),&memsize))
210         {
211                 TEST_SWITCH_INT(ChunkHdr.Size);
212                 stream_skip(&Stream,sizeof(WAVChunkHdr_Struct),&memsize);
213
214                 if (!memcmp(ChunkHdr.Id,"fmt ",4))
215                 {
216                         stream_read(&FmtHdr,&Stream,sizeof(WAVFmtHdr_Struct),&memsize);
217
218                         TEST_SWITCH_SHORT(FmtHdr.Format);
219                         TEST_SWITCH_SHORT(FmtHdr.Channels);
220                         TEST_SWITCH_INT(FmtHdr.SamplesPerSec);
221                         TEST_SWITCH_INT(FmtHdr.BytesPerSec);
222                         TEST_SWITCH_SHORT(FmtHdr.BlockAlign);
223                         TEST_SWITCH_SHORT(FmtHdr.BitsPerSample);
224
225                         if (FmtHdr.Format==0x0001)
226                         {
227                                 *format=(FmtHdr.Channels==1?
228                                                 (FmtHdr.BitsPerSample==8?AL_FORMAT_MONO8:AL_FORMAT_MONO16):
229                                                 (FmtHdr.BitsPerSample==8?AL_FORMAT_STEREO8:AL_FORMAT_STEREO16));
230                                 *freq=FmtHdr.SamplesPerSec;
231                         } 
232                         else
233                         {
234                                 stream_read(&FmtExHdr,&Stream,sizeof(WAVFmtExHdr_Struct),&memsize);
235                                 TEST_SWITCH_SHORT(FmtExHdr.Size);
236                                 TEST_SWITCH_SHORT(FmtExHdr.SamplesPerBlock);
237                         }
238                 }
239                 else if (!memcmp(ChunkHdr.Id,"data",4))
240                 {
241                         if (FmtHdr.Format==0x0001)
242                         {
243                                 if((ALsizei)ChunkHdr.Size <= memsize)
244                                 {
245                                         *size=ChunkHdr.Size;
246                                         *data=malloc(ChunkHdr.Size+31);
247
248                                         if (*data) {
249                                                 stream_read(*data,&Stream,ChunkHdr.Size,&memsize);
250                                                 memset(((char *)*data)+ChunkHdr.Size,0,31);
251
252                                                 if(FmtHdr.BitsPerSample == 16 && big_endian) {
253                                                         int a, len= *size/2;
254                                                         short *samples= (short*)*data;
255
256                                                         for(a=0; a<len; a++) {
257                                                                 TEST_SWITCH_SHORT(samples[a])
258                                                         }
259                                                 }
260                                         }
261                                 }
262                         }
263                         else if (FmtHdr.Format==0x0011)
264                         {
265                                 //IMA ADPCM
266                         }
267                         else if (FmtHdr.Format==0x0055)
268                         {
269                                 //MP3 WAVE
270                         }
271                 }
272                 else if (!memcmp(ChunkHdr.Id,"smpl",4))
273                 {
274                         stream_read(&SmplHdr,&Stream,sizeof(WAVSmplHdr_Struct),&memsize);
275
276                         TEST_SWITCH_INT(SmplHdr.Manufacturer);
277                         TEST_SWITCH_INT(SmplHdr.Product);
278                         TEST_SWITCH_INT(SmplHdr.SamplePeriod);
279                         TEST_SWITCH_INT(SmplHdr.Note);
280                         TEST_SWITCH_INT(SmplHdr.FineTune);
281                         TEST_SWITCH_INT(SmplHdr.SMPTEFormat);
282                         TEST_SWITCH_INT(SmplHdr.SMPTEOffest);
283                         TEST_SWITCH_INT(SmplHdr.Loops);
284                         TEST_SWITCH_INT(SmplHdr.SamplerData);
285
286                         *loop = (SmplHdr.Loops ? AL_TRUE : AL_FALSE);
287                 }
288
289                 if(!stream_skip(&Stream, ChunkHdr.Size + (ChunkHdr.Size&1), &memsize))
290                         break;
291
292                 FileHdr.Size-=(((ChunkHdr.Size+1)&~1)+8);
293         }
294 }
295
296 ALvoid SND_alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq)
297 {
298         if (data)
299                 free(data);
300 }
301
302 /************************ Device Implementation ****************************/
303
304 SND_OpenALDevice::SND_OpenALDevice()
305         : SND_AudioDevice(),
306           m_context(NULL),
307           m_device(NULL)
308 {
309     /* Removed the functionality for checking if noaudio was provided on */
310     /* the commandline. */
311         m_audio = true;
312         m_context = NULL;
313         m_buffersinitialized = false;
314         m_sourcesinitialized = false;
315
316         // let's check if we can get openal to initialize...
317         if (m_audio)
318         {
319                 m_audio = false;
320
321                 ALCdevice *dev = alcOpenDevice(NULL);
322                 if (dev) {
323                         m_context = alcCreateContext(dev, NULL);
324
325                         if (m_context) {
326 #ifdef AL_VERSION_1_1
327                         alcMakeContextCurrent((ALCcontext*)m_context);
328 #else
329                         alcMakeContextCurrent(m_context);
330 #endif
331                         m_audio = true;
332                                 m_device = dev;
333 #ifdef __linux__
334                                 /*
335                                 *   SIGHUP Hack:
336                                 *
337                                 *   On Linux, alcDestroyContext generates a SIGHUP (Hangup) when killing the OpenAL
338                                 *   mixer thread, which kills Blender.
339                                 *  
340                                 *   So we set the signal to ignore....
341                                 *
342                                 *   TODO: check if this applies to other platforms.
343                                 *
344                                 */
345                                 signal(SIGHUP, SIG_IGN);
346 #endif
347                         }
348                 }
349
350         }
351
352         // then try to generate some buffers
353         if (m_audio)
354         {
355                 // let openal generate its buffers
356                 alGenBuffers(NUM_BUFFERS, m_buffers);
357                 m_buffersinitialized = true;
358                 
359                 for (int i = 0; i < NUM_BUFFERS; i++)
360                 {
361                         if (!alIsBuffer(m_buffers[i]))
362                         {
363                                 //printf("\n\n  WARNING: OpenAL returned with an error. Continuing without audio.\n\n");
364                                 m_audio = false;
365                                 break;
366                         }
367                 }
368         }
369
370         // next: the sources
371         if (m_audio)
372         {
373 #ifdef __APPLE__
374                 ALenum alc_error = ALC_NO_ERROR;        // openal_2.12
375 #elif defined(_WIN32)
376                 // alcGetError has no arguments on windows
377                 ALenum alc_error = alcGetError();       // openal_2.14+
378 #else
379                 ALenum alc_error = alcGetError(NULL);   // openal_2.14+
380 #endif
381
382                 // let openal generate its sources
383                 if (alc_error == ALC_NO_ERROR)
384                 {
385                         int i;
386
387                         for (i=0;i<NUM_SOURCES;i++)
388                                 m_sources[i] = 0;
389                         alGenSources(NUM_SOURCES, m_sources);
390                         m_sourcesinitialized = true;
391                 }
392         }
393
394         // let's get us a wavecache
395         if (m_audio)
396         {
397                 m_wavecache = new SND_WaveCache();
398         }
399 #ifndef __APPLE__       
400         m_cdrom = new SND_SDLCDDevice();
401 #endif
402 }
403
404 void SND_OpenALDevice::UseCD(void) const
405 {
406         // we use SDL for CD, so we create the system
407         SND_CDObject::CreateSystem();
408
409 }
410
411 void SND_OpenALDevice::MakeCurrent() const
412 {
413 #ifdef WIN32
414         alcMakeContextCurrent(m_context);
415 #endif
416 }
417
418
419
420 SND_OpenALDevice::~SND_OpenALDevice()
421 {
422         MakeCurrent();
423         
424         if (m_sourcesinitialized)
425         {
426                 for (int i = 0; i < NUM_SOURCES; i++)
427                         alSourceStop(m_sources[i]);
428                 
429                 alDeleteSources(NUM_SOURCES, m_sources);
430                 m_sourcesinitialized = false;
431         }
432         
433         if (m_buffersinitialized)
434         {
435                 alDeleteBuffers(NUM_BUFFERS, m_buffers);
436                 m_buffersinitialized = false;
437         }
438         
439         if (m_context) {
440                 MakeCurrent();
441 #ifdef AL_VERSION_1_1
442                 alcDestroyContext((ALCcontext*)m_context);
443 #else
444                 alcDestroyContext(m_context);
445 #endif
446                 m_context = NULL;
447         }
448         
449 #ifdef __linux__
450         // restore the signal state above.
451         signal(SIGHUP, SIG_DFL);
452 #endif  
453         // let's see if we used the cd. if not, just leave it alone
454         SND_CDObject* pCD = SND_CDObject::Instance();
455         
456         if (pCD)
457         {
458                 this->StopCD();
459                 SND_CDObject::DisposeSystem();
460         }
461 #ifndef __APPLE__
462         if (m_cdrom)
463                 delete m_cdrom;
464 #endif
465         if (m_device)
466                 alcCloseDevice((ALCdevice*) m_device);
467 }
468
469
470 SND_WaveSlot* SND_OpenALDevice::LoadSample(const STR_String& name,
471                                                                                   void* memlocation,
472                                                                                   int size)
473 {
474         SND_WaveSlot* waveslot = NULL;
475         STR_String samplename = name;
476         
477         if (m_audio)
478         {
479                 /* create the waveslot */
480                 waveslot = m_wavecache->GetWaveSlot(samplename);
481
482                 /* do we support this sample? */
483                 if (SND_IsSampleValid(name, memlocation))
484                 {
485                         if (waveslot)
486                         {
487                                 bool freemem = false;
488                                 int buffer = waveslot->GetBuffer();
489                                 void* data = NULL;
490                                 char loop = 'a';
491                                 int sampleformat, bitrate, numberofchannels;
492                                 ALenum al_error = alGetError();
493                                 ALsizei samplerate, numberofsamples;  // openal_2.14+
494                                 
495                                 /* Give them some safe defaults just incase */
496                                 bitrate = numberofchannels = 0;
497
498                                 if (!(size && memlocation)) {
499                                         memlocation = SND_loadFileIntoMemory(samplename.Ptr(), &size);
500                                         freemem = true;
501                                 }
502
503                                 /* load the sample from memory? */
504                                 if (size && memlocation)
505                                 {
506                                         waveslot->SetFileSize(size);
507                                         
508                                         /* what was (our) buffer? */
509                                         int buffer = waveslot->GetBuffer();
510                                         
511                                         /* get some info out of the sample */
512                                         SND_GetSampleInfo((signed char*)memlocation, waveslot);
513                                         numberofchannels = SND_GetNumberOfChannels(memlocation);
514                                         bitrate = SND_GetBitRate(memlocation);
515                                         
516                                         /* load the sample into openal */
517                                         SND_alutLoadWAVMemory((char*)memlocation, size, &sampleformat, &data, &numberofsamples, &samplerate, &loop);
518                                         /* put it in the buffer */
519                                         alBufferData(m_buffers[buffer], sampleformat, data, numberofsamples, samplerate);
520                                 }
521                                 
522                                 if(freemem)
523                                                 free(memlocation);
524                                                                 
525                                 /* fill the waveslot with info */
526                                 al_error = alGetError();
527                                 if (al_error == AL_NO_ERROR && m_buffers[buffer])
528                                 {
529                                         waveslot->SetData(data);
530                                         waveslot->SetSampleFormat(sampleformat);
531                                         waveslot->SetNumberOfChannels(numberofchannels);
532                                         waveslot->SetSampleRate(samplerate);
533                                         waveslot->SetBitRate(bitrate);
534                                         waveslot->SetNumberOfSamples(numberofsamples);
535                                         
536                                         /* if the loading succeeded, mark the waveslot */
537                                         waveslot->SetLoaded(true);
538                                 }
539                                 else
540                                 {
541                                         /* or when it failed, free the waveslot */
542                                         m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer());
543                                         waveslot = NULL;
544                                 }
545                                 
546                                 /* and free the original stuff (copy was made in openal) */
547                                 SND_alutUnloadWAV(sampleformat, data, numberofsamples, samplerate);
548                         }
549                 }
550                 else
551                 {
552                         /* sample not supported, remove waveslot */
553                         m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer());
554                         waveslot = NULL;
555                 }
556         }
557         return waveslot;
558 }
559
560
561
562 // listener's and general stuff //////////////////////////////////////////////////////
563
564
565
566 /* sets the global dopplervelocity */
567 void SND_OpenALDevice::SetDopplerVelocity(MT_Scalar dopplervelocity) const
568 {
569         alDopplerVelocity ((float)dopplervelocity);
570 }
571
572
573
574 /* sets the global dopplerfactor */
575 void SND_OpenALDevice::SetDopplerFactor(MT_Scalar dopplerfactor) const
576 {
577         alDopplerFactor ((float)dopplerfactor);
578 }
579
580
581
582 /* sets the global rolloff factor */
583 void SND_OpenALDevice::SetListenerRollOffFactor(MT_Scalar rollofffactor) const
584 {
585         // not implemented in openal
586 }
587
588
589
590 void SND_OpenALDevice::NextFrame() const
591 {
592         // CD
593 #ifndef __APPLE__
594         m_cdrom->NextFrame();
595 #endif
596         // not needed by openal
597 }
598
599
600
601 // set the gain for the listener
602 void SND_OpenALDevice::SetListenerGain(float gain) const
603 {
604         alListenerf (AL_GAIN, gain);
605 }
606
607
608
609 void SND_OpenALDevice::InitListener()
610 {
611         // initialize the listener with these values that won't change
612         // (as long as we can have only one listener)
613         // now we can superimpose all listeners on each other (for they
614         // have the same settings)
615         float lispos[3] = {0,0,0};
616         float lisvel[3] = {0,0,0};
617 #ifdef WIN32
618         float lisori[6] = {0,1,0,0,0,1};
619 #else
620         float lisori[6] = {0,0,1,0,-1,0};
621 #endif
622
623         alListenerfv(AL_POSITION, lispos);
624         alListenerfv(AL_VELOCITY, lisvel);
625         alListenerfv(AL_ORIENTATION, lisori);
626 }
627
628
629
630 // source playstate stuff ////////////////////////////////////////////////////////////
631
632
633
634 /* sets the buffer */
635 void SND_OpenALDevice::SetObjectBuffer(int id, unsigned int buffer)
636 {
637         alSourcei (m_sources[id], AL_BUFFER, m_buffers[buffer]);
638 }
639
640
641
642 // check if the sound's still playing
643 int SND_OpenALDevice::GetPlayState(int id)
644 {
645     int alstate = 0;
646         int result = 0;
647
648         alGetSourcei(m_sources[id], AL_SOURCE_STATE, &alstate);
649         
650         switch(alstate)
651         {
652         case AL_INITIAL:
653                 {
654                         result = SND_INITIAL;
655                         break;
656                 }
657         case AL_PLAYING:
658                 {
659                         result = SND_PLAYING;
660                         break;
661                 }
662         case AL_PAUSED:
663                 {
664                         result = SND_PAUSED;
665                         break;
666                 }
667         case AL_STOPPED:
668                 {
669                         result = SND_STOPPED;
670                         break;
671                 }
672         default:
673                 result = SND_UNKNOWN;
674         }
675
676     return result;
677 }
678
679
680
681 // make the source play
682 void SND_OpenALDevice::PlayObject(int id)
683 {
684         alSourcePlay(m_sources[id]);
685 }
686
687
688
689 // make the source stop
690 void SND_OpenALDevice::StopObject(int id) const
691 {
692         float obpos[3] = {0,0,0};
693         float obvel[3] = {0,0,0};
694
695         alSourcefv(m_sources[id], AL_POSITION, obpos);
696         alSourcefv(m_sources[id], AL_VELOCITY, obvel);
697
698         alSourcef(m_sources[id], AL_GAIN, 1.0);
699         alSourcef(m_sources[id], AL_PITCH, 1.0);
700         alSourcei(m_sources[id], AL_LOOPING, AL_FALSE);
701         alSourceStop(m_sources[id]);
702 }
703
704
705
706 // stop all sources
707 void SND_OpenALDevice::StopAllObjects()
708 {
709         alSourceStopv(NUM_SOURCES, m_sources);
710 }
711
712
713
714 // pause the source
715 void SND_OpenALDevice::PauseObject(int id) const
716 {
717         alSourcePause(m_sources[id]);
718 }
719
720
721
722 // source properties stuff ////////////////////////////////////////////////////////////
723
724
725
726 // give openal the object's pitch
727 void SND_OpenALDevice::SetObjectPitch(int id, MT_Scalar pitch) const
728 {
729         alSourcef (m_sources[id], AL_PITCH, (float)pitch);
730 }
731
732
733
734 // give openal the object's gain
735 void SND_OpenALDevice::SetObjectGain(int id, MT_Scalar gain) const
736 {
737         alSourcef (m_sources[id], AL_GAIN, (float)gain);
738 }
739
740
741
742 // give openal the object's looping
743 void SND_OpenALDevice::SetObjectLoop(int id, unsigned int loopmode) const
744 {
745         if (loopmode == SND_LOOP_OFF)
746         {
747                 //printf("%d - ", id);
748                 alSourcei (m_sources[id], AL_LOOPING, AL_FALSE);
749         }
750         else
751                 alSourcei (m_sources[id], AL_LOOPING, AL_TRUE);
752 }
753
754 void SND_OpenALDevice::SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const
755 {
756
757
758 }
759
760
761 void SND_OpenALDevice::SetObjectMinGain(int id, MT_Scalar mingain) const
762 {
763         alSourcef (m_sources[id], AL_MIN_GAIN, (float)mingain);
764 }
765
766
767
768 void SND_OpenALDevice::SetObjectMaxGain(int id, MT_Scalar maxgain) const
769 {
770         alSourcef (m_sources[id], AL_MAX_GAIN, (float)maxgain);
771 }
772
773
774
775 void SND_OpenALDevice::SetObjectRollOffFactor(int id, MT_Scalar rollofffactor) const
776 {
777         alSourcef (m_sources[id], AL_ROLLOFF_FACTOR, (float)rollofffactor);
778 }
779
780
781
782 void SND_OpenALDevice::SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const
783 {
784         alSourcef (m_sources[id], AL_REFERENCE_DISTANCE, (float)referencedistance);
785 }
786
787
788
789 // give openal the object's position
790 void SND_OpenALDevice::ObjectIs2D(int id) const
791 {
792         float obpos[3] = {0,0,0};
793         float obvel[3] = {0,0,0};
794         
795         alSourcefv(m_sources[id], AL_POSITION, obpos);
796         alSourcefv(m_sources[id], AL_VELOCITY, obvel);
797 }
798
799
800
801 void SND_OpenALDevice::SetObjectTransform(int id,
802                                                                                   const MT_Vector3& position,
803                                                                                   const MT_Vector3& velocity,
804                                                                                   const MT_Matrix3x3& orientation,
805                                                                                   const MT_Vector3& lisposition,
806                                                                                   const MT_Scalar& rollofffactor) const 
807 {
808         float obpos[3];
809         float obvel[3];
810
811         obpos[0] = (float)position[0] * (float)rollofffactor;   //x (l/r)
812         obpos[1] = (float)position[1] * (float)rollofffactor;
813         obpos[2] = (float)position[2] * (float)rollofffactor;
814
815         alSourcefv(m_sources[id], AL_POSITION, obpos);
816
817         velocity.getValue(obvel);
818         alSourcefv(m_sources[id], AL_VELOCITY, obvel);
819 }
820
821 void SND_OpenALDevice::PlayCD(int track) const
822 {
823 #ifndef __APPLE__
824         m_cdrom->PlayCD(track);
825 #endif
826 }
827
828
829 void SND_OpenALDevice::PauseCD(bool pause) const
830 {
831 #ifndef __APPLE__
832         m_cdrom->PauseCD(pause);
833 #endif
834 }
835
836 void SND_OpenALDevice::StopCD() const
837 {
838 #ifndef __APPLE__
839         SND_CDObject* pCD = SND_CDObject::Instance();
840
841         if (pCD && pCD->GetUsed())
842         {
843                 m_cdrom->StopCD();
844         }
845 #endif
846 }
847
848 void SND_OpenALDevice::SetCDPlaymode(int playmode) const
849 {
850 #ifndef __APPLE__
851         m_cdrom->SetCDPlaymode(playmode);
852 #endif
853 }
854
855 void SND_OpenALDevice::SetCDGain(MT_Scalar gain) const
856 {
857 #ifndef __APPLE__
858         m_cdrom->SetCDGain(gain);
859 #endif
860 }