1 #include "alutInternal.h"
4 /****************************************************************************/
10 UnknwonEndian /* has anybody still a PDP11? :-) */
13 /* test from Harbison & Steele, "C - A Reference Manual", section 6.1.2 */
20 char c[sizeof (long)];
24 return (u.c[0] == 1) ? LittleEndian :
25 ((u.c[sizeof (long) - 1] == 1) ? BigEndian : UnknwonEndian);
28 /****************************************************************************/
33 return isupper (c) ? tolower (c) : c;
37 hasSuffixIgnoringCase (const char *string, const char *suffix)
39 const char *stringPointer = string;
40 const char *suffixPointer = suffix;
42 if (suffix[0] == '\0')
47 while (*stringPointer != '\0')
52 while (*suffixPointer != '\0')
57 if (stringPointer - string < suffixPointer - suffix)
62 while (safeToLower (*--suffixPointer) == safeToLower (*--stringPointer))
64 if (suffixPointer == suffix)
74 loadWavFile (InputStream *stream)
76 ALboolean found_header = AL_FALSE;
77 UInt32LittleEndian chunkLength;
79 UInt16LittleEndian audioFormat;
80 UInt16LittleEndian numChannels;
81 UInt32LittleEndian sampleFrequency;
82 UInt32LittleEndian byteRate;
83 UInt16LittleEndian blockAlign;
84 UInt16LittleEndian bitsPerSample;
85 Codec *codec = _alutCodecLinear;
87 if (!_alutInputStreamReadUInt32LE (stream, &chunkLength) ||
88 !_alutInputStreamReadInt32BE (stream, &magic))
93 if (magic != 0x57415645) /* "WAVE" */
95 _alutSetError (ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
101 if (!_alutInputStreamReadInt32BE (stream, &magic) ||
102 !_alutInputStreamReadUInt32LE (stream, &chunkLength))
107 if (magic == 0x666d7420) /* "fmt " */
109 found_header = AL_TRUE;
111 if (chunkLength < 16)
113 _alutSetError (ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
117 if (!_alutInputStreamReadUInt16LE (stream, &audioFormat) ||
118 !_alutInputStreamReadUInt16LE (stream, &numChannels) ||
119 !_alutInputStreamReadUInt32LE (stream, &sampleFrequency) ||
120 !_alutInputStreamReadUInt32LE (stream, &byteRate) ||
121 !_alutInputStreamReadUInt16LE (stream, &blockAlign) ||
122 !_alutInputStreamReadUInt16LE (stream, &bitsPerSample))
127 if (!_alutInputStreamSkip (stream, chunkLength - 16))
135 codec = (bitsPerSample == 8
137 LittleEndian) ? _alutCodecLinear : _alutCodecPCM16;
140 bitsPerSample *= 2; /* ToDo: ??? */
141 codec = _alutCodecULaw;
144 _alutSetError (ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
148 else if (magic == 0x64617461) /* "data" */
153 /* ToDo: A bit wrong to check here, fmt chunk could come later... */
154 _alutSetError (ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
157 data = _alutInputStreamRead (stream, chunkLength);
162 return codec (data, chunkLength, numChannels, bitsPerSample,
163 (ALfloat) sampleFrequency);
167 if (!_alutInputStreamSkip (stream, chunkLength))
173 if ((chunkLength & 1) && !_alutInputStreamEOF (stream)
174 && !_alutInputStreamSkip (stream, 1))
182 loadAUFile (InputStream *stream)
184 Int32BigEndian dataOffset; /* byte offset to data part, minimum 24 */
185 Int32BigEndian len; /* number of bytes in the data part, -1 = not known */
186 Int32BigEndian encoding; /* encoding of the data part, see AUEncoding */
187 Int32BigEndian sampleFrequency; /* number of samples per second */
188 Int32BigEndian numChannels; /* number of interleaved channels */
194 if (!_alutInputStreamReadInt32BE (stream, &dataOffset) ||
195 !_alutInputStreamReadInt32BE (stream, &len) ||
196 !_alutInputStreamReadInt32BE (stream, &encoding) ||
197 !_alutInputStreamReadInt32BE (stream, &sampleFrequency) ||
198 !_alutInputStreamReadInt32BE (stream, &numChannels))
203 length = (len == -1) ?
204 (_alutInputStreamGetRemainingLength (stream) - AU_HEADER_SIZE -
205 dataOffset) : (size_t) len;
208 (dataOffset >= AU_HEADER_SIZE && length > 0 && sampleFrequency >= 1
209 && numChannels >= 1))
211 _alutSetError (ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
215 if (!_alutInputStreamSkip (stream, dataOffset - AU_HEADER_SIZE))
224 codec = _alutCodecULaw;
228 codec = _alutCodecPCM8s;
233 (endianess () == BigEndian) ? _alutCodecLinear : _alutCodecPCM16;
237 codec = _alutCodecALaw;
240 _alutSetError (ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
244 data = _alutInputStreamRead (stream, length);
249 return codec (data, length, numChannels, bitsPerSample,
250 (ALfloat) sampleFrequency);
254 loadRawFile (InputStream *stream)
256 size_t length = _alutInputStreamGetRemainingLength (stream);
257 ALvoid *data = _alutInputStreamRead (stream, length);
263 return _alutCodecLinear (data, length, 1, 8, 8000);
267 loadFile (InputStream *stream)
269 const char *fileName;
270 Int32BigEndian magic;
272 /* Raw files have no magic number - so use the fileName extension */
274 fileName = _alutInputStreamGetFileName (stream);
275 if (fileName != NULL && hasSuffixIgnoringCase (fileName, ".raw"))
277 return loadRawFile (stream);
280 /* For other file formats, read the quasi-standard four byte magic number */
281 if (!_alutInputStreamReadInt32BE (stream, &magic))
286 /* Magic number 'RIFF' == Microsoft '.wav' format */
287 if (magic == 0x52494646)
289 return loadWavFile (stream);
292 /* Magic number '.snd' == Sun & Next's '.au' format */
293 if (magic == 0x2E736E64)
295 return loadAUFile (stream);
298 _alutSetError (ALUT_ERROR_UNSUPPORTED_FILE_TYPE);
303 _alutCreateBufferFromInputStream (InputStream *stream)
305 BufferData *bufferData;
313 bufferData = loadFile (stream);
314 _alutInputStreamDestroy (stream);
315 if (bufferData == NULL)
320 buffer = _alutPassBufferData (bufferData);
321 _alutBufferDataDestroy (bufferData);
327 alutCreateBufferFromFile (const char *fileName)
330 if (!_alutSanityCheck ())
334 stream = _alutInputStreamConstructFromFile (fileName);
335 return _alutCreateBufferFromInputStream (stream);
339 alutCreateBufferFromFileImage (const ALvoid *data, ALsizei length)
342 if (!_alutSanityCheck ())
346 stream = _alutInputStreamConstructFromMemory (data, length);
347 return _alutCreateBufferFromInputStream (stream);
351 _alutLoadMemoryFromInputStream (InputStream *stream, ALenum *format,
352 ALsizei *size, ALfloat *frequency)
354 BufferData *bufferData;
363 bufferData = loadFile (stream);
364 if (bufferData == NULL)
366 _alutInputStreamDestroy (stream);
369 _alutInputStreamDestroy (stream);
371 if (!_alutGetFormat (bufferData, &fmt))
373 _alutBufferDataDestroy (bufferData);
379 *size = (ALsizei) _alutBufferDataGetLength (bufferData);
387 if (frequency != NULL)
389 *frequency = _alutBufferDataGetSampleFrequency (bufferData);
392 data = _alutBufferDataGetData (bufferData);
393 _alutBufferDataDetachData (bufferData);
394 _alutBufferDataDestroy (bufferData);
399 alutLoadMemoryFromFile (const char *fileName, ALenum *format,
400 ALsizei *size, ALfloat *frequency)
403 if (!_alutSanityCheck ())
407 stream = _alutInputStreamConstructFromFile (fileName);
408 return _alutLoadMemoryFromInputStream (stream, format, size, frequency);
412 alutLoadMemoryFromFileImage (const ALvoid *data, ALsizei length,
413 ALenum *format, ALsizei *size,
417 if (!_alutSanityCheck ())
421 stream = _alutInputStreamConstructFromMemory (data, length);
422 return _alutLoadMemoryFromInputStream (stream, format, size, frequency);
426 Yukky backwards compatibility crap.
430 alutLoadWAVFile (ALbyte *fileName, ALenum *format, void **data, ALsizei *size,
432 #if !defined(__APPLE__)
440 /* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
442 stream = _alutInputStreamConstructFromFile (fileName);
443 *data = _alutLoadMemoryFromInputStream (stream, format, size, &freq);
451 *frequency = (ALsizei) freq;
454 #if !defined(__APPLE__)
463 alutLoadWAVMemory (ALbyte *buffer, ALenum *format, void **data, ALsizei *size,
465 #if !defined(__APPLE__)
473 /* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
475 /* ToDo: Can we do something less insane than passing 0x7FFFFFFF? */
476 stream = _alutInputStreamConstructFromMemory (buffer, 0x7FFFFFFF);
477 _alutLoadMemoryFromInputStream (stream, format, size, &freq);
485 *frequency = (ALsizei) freq;
488 #if !defined(__APPLE__)
497 alutUnloadWAV (ALenum UNUSED (format), ALvoid *data, ALsizei UNUSED (size),
498 ALsizei UNUSED (frequency))
500 /* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
506 alutGetMIMETypes (ALenum loader)
508 if (!_alutSanityCheck ())
513 /* We do not distinguish the loaders yet... */
516 case ALUT_LOADER_BUFFER:
517 return "audio/basic,audio/x-raw,audio/x-wav";
519 case ALUT_LOADER_MEMORY:
520 return "audio/basic,audio/x-raw,audio/x-wav";
523 _alutSetError (ALUT_ERROR_INVALID_ENUM);