20 static int16_t mulaw_table[256] = {
21 -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
22 -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
23 -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
24 -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
25 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
26 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
27 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
28 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
29 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
30 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
31 -876, -844, -812, -780, -748, -716, -684, -652,
32 -620, -588, -556, -524, -492, -460, -428, -396,
33 -372, -356, -340, -324, -308, -292, -276, -260,
34 -244, -228, -212, -196, -180, -164, -148, -132,
35 -120, -112, -104, -96, -88, -80, -72, -64,
36 -56, -48, -40, -32, -24, -16, -8, -1,
37 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
38 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
39 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
40 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
41 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
42 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
43 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
44 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
45 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
46 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
47 876, 844, 812, 780, 748, 716, 684, 652,
48 620, 588, 556, 524, 492, 460, 428, 396,
49 372, 356, 340, 324, 308, 292, 276, 260,
50 244, 228, 212, 196, 180, 164, 148, 132,
51 120, 112, 104, 96, 88, 80, 72, 64,
52 56, 48, 40, 32, 24, 16, 8, 0
55 static int16_t alaw_table[256] = {
56 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
57 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
58 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
59 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
60 -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
61 -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
62 -11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
63 -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
64 -344, -328, -376, -360, -280, -264, -312, -296,
65 -472, -456, -504, -488, -408, -392, -440, -424,
66 -88, -72, -120, -104, -24, -8, -56, -40,
67 -216, -200, -248, -232, -152, -136, -184, -168,
68 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
69 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
70 -688, -656, -752, -720, -560, -528, -624, -592,
71 -944, -912, -1008, -976, -816, -784, -880, -848,
72 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
73 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
74 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
75 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
76 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
77 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
78 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
79 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
80 344, 328, 376, 360, 280, 264, 312, 296,
81 472, 456, 504, 488, 408, 392, 440, 424,
82 88, 72, 120, 104, 24, 8, 56, 40,
83 216, 200, 248, 232, 152, 136, 184, 168,
84 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
85 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
86 688, 656, 752, 720, 560, 528, 624, 592,
87 944, 912, 1008, 976, 816, 784, 880, 848
101 _reader(stream, false),
106 nassertv(stream !=
nullptr);
109 unsigned char magic[4];
110 if (_reader.
extract_bytes(magic, 4) != 4 || memcmp(magic,
"RIFF", 4) != 0) {
112 <<
".wav file is not a valid RIFF file.\n";
116 unsigned int chunk_size = _reader.
get_uint32();
118 if (_reader.
extract_bytes(magic, 4) != 4 || memcmp(magic,
"WAVE", 4) != 0) {
120 <<
".wav file is a RIFF file but does not start with a WAVE chunk.\n";
125 bool have_fmt =
false, have_data =
false;
126 unsigned int bytes_read = 4;
128 while ((!have_fmt || !have_data) && _stream->good() && (bytes_read + 8) < chunk_size) {
131 unsigned int subchunk_size = _reader.
get_uint32();
133 if (memcmp(magic,
"fmt ", 4) == 0) {
135 nassertv(subchunk_size >= 16);
148 bps = (bps + 7) & 0xfff8;
151 unsigned int read_bytes = 16;
154 if (_format == F_extensible) {
155 unsigned short ext_size = _reader.
get_uint16();
169 if (bps != 8 && bps != 16 && bps != 24 && bps != 32 && bps != 64) {
171 <<
"Unsupported number of bits per sample for PCM storage: " << bps <<
"\n";
177 if (bps != 32 && bps != 64) {
179 <<
"Unsupported number of bits per sample for float storage: " << bps <<
"\n";
188 <<
".wav file with A-law or mu-law compression must specify 8 bits per sample, not " << bps <<
".\n";
195 <<
"Unsupported .wav format " << _format <<
". Only PCM, float, A-law and mu-law encodings are supported.\n";
199 _bytes_per_sample = bps / 8;
202 if (subchunk_size > read_bytes) {
203 _reader.
skip_bytes(subchunk_size - read_bytes);
206 }
else if (memcmp(magic,
"data", 4) == 0) {
210 <<
".wav file specifies 'data' chunk before 'fmt ' chunk.\n";
216 _data_start = stream->tellg();
217 _data_size = subchunk_size;
226 bytes_read += subchunk_size + 8;
230 if (_stream->eof()) {
232 <<
"Reached end of file while reading .wav file header.\n";
234 }
else if (!_stream->good()) {
236 <<
"Stream error while reading .wav file header.\n";
242 <<
".wav file did not specify a 'fmt ' chunk.\n";
248 <<
".wav file did not specify a 'data' chunk.\n";
257 _can_seek_fast =
true;
259 if (_block_align != _audio_channels * _bytes_per_sample) {
261 <<
".wav file specified an unexpected block alignment of " << _block_align
262 <<
", expected " << (_audio_channels * _bytes_per_sample) <<
".\n";
263 _block_align = _audio_channels * _bytes_per_sample;
266 if (_byte_rate != _audio_rate * _block_align) {
268 <<
".wav file specified an unexpected byte rate of " << _byte_rate
269 <<
", expected " << (_audio_rate * _block_align) <<
".\n";
270 _byte_rate = _audio_rate * _block_align;
273 _length = _data_size / _byte_rate;
282 if (_stream !=
nullptr) {
294 t = std::max(t, 0.0);
295 std::streampos pos = _data_start + (std::streampos) std::min((
size_t) (t * _byte_rate), _data_size);
297 if (_can_seek_fast) {
299 if (_stream->tellg() != pos) {
301 _can_seek_fast =
false;
305 if (!_can_seek_fast) {
306 std::streampos current = _stream->tellg();
312 }
else if (pos < current) {
317 _data_pos = _stream->tellg() - _data_start;
318 _last_seek = _data_pos / _byte_rate;
329 int desired = n * _audio_channels;
330 int read_samples = std::min(desired, ((
int) (_data_size - _data_pos)) / _bytes_per_sample);
339 switch (_bytes_per_sample) {
343 data[i] = (_reader.
get_uint8() - 128) * 258;
363 const int32_t scale_factor = 0x7fffffff / 0x7fff;
366 data[i] = _reader.
get_int32() / scale_factor;
372 const int64_t scale_factor = 0x7fffffffffffffffLL / 0x7fffLL;
375 data[i] = _reader.
get_int64() / scale_factor;
387 switch (_bytes_per_sample) {
390 data[i] = (int16_t) (_reader.
get_float32() * 0x7fff);
396 data[i] = (int16_t) (_reader.
get_float64() * 0x7fff);
407 data[i] = alaw_table[_reader.
get_uint8()];
413 data[i] = mulaw_table[_reader.
get_uint8()];
426 _data_pos = _stream->tellg() - _data_start;
WavAudioCursor(WavAudio *src, std::istream *stream)
Reads the .wav header from the indicated stream.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
int64_t get_int64()
Extracts a signed 64-bit integer.
int32_t get_int32()
Extracts a signed 32-bit integer.
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.
virtual void read_samples(int n, int16_t *data)
Read audio samples from the stream.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual ~WavAudioCursor()
xxx
size_t extract_bytes(unsigned char *into, size_t size)
Extracts the indicated number of bytes in the stream into the given character buffer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A native PCM .wav loader.
int16_t get_int16()
Extracts a signed 16-bit integer.
TypeHandle is the identifier used to differentiate C++ class types.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the stream.