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 */
14
static Endianess endianess(void)
23
return (u.c[0] == 1) ? LittleEndian : ((u.c[sizeof(long) - 1] == 1) ? BigEndian : UnknwonEndian);
26
/****************************************************************************/
28
static int safeToLower(int c)
30
return isupper(c) ? tolower(c) : c;
33
static int hasSuffixIgnoringCase(const char *string, const char *suffix)
35
const char *stringPointer = string;
36
const char *suffixPointer = suffix;
38
if (suffix[0] == '\0')
43
while (*stringPointer != '\0')
48
while (*suffixPointer != '\0')
53
if (stringPointer - string < suffixPointer - suffix)
58
while (safeToLower(*--suffixPointer) == safeToLower(*--stringPointer))
60
if (suffixPointer == suffix)
69
static BufferData *loadWavFile(InputStream * stream)
71
ALboolean found_header = AL_FALSE;
72
UInt32LittleEndian chunkLength;
74
UInt16LittleEndian audioFormat;
75
UInt16LittleEndian numChannels;
76
UInt32LittleEndian sampleFrequency;
77
UInt32LittleEndian byteRate;
78
UInt16LittleEndian blockAlign;
79
UInt16LittleEndian bitsPerSample;
80
Codec *codec = _alutCodecLinear;
82
if (!_alutInputStreamReadUInt32LE(stream, &chunkLength) || !_alutInputStreamReadInt32BE(stream, &magic))
87
if (magic != 0x57415645) /* "WAVE" */
89
_alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
95
if (!_alutInputStreamReadInt32BE(stream, &magic) || !_alutInputStreamReadUInt32LE(stream, &chunkLength))
100
if (magic == 0x666d7420) /* "fmt " */
102
found_header = AL_TRUE;
104
if (chunkLength < 16)
106
_alutSetError(ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
110
if (!_alutInputStreamReadUInt16LE(stream, &audioFormat) ||
111
!_alutInputStreamReadUInt16LE(stream, &numChannels) ||
112
!_alutInputStreamReadUInt32LE(stream, &sampleFrequency) ||
113
!_alutInputStreamReadUInt32LE(stream, &byteRate) ||
114
!_alutInputStreamReadUInt16LE(stream, &blockAlign) || !_alutInputStreamReadUInt16LE(stream, &bitsPerSample))
119
if (!_alutInputStreamSkip(stream, chunkLength - 16))
127
codec = (bitsPerSample == 8 || endianess() == LittleEndian) ? _alutCodecLinear : _alutCodecPCM16;
130
bitsPerSample *= 2; /* ToDo: ??? */
131
codec = _alutCodecULaw;
134
_alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
138
else if (magic == 0x64617461) /* "data" */
144
/* ToDo: A bit wrong to check here, fmt chunk could come later... */
145
_alutSetError(ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
148
data = _alutInputStreamRead(stream, chunkLength);
153
return codec(data, chunkLength, numChannels, bitsPerSample, (ALfloat) sampleFrequency);
157
if (!_alutInputStreamSkip(stream, chunkLength))
163
if ((chunkLength & 1) && !_alutInputStreamEOF(stream) && !_alutInputStreamSkip(stream, 1))
170
static BufferData *loadAUFile(InputStream * stream)
172
Int32BigEndian dataOffset; /* byte offset to data part, minimum 24 */
173
Int32BigEndian len; /* number of bytes in the data part, -1 = not known */
174
Int32BigEndian encoding; /* encoding of the data part, see AUEncoding */
175
Int32BigEndian sampleFrequency; /* number of samples per second */
176
Int32BigEndian numChannels; /* number of interleaved channels */
182
if (!_alutInputStreamReadInt32BE(stream, &dataOffset) ||
183
!_alutInputStreamReadInt32BE(stream, &len) ||
184
!_alutInputStreamReadInt32BE(stream, &encoding) ||
185
!_alutInputStreamReadInt32BE(stream, &sampleFrequency) || !_alutInputStreamReadInt32BE(stream, &numChannels))
190
length = (len == -1) ? (_alutInputStreamGetRemainingLength(stream) - AU_HEADER_SIZE - dataOffset) : (size_t) len;
192
if (!(dataOffset >= AU_HEADER_SIZE && length > 0 && sampleFrequency >= 1 && numChannels >= 1))
194
_alutSetError(ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
198
if (!_alutInputStreamSkip(stream, dataOffset - AU_HEADER_SIZE))
207
codec = _alutCodecULaw;
211
codec = _alutCodecPCM8s;
215
codec = (endianess() == BigEndian) ? _alutCodecLinear : _alutCodecPCM16;
219
codec = _alutCodecALaw;
222
_alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
226
data = _alutInputStreamRead(stream, length);
231
return codec(data, length, numChannels, bitsPerSample, (ALfloat) sampleFrequency);
234
static BufferData *loadRawFile(InputStream * stream)
236
size_t length = _alutInputStreamGetRemainingLength(stream);
237
ALvoid *data = _alutInputStreamRead(stream, length);
244
return _alutCodecLinear(data, length, 1, 8, 8000);
247
static BufferData *loadFile(InputStream * stream)
249
const char *fileName;
250
Int32BigEndian magic;
252
/* Raw files have no magic number - so use the fileName extension */
254
fileName = _alutInputStreamGetFileName(stream);
255
if (fileName != NULL && hasSuffixIgnoringCase(fileName, ".raw"))
257
return loadRawFile(stream);
260
/* For other file formats, read the quasi-standard four byte magic number */
261
if (!_alutInputStreamReadInt32BE(stream, &magic))
266
/* Magic number 'RIFF' == Microsoft '.wav' format */
267
if (magic == 0x52494646)
269
return loadWavFile(stream);
272
/* Magic number '.snd' == Sun & Next's '.au' format */
273
if (magic == 0x2E736E64)
275
return loadAUFile(stream);
278
_alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_TYPE);
282
ALuint _alutCreateBufferFromInputStream(InputStream * stream)
284
BufferData *bufferData;
292
bufferData = loadFile(stream);
293
_alutInputStreamDestroy(stream);
294
if (bufferData == NULL)
299
buffer = _alutPassBufferData(bufferData);
300
_alutBufferDataDestroy(bufferData);
305
ALuint alutCreateBufferFromFile(const char *fileName)
309
if (!_alutSanityCheck())
313
stream = _alutInputStreamConstructFromFile(fileName);
314
return _alutCreateBufferFromInputStream(stream);
317
ALuint alutCreateBufferFromFileImage(const ALvoid * data, ALsizei length)
321
if (!_alutSanityCheck())
325
stream = _alutInputStreamConstructFromMemory(data, length);
326
return _alutCreateBufferFromInputStream(stream);
329
void *_alutLoadMemoryFromInputStream(InputStream * stream, ALenum * format, ALsizei * size, ALfloat * frequency)
331
BufferData *bufferData;
340
bufferData = loadFile(stream);
341
if (bufferData == NULL)
343
_alutInputStreamDestroy(stream);
346
_alutInputStreamDestroy(stream);
348
if (!_alutGetFormat(bufferData, &fmt))
350
_alutBufferDataDestroy(bufferData);
356
*size = (ALsizei) _alutBufferDataGetLength(bufferData);
364
if (frequency != NULL)
366
*frequency = _alutBufferDataGetSampleFrequency(bufferData);
369
data = _alutBufferDataGetData(bufferData);
370
_alutBufferDataDetachData(bufferData);
371
_alutBufferDataDestroy(bufferData);
375
ALvoid *alutLoadMemoryFromFile(const char *fileName, ALenum * format, ALsizei * size, ALfloat * frequency)
379
if (!_alutSanityCheck())
383
stream = _alutInputStreamConstructFromFile(fileName);
384
return _alutLoadMemoryFromInputStream(stream, format, size, frequency);
387
ALvoid *alutLoadMemoryFromFileImage(const ALvoid * data, ALsizei length, ALenum * format, ALsizei * size, ALfloat * frequency)
391
if (!_alutSanityCheck())
395
stream = _alutInputStreamConstructFromMemory(data, length);
396
return _alutLoadMemoryFromInputStream(stream, format, size, frequency);
400
Yukky backwards compatibility crap.
403
void alutLoadWAVFile(ALbyte * fileName, ALenum * format, void **data, ALsizei * size, ALsizei * frequency
404
#if !defined(__APPLE__)
412
/* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
414
stream = _alutInputStreamConstructFromFile(fileName);
415
*data = _alutLoadMemoryFromInputStream(stream, format, size, &freq);
423
*frequency = (ALsizei) freq;
426
#if !defined(__APPLE__)
434
void alutLoadWAVMemory(ALbyte * buffer, ALenum * format, void **data, ALsizei * size, ALsizei * frequency
435
#if !defined(__APPLE__)
443
/* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
445
/* ToDo: Can we do something less insane than passing 0x7FFFFFFF? */
446
stream = _alutInputStreamConstructFromMemory(buffer, 0x7FFFFFFF);
447
_alutLoadMemoryFromInputStream(stream, format, size, &freq);
455
*frequency = (ALsizei) freq;
458
#if !defined(__APPLE__)
466
void alutUnloadWAV(ALenum UNUSED(format), ALvoid * data, ALsizei UNUSED(size), ALsizei UNUSED(frequency))
468
/* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
473
const char *alutGetMIMETypes(ALenum loader)
475
if (!_alutSanityCheck())
480
/* We do not distinguish the loaders yet... */
483
case ALUT_LOADER_BUFFER:
484
return "audio/basic,audio/x-raw,audio/x-wav";
486
case ALUT_LOADER_MEMORY:
487
return "audio/basic,audio/x-raw,audio/x-wav";
490
_alutSetError(ALUT_ERROR_INVALID_ENUM);