15 #include "wavAudioCursor.h"
16 #include "config_movies.h"
17 #include "virtualFileSystem.h"
21 static PN_int16 mulaw_table[256] = {
22 -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
23 -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
24 -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
25 -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
26 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
27 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
28 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
29 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
30 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
31 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
32 -876, -844, -812, -780, -748, -716, -684, -652,
33 -620, -588, -556, -524, -492, -460, -428, -396,
34 -372, -356, -340, -324, -308, -292, -276, -260,
35 -244, -228, -212, -196, -180, -164, -148, -132,
36 -120, -112, -104, -96, -88, -80, -72, -64,
37 -56, -48, -40, -32, -24, -16, -8, -1,
38 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
39 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
40 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
41 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
42 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
43 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
44 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
45 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
46 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
47 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
48 876, 844, 812, 780, 748, 716, 684, 652,
49 620, 588, 556, 524, 492, 460, 428, 396,
50 372, 356, 340, 324, 308, 292, 276, 260,
51 244, 228, 212, 196, 180, 164, 148, 132,
52 120, 112, 104, 96, 88, 80, 72, 64,
53 56, 48, 40, 32, 24, 16, 8, 0
56 static PN_int16 alaw_table[256] = {
57 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
58 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
59 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
60 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
61 -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
62 -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
63 -11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
64 -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
65 -344, -328, -376, -360, -280, -264, -312, -296,
66 -472, -456, -504, -488, -408, -392, -440, -424,
67 -88, -72, -120, -104, -24, -8, -56, -40,
68 -216, -200, -248, -232, -152, -136, -184, -168,
69 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
70 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
71 -688, -656, -752, -720, -560, -528, -624, -592,
72 -944, -912, -1008, -976, -816, -784, -880, -848,
73 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
74 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
75 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
76 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
77 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
78 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
79 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
80 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
81 344, 328, 376, 360, 280, 264, 312, 296,
82 472, 456, 504, 488, 408, 392, 440, 424,
83 88, 72, 120, 104, 24, 8, 56, 40,
84 216, 200, 248, 232, 152, 136, 184, 168,
85 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
86 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
87 688, 656, 752, 720, 560, 528, 624, 592,
88 944, 912, 1008, 976, 816, 784, 880, 848
105 _reader(stream, false),
110 nassertv(stream != NULL);
115 <<
".wav file is not a valid RIFF file.\n";
119 unsigned int chunk_size = _reader.
get_uint32();
123 <<
".wav file is a RIFF file but does not start with a WAVE chunk.\n";
128 bool have_fmt =
false, have_data =
false;
129 unsigned int bytes_read = 4;
131 while ((!have_fmt || !have_data) && _stream->good() && (bytes_read + 8) < chunk_size) {
134 unsigned int subchunk_size = _reader.
get_uint32();
136 if (subchunk_id ==
"fmt ") {
138 nassertv(subchunk_size >= 16);
151 bps = (bps + 7) & 0xfff8;
154 unsigned int read_bytes = 16;
157 if (_format == F_extensible) {
158 unsigned short ext_size = _reader.
get_uint16();
172 if (bps != 8 && bps != 16 && bps != 24 && bps != 32 && bps != 64) {
174 <<
"Unsupported number of bits per sample for PCM storage: " << bps <<
"\n";
180 if (bps != 32 && bps != 64) {
182 <<
"Unsupported number of bits per sample for float storage: " << bps <<
"\n";
191 <<
".wav file with A-law or mu-law compression must specify 8 bits per sample, not " << bps <<
".\n";
198 <<
"Unsupported .wav format " << _format <<
". Only PCM, float, A-law and mu-law encodings are supported.\n";
202 _bytes_per_sample = bps / 8;
205 if (subchunk_size > read_bytes) {
206 _reader.
skip_bytes(subchunk_size - read_bytes);
209 }
else if (subchunk_id ==
"data") {
213 <<
".wav file specifies 'data' chunk before 'fmt ' chunk.\n";
219 _data_start = stream->tellg();
220 _data_size = subchunk_size;
229 bytes_read += subchunk_size + 8;
233 if (_stream->eof()) {
235 <<
"Reached end of file while reading .wav file header.\n";
237 }
else if (!_stream->good()) {
239 <<
"Stream error while reading .wav file header.\n";
245 <<
".wav file did not specify a 'fmt ' chunk.\n";
251 <<
".wav file did not specify a 'data' chunk.\n";
260 _can_seek_fast =
true;
262 if (_block_align != _audio_channels * _bytes_per_sample) {
264 <<
".wav file specified an unexpected block alignment of " << _block_align
265 <<
", expected " << (_audio_channels * _bytes_per_sample) <<
".\n";
266 _block_align = _audio_channels * _bytes_per_sample;
269 if (_byte_rate != _audio_rate * _block_align) {
271 <<
".wav file specified an unexpected byte rate of " << _byte_rate
272 <<
", expected " << (_audio_rate * _block_align) <<
".\n";
273 _byte_rate = _audio_rate * _block_align;
276 _length = _data_size / _byte_rate;
287 if (_stream != NULL) {
303 streampos pos = _data_start + (streampos) min((
size_t) (t * _byte_rate), _data_size);
305 if (_can_seek_fast) {
307 if (_stream->tellg() != pos) {
310 _can_seek_fast =
false;
314 if (!_can_seek_fast) {
315 streampos current = _stream->tellg();
321 }
else if (pos < current) {
327 _data_pos = _stream->tellg() - _data_start;
328 _last_seek = _data_pos / _byte_rate;
342 int desired = n * _audio_channels;
343 int read_samples = min(desired, ((
int) (_data_size - _data_pos)) / _bytes_per_sample);
345 if (read_samples <= 0) {
352 switch (_bytes_per_sample) {
356 data[i] = (_reader.
get_uint8() - 128) * 258;
362 read_samples = _reader.
extract_bytes((
unsigned char*) data, read_samples * 2) / 2;
376 const PN_int32 scale_factor = 0x7fffffff / 0x7fff;
379 data[i] = _reader.
get_int32() / scale_factor;
385 const PN_int64 scale_factor = 0x7fffffffffffffffLL / 0x7fffLL;
388 data[i] = _reader.
get_int64() / scale_factor;
400 switch (_bytes_per_sample) {
403 data[i] = (PN_int16) (_reader.
get_float32() * 0x7fff);
409 data[i] = (PN_int16) (_reader.
get_float64() * 0x7fff);
420 data[i] = alaw_table[_reader.
get_uint8()];
426 data[i] = mulaw_table[_reader.
get_uint8()];
435 if (read_samples < desired) {
436 memset(data + read_samples, 0, (desired - read_samples) * 2);
439 _data_pos = _stream->tellg() - _data_start;
440 _samples_read += read_samples / _audio_channels;
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
string extract_bytes(size_t size)
Extracts the indicated number of bytes in the stream and returns them as a string.
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
virtual void seek(double offset)
Seeks to a target location.
A MovieAudio is actually any source that provides a sequence of audio samples.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PN_float64 get_float64()
Extracts a 64-bit floating-point number.
float get_float32()
Extracts a 32-bit single-precision floating-point number.
virtual ~WavAudioCursor()
xxx
WavAudioCursor(WavAudio *src, istream *stream)
Reads the .wav header from the indicated stream.
PN_int16 get_int16()
Extracts a signed 16-bit integer.
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
A native PCM .wav loader.
virtual void read_samples(int n, PN_int16 *data)
Read audio samples from the stream.
PN_int32 get_int32()
Extracts a signed 32-bit integer.
TypeHandle is the identifier used to differentiate C++ class types.
PN_int64 get_int64()
Extracts a signed 64-bit integer.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the stream.