20static 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
55static 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 std::streambuf *buf = _stream->rdbuf();
299 if (_can_seek_fast) {
300 if (buf->pubseekpos(pos, std::ios::in) != pos) {
302 _can_seek_fast =
false;
307 std::streampos current = buf->pubseekoff(0, std::ios::cur, std::ios::in);
309 if (!_can_seek_fast) {
312 _stream->ignore(pos - current);
315 }
else if (pos < current) {
318 if (buf->pubseekpos(0, std::ios::in) == (std::streampos)0) {
319 if (pos > _data_start && movies_cat.is_info()) {
320 Filename fn = get_source()->get_filename();
323 <<
"; seeking to beginning and skipping " << pos <<
" bytes.\n";
325 _stream->ignore(pos);
329 Filename fn = get_source()->get_filename();
332 <<
"; reopening and skipping " << pos <<
" bytes.\n";
335 std::istream *stream = vfs->
open_read_file(get_source()->get_filename(),
true);
336 if (stream !=
nullptr) {
344 <<
"Unable to reopen " << fn <<
".\n";
351 _data_pos = (size_t)current - _data_start;
352 _last_seek = _data_pos / _byte_rate;
363 int desired = n * _audio_channels;
364 int read_samples = std::min(desired, ((
int) (_data_size - _data_pos)) / _bytes_per_sample);
373 switch (_bytes_per_sample) {
377 data[i] = (_reader.
get_uint8() - 128) * 258;
397 const int32_t scale_factor = 0x7fffffff / 0x7fff;
400 data[i] = _reader.
get_int32() / scale_factor;
406 const int64_t scale_factor = 0x7fffffffffffffffLL / 0x7fffLL;
409 data[i] = _reader.
get_int64() / scale_factor;
421 switch (_bytes_per_sample) {
424 data[i] = (int16_t) (_reader.
get_float32() * 0x7fff);
430 data[i] = (int16_t) (_reader.
get_float64() * 0x7fff);
441 data[i] = alaw_table[_reader.
get_uint8()];
447 data[i] = mulaw_table[_reader.
get_uint8()];
460 _data_pos = _stream->tellg() - _data_start;
The name of a file, such as a texture file or an Egg file.
std::string get_basename() const
Returns the basename part of the filename.
A MovieAudio is actually any source that provides a sequence of audio samples.
A class to read sequential binary data directly from an istream.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
int16_t get_int16()
Extracts a signed 16-bit integer.
float get_float32()
Extracts a 32-bit single-precision floating-point number.
PN_float64 get_float64()
Extracts a 64-bit floating-point number.
int32_t get_int32()
Extracts a signed 32-bit integer.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the stream.
size_t extract_bytes(unsigned char *into, size_t size)
Extracts the indicated number of bytes in the stream into the given character buffer.
int64_t get_int64()
Extracts a signed 64-bit integer.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
TypeHandle is the identifier used to differentiate C++ class types.
A hierarchy of directories and files that appears to be one continuous file system,...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
std::istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read,...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
WavAudioCursor(WavAudio *src, std::istream *stream)
Reads the .wav header from the indicated stream.
virtual void seek(double offset)
Seeks to a target location.
virtual void read_samples(int n, int16_t *data)
Read audio samples from the stream.
virtual ~WavAudioCursor()
xxx
A native PCM .wav loader.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.