26 ALushort BitsPerSample;
32 ALushort SamplesPerBlock;
63 void SwapWords(
unsigned int *puint )
69 void SwapBytes(
unsigned short *pshort )
75 void blutLoadWAVMemory( ALbyte *memory, ALenum
76 *format, ALvoid **data, ALsizei *
size, ALsizei *freq, ALboolean *
loop )
78 WAVChunkHdr_Struct ChunkHdr;
79 WAVFmtExHdr_Struct FmtExHdr;
80 WAVFileHdr_Struct FileHdr;
81 WAVSmplHdr_Struct SmplHdr;
82 WAVFmtHdr_Struct FmtHdr;
85 *format = AL_FORMAT_MONO16;
93 memcpy( &FileHdr, Stream,
sizeof (WAVFileHdr_Struct) );
94 Stream +=
sizeof (WAVFileHdr_Struct);
95 SwapWords( (
unsigned int*) &FileHdr.Size );
96 FileHdr.Size = ( (FileHdr.Size+1)&~1 )-4;
97 while ( (FileHdr.Size != 0) && (
memcpy( &ChunkHdr, Stream,
sizeof (WAVChunkHdr_Struct) ) ) ) {
98 Stream +=
sizeof (WAVChunkHdr_Struct);
99 SwapWords( &ChunkHdr.Size );
100 if ( (ChunkHdr.Id[0] ==
'f') && (ChunkHdr.Id[1] ==
'm') && (ChunkHdr.Id[2] ==
't')
101 && (ChunkHdr.Id[3] ==
' ') ) {
102 memcpy( &FmtHdr, Stream,
sizeof (WAVFmtHdr_Struct) );
103 SwapBytes( &FmtHdr.Format );
104 if (FmtHdr.Format == 0x0001) {
105 SwapBytes( &FmtHdr.Channels );
106 SwapBytes( &FmtHdr.BitsPerSample );
107 SwapWords( &FmtHdr.SamplesPerSec );
108 SwapBytes( &FmtHdr.BlockAlign );
110 *format = ( FmtHdr.Channels == 1
111 ? (FmtHdr.BitsPerSample == 8 ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16)
112 : (FmtHdr.BitsPerSample == 8 ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16) );
113 *freq = FmtHdr.SamplesPerSec;
114 Stream += ChunkHdr.Size;
116 memcpy( &FmtExHdr, Stream,
sizeof (WAVFmtExHdr_Struct) );
117 Stream += ChunkHdr.Size;
119 }
else if ( (ChunkHdr.Id[0] ==
'd') && (ChunkHdr.Id[1] ==
'a') && (ChunkHdr.Id[2] ==
't')
120 && (ChunkHdr.Id[3] ==
'a') ) {
121 if (FmtHdr.Format == 0x0001) {
122 *size = ChunkHdr.Size;
124 *data = malloc( ChunkHdr.Size+31 );
126 *data = realloc( *data, ChunkHdr.Size+31 );
128 memcpy( *data, Stream, ChunkHdr.Size );
129 memset( ( (
char*) *data )+ChunkHdr.Size, 0, 31 );
130 Stream += ChunkHdr.Size;
131 if (FmtHdr.BitsPerSample == 16)
132 for (
size_t i = 0;
i < (ChunkHdr.Size/2); ++
i)
133 SwapBytes( &(*(
unsigned short**) data)[
i] );
135 }
else if (FmtHdr.Format == 0x0011) {
137 }
else if (FmtHdr.Format == 0x0055) {
140 }
else if ( (ChunkHdr.Id[0] ==
's') && (ChunkHdr.Id[1] ==
'm') && (ChunkHdr.Id[2] ==
'p')
141 && (ChunkHdr.Id[3] ==
'l') ) {
142 memcpy( &SmplHdr, Stream,
sizeof (WAVSmplHdr_Struct) );
143 Stream += ChunkHdr.Size;
144 }
else {Stream += ChunkHdr.Size; } Stream += ChunkHdr.Size&1;
145 FileHdr.Size -= ( ( (ChunkHdr.Size+1)&~1 )+8 );
156 #include <sys/types.h>
157 #include <sys/stat.h>
174 #include <vorbis/vorbisfile.h>
176 std::vector< unsigned int >dirtysounds;
177 std::vector< OurSound > sounds;
178 std::vector< ALuint >buffers;
180 static void convertToLittle(
unsigned int tmp,
char *data )
182 data[0] = (char) (tmp%256);
183 data[1] = (char) ( (tmp/256)%256 );
184 data[2] = (char) ( (tmp/65536)%256 );
185 data[3] = (char) ( (tmp/65536)/256 );
196 size_t mem_read(
void *ptr,
size_t size,
size_t nmemb,
void *datasource )
198 fake_file *fp = (fake_file*) datasource;
199 if (fp->loc+size > fp->size) {
200 size_t tmp = fp->size-fp->loc;
202 memcpy( ptr, fp->data+fp->loc, tmp );
206 memcpy( ptr, fp->data+fp->loc, size );
212 int mem_close(
void* )
217 long mem_tell(
void *datasource )
219 fake_file *fp = (fake_file*) datasource;
220 return (
long) fp->loc;
223 int cant_seek(
void *datasource, ogg_int64_t offset,
int whence )
228 int mem_seek(
void *datasource, ogg_int64_t offset,
int whence )
230 fake_file *fp = (fake_file*) datasource;
231 if (whence == SEEK_END) {
233 if (fp->size < (
size_t) -offset) {
236 fp->loc = fp->size+offset;
239 }
else if (offset == 0) {
241 }
else {
return -1; }}
else if (whence == SEEK_CUR) {
243 if (fp->loc < (
size_t) -offset) {
250 if (fp->loc+offset > fp->size) {
257 }
else if (whence == SEEK_SET) {
258 if (offset > static_cast<int>(fp->size))
268 static void ConvertFormat( vector< char > &ogg )
270 vector< char >converted;
271 if (ogg.size() > 4) {
272 if (ogg[0] ==
'O' && ogg[1] ==
'g' && ogg[2] ==
'g' && ogg[3] ==
'S') {
275 ov_callbacks callbacks;
280 ff.size = ogg.size();
281 callbacks.read_func = &mem_read;
282 callbacks.seek_func = &mem_seek;
283 callbacks.close_func = &mem_close;
284 callbacks.tell_func = &mem_tell;
285 if ( ov_open_callbacks( &ff, &vf, NULL, 0, callbacks ) ) {
289 vorbis_info *info = ov_info( &vf, -1 );
290 const int segmentsize = 65536*32;
291 const int samples = 16;
292 converted.push_back(
'R' );
293 converted.push_back(
'I' );
294 converted.push_back(
'F' );
295 converted.push_back(
'F' );
296 converted.push_back( 0 );
297 converted.push_back( 0 );
298 converted.push_back( 0 );
299 converted.push_back( 0 );
300 converted.push_back(
'W' );
301 converted.push_back(
'A' );
302 converted.push_back(
'V' );
303 converted.push_back(
'E' );
304 converted.push_back(
'f' );
305 converted.push_back(
'm' );
306 converted.push_back(
't' );
307 converted.push_back(
' ' );
309 converted.push_back( 18 );
310 converted.push_back( 0 );
311 converted.push_back( 0 );
312 converted.push_back( 0 );
314 converted.push_back( 1 );
315 converted.push_back( 0 );
317 converted.push_back( (
char) (info->channels%256) );
318 converted.push_back( (
char) (info->channels/256) );
320 converted.push_back( 0 );
321 converted.push_back( 0 );
322 converted.push_back( 0 );
323 converted.push_back( 0 );
324 convertToLittle( info->rate, &converted[converted.size()-4] );
326 long byterate = info->rate*info->channels*samples/8;
327 converted.push_back( 0 );
328 converted.push_back( 0 );
329 converted.push_back( 0 );
330 converted.push_back( 0 );
331 convertToLittle( byterate, &converted[converted.size()-4] );
333 converted.push_back( (
char) ( (info->channels*samples/8)%256 ) );
334 converted.push_back( (
char) ( (info->channels*samples/8)/256 ) );
336 converted.push_back( samples );
337 converted.push_back( 0 );
338 converted.push_back( 0 );
339 converted.push_back( 0 );
342 converted.push_back(
'd' );
343 converted.push_back(
'a' );
344 converted.push_back(
't' );
345 converted.push_back(
'a' );
347 converted.push_back( 0 );
348 converted.push_back( 0 );
349 converted.push_back( 0 );
350 converted.push_back( 0 );
351 ogg_int64_t pcmsizestart = converted.size();
352 converted.resize( converted.size()+segmentsize );
355 while ( ( bytesread =
356 ov_read( &vf, &converted[converted.size()-segmentsize], segmentsize, 0, samples/8, signedvalue,
357 &bitstream ) ) > 0 ) {
359 if (bytesread < segmentsize)
360 numtoerase = segmentsize-bytesread;
362 converted.resize( converted.size()+segmentsize-numtoerase );
364 converted.resize( converted.size()-segmentsize );
365 convertToLittle( converted.size()-8, &converted[4] );
366 convertToLittle( converted.size()-pcmsizestart, &converted[pcmsizestart-4] );
368 converted.swap( ogg );
378 static int LoadSound( ALuint
buffer,
bool looping,
bool music )
381 if ( !dirtysounds.empty() ) {
382 i = dirtysounds.back();
383 dirtysounds.pop_back();
385 if (sounds[i].buffer != (ALuint) 0)
387 sounds[i].buffer =
buffer;
390 sounds.push_back( OurSound( 0, buffer ) );
392 sounds[i].source = (ALuint) 0;
393 sounds[i].looping = looping ? AL_TRUE : AL_FALSE;
394 sounds[i].music = music;
396 printf(
" with buffer %d and looping property %d\n", i, (
int) looping );
407 using namespace VSFileSystem;
413 info->success =
false;
416 FILE *
f =
fopen( s,
"rb" );
418 std::string path = std::string(
"sounds/" )+s;
419 f =
fopen( path.c_str(),
"rb" );
422 std::string path = std::string(
"music/" )+s;
423 f =
fopen( path.c_str(),
"rb" );
426 fseek( f, 0, SEEK_END );
427 size_t siz = ftell( f );
428 fseek( f, 0, SEEK_SET );
430 size_t bogus_return_var;
431 bogus_return_var = fread( &dat[0], 1, siz, f );
433 info->shared =
false;
443 info->shared = (error ==
Shared);
451 printf(
"Sound %s created with and alBuffer %d\n", s.c_str(), *wavbuf );
453 dat.resize( f.
Size() );
457 ConvertFormat( dat );
466 MacFixedLoadWAVFile( &dat[0], &format, &wave, &size, &freq );
468 blutLoadWAVMemory( (ALbyte*) &dat[0], &info->format, &info->wave, &info->size, &info->freq, &info->looping );
473 info->success =
true;
481 alGenBuffers( 1, &wavbuf );
482 if (!wavbuf) printf(
"OpenAL Error in alGenBuffers: %d\n", alGetError() );
483 alBufferData( wavbuf, info->format, info->wave, info->size, info->freq );
485 return LoadSound( wavbuf, info->looping, music );
499 printf(
"AUDCreateSoundWAV:: " );
502 ALuint *wavbuf = NULL;
503 std::string hashname;
506 wavbuf = soundHash.Get( hashname );
509 wavbuf = soundHash.Get( hashname );
516 printf(
"Sound %s restored with alBuffer %d\n", s.c_str(), *wavbuf );
519 if (wavbuf == NULL) {
520 AUDSoundProperties info;
525 wavbuf = (ALuint*) malloc(
sizeof (ALuint) );
526 alGenBuffers( 1, wavbuf );
527 alBufferData( *wavbuf, info.format, info.wave, info.size, info.freq );
530 soundHash.Put( info.hashname, wavbuf );
531 buffers.push_back( *wavbuf );
534 return LoadSound( *wavbuf, LOOP, music );
557 bool shared = (error ==
Shared);
558 std::string nam( s );
559 ALuint *mp3buf = NULL;
560 std::string hashname;
563 mp3buf = soundHash.Get( hashname );
570 if (mp3buf == NULL) {
571 char *data =
new char[f.
Size()];
573 mp3buf = (ALuint*) malloc(
sizeof (ALuint) );
574 alGenBuffers( 1, mp3buf );
582 soundHash.Put( hashname, mp3buf );
583 buffers.push_back( *mp3buf );
588 return LoadSound( *mp3buf, LOOP, music );
606 if ( s.end()-1 >= s.begin() ) {
607 if (*(s.end()-1) ==
'3')
617 if ( s.end()-1 >= s.begin() ) {
618 if (*(s.end()-1) ==
'v')
632 if ( sound >= 0 && sound < (
int) sounds.size() )
633 return LoadSound( sounds[sound].buffer, LOOP,
false );
642 if ( sound >= 0 && sound < (
int) sounds.size() ) {
646 printf(
"AUDDeleteSound: Sound Playing enqueue soundstodelete %d %d\n",
647 sounds[sound].source,
648 sounds[sound].buffer );
657 printf(
"AUDDeleteSound: Sound Not Playing push back to unused src %d %d\n", sounds[sound].source, sounds[sound].buffer );
659 if (sounds[sound].source) {
660 unusedsrcs.push_back( sounds[sound].source );
661 alSourcei( sounds[sound].source, AL_BUFFER, 0 );
662 sounds[sound].source = (ALuint) 0;
665 if ( std::find( dirtysounds.begin(), dirtysounds.end(), sound ) == dirtysounds.end() ) {
667 dirtysounds.push_back( sound );
677 alDeleteBuffers( 1, &sounds[sound].buffer );
678 sounds[sound].buffer = (ALuint) 0;
689 if ( sound >= 0 && sound < (
int) sounds.size() ) {
691 scalepos *pos.i, scalepos*pos.j, scalepos*pos.k
694 float v[] = {scalevel *vel.i, scalevel*vel.j, scalevel*vel.k};
695 sounds[sound].pos = pos.Cast();
696 sounds[sound].vel = vel;
697 if (usepositional && sounds[sound].source) {
698 alSourcefv( sounds[sound].source, AL_POSITION, p );
699 bool relative = (p[0] == 0 && p[1] == 0 && p[2] == 0);
700 alSourcei( sounds[sound].source, AL_SOURCE_RELATIVE, relative );
703 alSourcef(sounds[sound].source, AL_MAX_DISTANCE, scalepos * max_distance);
704 alSourcef(sounds[sound].source, AL_REFERENCE_DISTANCE, scalepos * ref_distance);
705 alSourcef(sounds[sound].source, AL_ROLLOFF_FACTOR, 1.
f);
708 if (usedoppler && sounds[sound].source)
709 alSourcefv( sounds[sound].source, AL_VELOCITY, v );
717 if (sound >= 0 && sound < (
int) sounds.size() && sounds[sound].source) {
718 alSource3f( sounds[sound].source, AL_POSITION, 0.0, 0.0, 0.0 );
719 alSource3f( sounds[sound].source, AL_VELOCITY, 0.0, 0.0, 0.0 );
720 alSource3f( sounds[sound].source, AL_DIRECTION, 0.0, 0.0, 0.0 );
721 alSourcef( sounds[sound].source, AL_ROLLOFF_FACTOR, 0.0 );
722 alSourcei( sounds[sound].source, AL_SOURCE_RELATIVE, AL_TRUE );
742 unsigned int s = ::sounds.size();
743 for (
unsigned int i = 0; i < s; ++i)
744 if (
false == ::sounds[i].music &&
AUDIsPlaying( i ) &&
false == ::sounds[i].looping)
753 unsigned int s = ::sounds.size();
754 for (
unsigned int i = 0; i < s; ++i)
755 if ( (
int) i != except_this_one &&
false == ::sounds[i].music &&
AUDIsPlaying( i ) )
763 if ( sound >= 0 && sound < (
int) sounds.size() ) {
764 if (!sounds[sound].source)
767 #if defined (_WIN32) || defined (__APPLE__)
768 alGetSourcei( sounds[sound].source, AL_SOURCE_STATE, &state );
770 alGetSourceiv( sounds[sound].source, AL_SOURCE_STATE, &state );
773 return state == AL_PLAYING;
782 if ( sound >= 0 && sound < (
int) sounds.size() ) {
784 printf(
"AUDStopPlaying sound %d source(releasing): %d buffer:%d\n", sound, sounds[sound].source, sounds[sound].buffer );
786 if (sounds[sound].source != 0) {
787 alSourceStop( sounds[sound].source );
788 unusedsrcs.push_back( sounds[sound].source );
789 alSourcei( sounds[sound].source, AL_BUFFER, 0 );
791 sounds[sound].source = (ALuint) 0;
799 if (sounds[sound].source == (ALuint) 0) {
800 if (!sounds[sound].buffer)
802 if ( unusedsrcs.empty() ) {
805 unsigned int candidate = 0;
807 for (i = 0; i < sounds.size(); ++i)
808 if (sounds[i].source != 0)
809 if (sounds[i].pos.i != 0 || sounds[i].pos.j != 0 || sounds[i].pos.k != 0) {
821 alSourceStop( sounds[candidate].source );
822 sounds[sound].source = sounds[candidate].source;
823 alSourcei( sounds[candidate].source, AL_BUFFER, 0 );
824 sounds[candidate].source = 0;
830 sounds[sound].source = unusedsrcs.back();
831 unusedsrcs.pop_back();
833 alSourcei( sounds[sound].source, AL_BUFFER, sounds[sound].buffer );
834 alSourcei( sounds[sound].source, AL_LOOPING, sounds[sound].looping );
844 printf(
"AUDStartPlaying(%d)", sound );
848 if ( sound >= 0 && sound < (
int) sounds.size() ) {
852 printf(
"AUDStartPlaying sound %d source:%d buffer:%d\n", sound, sounds[sound].source, sounds[sound].buffer );
855 AUDSoundGain( sound, sounds[sound].gain, sounds[sound].music );
856 alSourcePlay( sounds[sound].source );
868 if (sounds[sound].buffer == 0)
880 sounds[sound].source, sounds[sound].buffer );
884 sounds[sound].source, sounds[sound].buffer );
885 alSourceStop( sounds[sound].source );
887 alSourcePlay( sounds[sound].source );
893 #ifndef AL_SEC_OFFSET
895 #define AL_SEC_OFFSET 0x1024
912 if ( sound >= 0 && sound < (
int) sounds.size() ) {