~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freealut/src/alutLoader.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "alutInternal.h"
 
2
#include <ctype.h>
 
3
 
 
4
/****************************************************************************/
 
5
 
 
6
typedef enum
 
7
{
 
8
  LittleEndian,
 
9
  BigEndian,
 
10
  UnknwonEndian                 /* has anybody still a PDP11? :-) */
 
11
} Endianess;
 
12
 
 
13
/* test from Harbison & Steele, "C - A Reference Manual", section 6.1.2 */
 
14
static Endianess endianess(void)
 
15
{
 
16
  union
 
17
  {
 
18
    long l;
 
19
    char c[sizeof(long)];
 
20
  } u;
 
21
 
 
22
  u.l = 1;
 
23
  return (u.c[0] == 1) ? LittleEndian : ((u.c[sizeof(long) - 1] == 1) ? BigEndian : UnknwonEndian);
 
24
}
 
25
 
 
26
/****************************************************************************/
 
27
 
 
28
static int safeToLower(int c)
 
29
{
 
30
  return isupper(c) ? tolower(c) : c;
 
31
}
 
32
 
 
33
static int hasSuffixIgnoringCase(const char *string, const char *suffix)
 
34
{
 
35
  const char *stringPointer = string;
 
36
  const char *suffixPointer = suffix;
 
37
 
 
38
  if (suffix[0] == '\0')
 
39
  {
 
40
    return 1;
 
41
  }
 
42
 
 
43
  while (*stringPointer != '\0')
 
44
  {
 
45
    stringPointer++;
 
46
  }
 
47
 
 
48
  while (*suffixPointer != '\0')
 
49
  {
 
50
    suffixPointer++;
 
51
  }
 
52
 
 
53
  if (stringPointer - string < suffixPointer - suffix)
 
54
  {
 
55
    return 0;
 
56
  }
 
57
 
 
58
  while (safeToLower(*--suffixPointer) == safeToLower(*--stringPointer))
 
59
  {
 
60
    if (suffixPointer == suffix)
 
61
    {
 
62
      return 1;
 
63
    }
 
64
  }
 
65
 
 
66
  return 0;
 
67
}
 
68
 
 
69
static BufferData *loadWavFile(InputStream * stream)
 
70
{
 
71
  ALboolean found_header = AL_FALSE;
 
72
  UInt32LittleEndian chunkLength;
 
73
  Int32BigEndian magic;
 
74
  UInt16LittleEndian audioFormat;
 
75
  UInt16LittleEndian numChannels;
 
76
  UInt32LittleEndian sampleFrequency;
 
77
  UInt32LittleEndian byteRate;
 
78
  UInt16LittleEndian blockAlign;
 
79
  UInt16LittleEndian bitsPerSample;
 
80
  Codec *codec = _alutCodecLinear;
 
81
 
 
82
  if (!_alutInputStreamReadUInt32LE(stream, &chunkLength) || !_alutInputStreamReadInt32BE(stream, &magic))
 
83
  {
 
84
    return NULL;
 
85
  }
 
86
 
 
87
  if (magic != 0x57415645)      /* "WAVE" */
 
88
  {
 
89
    _alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
 
90
    return NULL;
 
91
  }
 
92
 
 
93
  while (1)
 
94
  {
 
95
    if (!_alutInputStreamReadInt32BE(stream, &magic) || !_alutInputStreamReadUInt32LE(stream, &chunkLength))
 
96
    {
 
97
      return NULL;
 
98
    }
 
99
 
 
100
    if (magic == 0x666d7420)    /* "fmt " */
 
101
    {
 
102
      found_header = AL_TRUE;
 
103
 
 
104
      if (chunkLength < 16)
 
105
      {
 
106
        _alutSetError(ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
 
107
        return NULL;
 
108
      }
 
109
 
 
110
      if (!_alutInputStreamReadUInt16LE(stream, &audioFormat) ||
 
111
          !_alutInputStreamReadUInt16LE(stream, &numChannels) ||
 
112
          !_alutInputStreamReadUInt32LE(stream, &sampleFrequency) ||
 
113
          !_alutInputStreamReadUInt32LE(stream, &byteRate) ||
 
114
          !_alutInputStreamReadUInt16LE(stream, &blockAlign) || !_alutInputStreamReadUInt16LE(stream, &bitsPerSample))
 
115
      {
 
116
        return NULL;
 
117
      }
 
118
 
 
119
      if (!_alutInputStreamSkip(stream, chunkLength - 16))
 
120
      {
 
121
        return NULL;
 
122
      }
 
123
 
 
124
      switch (audioFormat)
 
125
      {
 
126
      case 1:                  /* PCM */
 
127
        codec = (bitsPerSample == 8 || endianess() == LittleEndian) ? _alutCodecLinear : _alutCodecPCM16;
 
128
        break;
 
129
      case 7:                  /* uLaw */
 
130
        bitsPerSample *= 2;     /* ToDo: ??? */
 
131
        codec = _alutCodecULaw;
 
132
        break;
 
133
      default:
 
134
        _alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
 
135
        return NULL;
 
136
      }
 
137
    }
 
138
    else if (magic == 0x64617461) /* "data" */
 
139
    {
 
140
      ALvoid *data;
 
141
 
 
142
      if (!found_header)
 
143
      {
 
144
        /* ToDo: A bit wrong to check here, fmt chunk could come later... */
 
145
        _alutSetError(ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
 
146
        return NULL;
 
147
      }
 
148
      data = _alutInputStreamRead(stream, chunkLength);
 
149
      if (data == NULL)
 
150
      {
 
151
        return NULL;
 
152
      }
 
153
      return codec(data, chunkLength, numChannels, bitsPerSample, (ALfloat) sampleFrequency);
 
154
    }
 
155
    else
 
156
    {
 
157
      if (!_alutInputStreamSkip(stream, chunkLength))
 
158
      {
 
159
        return NULL;
 
160
      }
 
161
    }
 
162
 
 
163
    if ((chunkLength & 1) && !_alutInputStreamEOF(stream) && !_alutInputStreamSkip(stream, 1))
 
164
    {
 
165
      return NULL;
 
166
    }
 
167
  }
 
168
}
 
169
 
 
170
static BufferData *loadAUFile(InputStream * stream)
 
171
{
 
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 */
 
177
  size_t length;
 
178
  Codec *codec;
 
179
  char *data;
 
180
  ALint bitsPerSample;
 
181
 
 
182
  if (!_alutInputStreamReadInt32BE(stream, &dataOffset) ||
 
183
      !_alutInputStreamReadInt32BE(stream, &len) ||
 
184
      !_alutInputStreamReadInt32BE(stream, &encoding) ||
 
185
      !_alutInputStreamReadInt32BE(stream, &sampleFrequency) || !_alutInputStreamReadInt32BE(stream, &numChannels))
 
186
  {
 
187
    return AL_FALSE;
 
188
  }
 
189
 
 
190
  length = (len == -1) ? (_alutInputStreamGetRemainingLength(stream) - AU_HEADER_SIZE - dataOffset) : (size_t) len;
 
191
 
 
192
  if (!(dataOffset >= AU_HEADER_SIZE && length > 0 && sampleFrequency >= 1 && numChannels >= 1))
 
193
  {
 
194
    _alutSetError(ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
 
195
    return AL_FALSE;
 
196
  }
 
197
 
 
198
  if (!_alutInputStreamSkip(stream, dataOffset - AU_HEADER_SIZE))
 
199
  {
 
200
    return AL_FALSE;
 
201
  }
 
202
 
 
203
  switch (encoding)
 
204
  {
 
205
  case AU_ULAW_8:
 
206
    bitsPerSample = 16;
 
207
    codec = _alutCodecULaw;
 
208
    break;
 
209
  case AU_PCM_8:
 
210
    bitsPerSample = 8;
 
211
    codec = _alutCodecPCM8s;
 
212
    break;
 
213
  case AU_PCM_16:
 
214
    bitsPerSample = 16;
 
215
    codec = (endianess() == BigEndian) ? _alutCodecLinear : _alutCodecPCM16;
 
216
    break;
 
217
  case AU_ALAW_8:
 
218
    bitsPerSample = 16;
 
219
    codec = _alutCodecALaw;
 
220
    break;
 
221
  default:
 
222
    _alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE);
 
223
    return AL_FALSE;
 
224
  }
 
225
 
 
226
  data = _alutInputStreamRead(stream, length);
 
227
  if (data == NULL)
 
228
  {
 
229
    return NULL;
 
230
  }
 
231
  return codec(data, length, numChannels, bitsPerSample, (ALfloat) sampleFrequency);
 
232
}
 
233
 
 
234
static BufferData *loadRawFile(InputStream * stream)
 
235
{
 
236
  size_t length = _alutInputStreamGetRemainingLength(stream);
 
237
  ALvoid *data = _alutInputStreamRead(stream, length);
 
238
 
 
239
  if (data == NULL)
 
240
  {
 
241
    return NULL;
 
242
  }
 
243
  /* Guesses */
 
244
  return _alutCodecLinear(data, length, 1, 8, 8000);
 
245
}
 
246
 
 
247
static BufferData *loadFile(InputStream * stream)
 
248
{
 
249
  const char *fileName;
 
250
  Int32BigEndian magic;
 
251
 
 
252
  /* Raw files have no magic number - so use the fileName extension */
 
253
 
 
254
  fileName = _alutInputStreamGetFileName(stream);
 
255
  if (fileName != NULL && hasSuffixIgnoringCase(fileName, ".raw"))
 
256
  {
 
257
    return loadRawFile(stream);
 
258
  }
 
259
 
 
260
  /* For other file formats, read the quasi-standard four byte magic number */
 
261
  if (!_alutInputStreamReadInt32BE(stream, &magic))
 
262
  {
 
263
    return AL_FALSE;
 
264
  }
 
265
 
 
266
  /* Magic number 'RIFF' == Microsoft '.wav' format */
 
267
  if (magic == 0x52494646)
 
268
  {
 
269
    return loadWavFile(stream);
 
270
  }
 
271
 
 
272
  /* Magic number '.snd' == Sun & Next's '.au' format */
 
273
  if (magic == 0x2E736E64)
 
274
  {
 
275
    return loadAUFile(stream);
 
276
  }
 
277
 
 
278
  _alutSetError(ALUT_ERROR_UNSUPPORTED_FILE_TYPE);
 
279
  return AL_FALSE;
 
280
}
 
281
 
 
282
ALuint _alutCreateBufferFromInputStream(InputStream * stream)
 
283
{
 
284
  BufferData *bufferData;
 
285
  ALuint buffer;
 
286
 
 
287
  if (stream == NULL)
 
288
  {
 
289
    return AL_NONE;
 
290
  }
 
291
 
 
292
  bufferData = loadFile(stream);
 
293
  _alutInputStreamDestroy(stream);
 
294
  if (bufferData == NULL)
 
295
  {
 
296
    return AL_NONE;
 
297
  }
 
298
 
 
299
  buffer = _alutPassBufferData(bufferData);
 
300
  _alutBufferDataDestroy(bufferData);
 
301
 
 
302
  return buffer;
 
303
}
 
304
 
 
305
ALuint alutCreateBufferFromFile(const char *fileName)
 
306
{
 
307
  InputStream *stream;
 
308
 
 
309
  if (!_alutSanityCheck())
 
310
  {
 
311
    return AL_NONE;
 
312
  }
 
313
  stream = _alutInputStreamConstructFromFile(fileName);
 
314
  return _alutCreateBufferFromInputStream(stream);
 
315
}
 
316
 
 
317
ALuint alutCreateBufferFromFileImage(const ALvoid * data, ALsizei length)
 
318
{
 
319
  InputStream *stream;
 
320
 
 
321
  if (!_alutSanityCheck())
 
322
  {
 
323
    return AL_NONE;
 
324
  }
 
325
  stream = _alutInputStreamConstructFromMemory(data, length);
 
326
  return _alutCreateBufferFromInputStream(stream);
 
327
}
 
328
 
 
329
void *_alutLoadMemoryFromInputStream(InputStream * stream, ALenum * format, ALsizei * size, ALfloat * frequency)
 
330
{
 
331
  BufferData *bufferData;
 
332
  ALenum fmt;
 
333
  void *data;
 
334
 
 
335
  if (stream == NULL)
 
336
  {
 
337
    return NULL;
 
338
  }
 
339
 
 
340
  bufferData = loadFile(stream);
 
341
  if (bufferData == NULL)
 
342
  {
 
343
    _alutInputStreamDestroy(stream);
 
344
    return NULL;
 
345
  }
 
346
  _alutInputStreamDestroy(stream);
 
347
 
 
348
  if (!_alutGetFormat(bufferData, &fmt))
 
349
  {
 
350
    _alutBufferDataDestroy(bufferData);
 
351
    return NULL;
 
352
  }
 
353
 
 
354
  if (size != NULL)
 
355
  {
 
356
    *size = (ALsizei) _alutBufferDataGetLength(bufferData);
 
357
  }
 
358
 
 
359
  if (format != NULL)
 
360
  {
 
361
    *format = fmt;
 
362
  }
 
363
 
 
364
  if (frequency != NULL)
 
365
  {
 
366
    *frequency = _alutBufferDataGetSampleFrequency(bufferData);
 
367
  }
 
368
 
 
369
  data = _alutBufferDataGetData(bufferData);
 
370
  _alutBufferDataDetachData(bufferData);
 
371
  _alutBufferDataDestroy(bufferData);
 
372
  return data;
 
373
}
 
374
 
 
375
ALvoid *alutLoadMemoryFromFile(const char *fileName, ALenum * format, ALsizei * size, ALfloat * frequency)
 
376
{
 
377
  InputStream *stream;
 
378
 
 
379
  if (!_alutSanityCheck())
 
380
  {
 
381
    return NULL;
 
382
  }
 
383
  stream = _alutInputStreamConstructFromFile(fileName);
 
384
  return _alutLoadMemoryFromInputStream(stream, format, size, frequency);
 
385
}
 
386
 
 
387
ALvoid *alutLoadMemoryFromFileImage(const ALvoid * data, ALsizei length, ALenum * format, ALsizei * size, ALfloat * frequency)
 
388
{
 
389
  InputStream *stream;
 
390
 
 
391
  if (!_alutSanityCheck())
 
392
  {
 
393
    return NULL;
 
394
  }
 
395
  stream = _alutInputStreamConstructFromMemory(data, length);
 
396
  return _alutLoadMemoryFromInputStream(stream, format, size, frequency);
 
397
}
 
398
 
 
399
/*
 
400
  Yukky backwards compatibility crap.
 
401
*/
 
402
 
 
403
void alutLoadWAVFile(ALbyte * fileName, ALenum * format, void **data, ALsizei * size, ALsizei * frequency
 
404
#if !defined(__APPLE__)
 
405
                     , ALboolean * loop
 
406
#endif
 
407
  )
 
408
{
 
409
  InputStream *stream;
 
410
  ALfloat freq;
 
411
 
 
412
  /* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
 
413
 
 
414
  stream = _alutInputStreamConstructFromFile(fileName);
 
415
  *data = _alutLoadMemoryFromInputStream(stream, format, size, &freq);
 
416
  if (*data == NULL)
 
417
  {
 
418
    return;
 
419
  }
 
420
 
 
421
  if (frequency)
 
422
  {
 
423
    *frequency = (ALsizei) freq;
 
424
  }
 
425
 
 
426
#if !defined(__APPLE__)
 
427
  if (loop)
 
428
  {
 
429
    *loop = AL_FALSE;
 
430
  }
 
431
#endif
 
432
}
 
433
 
 
434
void alutLoadWAVMemory(ALbyte * buffer, ALenum * format, void **data, ALsizei * size, ALsizei * frequency
 
435
#if !defined(__APPLE__)
 
436
                       , ALboolean * loop
 
437
#endif
 
438
  )
 
439
{
 
440
  InputStream *stream;
 
441
  ALfloat freq;
 
442
 
 
443
  /* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
 
444
 
 
445
  /* ToDo: Can we do something less insane than passing 0x7FFFFFFF? */
 
446
  stream = _alutInputStreamConstructFromMemory(buffer, 0x7FFFFFFF);
 
447
  _alutLoadMemoryFromInputStream(stream, format, size, &freq);
 
448
  if (*data == NULL)
 
449
  {
 
450
    return;
 
451
  }
 
452
 
 
453
  if (frequency)
 
454
  {
 
455
    *frequency = (ALsizei) freq;
 
456
  }
 
457
 
 
458
#if !defined(__APPLE__)
 
459
  if (loop)
 
460
  {
 
461
    *loop = AL_FALSE;
 
462
  }
 
463
#endif
 
464
}
 
465
 
 
466
void alutUnloadWAV(ALenum UNUSED(format), ALvoid * data, ALsizei UNUSED(size), ALsizei UNUSED(frequency))
 
467
{
 
468
  /* Don't do an _alutSanityCheck () because it's not required in ALUT 0.x.x */
 
469
 
 
470
  free(data);
 
471
}
 
472
 
 
473
const char *alutGetMIMETypes(ALenum loader)
 
474
{
 
475
  if (!_alutSanityCheck())
 
476
  {
 
477
    return NULL;
 
478
  }
 
479
 
 
480
  /* We do not distinguish the loaders yet... */
 
481
  switch (loader)
 
482
  {
 
483
  case ALUT_LOADER_BUFFER:
 
484
    return "audio/basic,audio/x-raw,audio/x-wav";
 
485
 
 
486
  case ALUT_LOADER_MEMORY:
 
487
    return "audio/basic,audio/x-raw,audio/x-wav";
 
488
 
 
489
  default:
 
490
    _alutSetError(ALUT_ERROR_INVALID_ENUM);
 
491
    return NULL;
 
492
  }
 
493
}