23 #include <opus/opusfile.h>
31 int cb_read(
void *stream,
unsigned char *ptr,
int nbytes) {
32 istream *in = (istream *)stream;
33 nassertr(in !=
nullptr, -1);
35 in->read((
char *)ptr, nbytes);
45 int cb_seek(
void *stream, opus_int64 offset,
int whence) {
46 if (!opus_enable_seek) {
50 istream *in = (istream *)stream;
51 nassertr(in !=
nullptr, -1);
55 in->seekg(offset, std::ios::beg);
62 std::streambuf *buf = in->rdbuf();
63 std::streampos pos = buf->pubseekoff(0, std::ios::cur, std::ios::in);
67 if (buf->pubseekoff(0, std::ios::end, std::ios::in) >= 0) {
69 buf->pubseekpos(pos, std::ios::in);
75 in->seekg(offset, std::ios::cur);
79 in->seekg(offset, std::ios::end);
84 <<
"Illegal parameter to seek in cb_seek\n";
90 <<
"Failure to seek to byte " << offset;
94 movies_cat.error(
false)
95 <<
" from current location!\n";
99 movies_cat.error(
false)
100 <<
" from end of file!\n";
104 movies_cat.error(
false) <<
"!\n";
113 opus_int64 cb_tell(
void *stream) {
114 istream *in = (istream *)stream;
115 nassertr(in !=
nullptr, -1);
120 int cb_close(
void *stream) {
121 istream *in = (istream *)stream;
122 nassertr(in !=
nullptr, EOF);
129 static const OpusFileCallbacks callbacks = {cb_read, cb_seek, cb_tell, cb_close};
138 OpusAudioCursor(OpusAudio *src, istream *stream) :
143 nassertv(stream !=
nullptr);
144 nassertv(stream->good());
147 _op = op_open_callbacks((
void *)stream, &callbacks,
nullptr, 0, &error);
148 if (_op ==
nullptr) {
150 <<
"Failed to read Opus file (error code " << error <<
").\n";
154 ogg_int64_t samples = op_pcm_total(_op, -1);
155 if (samples != OP_EINVAL) {
157 _length = (double)samples / 48000.0;
160 _audio_channels = op_channel_count(_op, -1);
163 _can_seek = opus_enable_seek && op_seekable(_op);
164 _can_seek_fast = _can_seek;
174 if (_op !=
nullptr) {
184 void OpusAudioCursor::
186 if (!opus_enable_seek) {
190 t = std::max(t, 0.0);
193 int error = op_pcm_seek(_op, (ogg_int64_t)(t * 48000.0));
196 <<
"Seek failed (error " << error <<
"). Opus stream may not be seekable.\n";
200 _last_seek = op_pcm_tell(_op) / 48000.0;
209 void OpusAudioCursor::
210 read_samples(
int n, int16_t *data) {
211 int16_t *end = data + (n * _audio_channels);
216 int read_samples = op_read(_op, data, end - data, &link);
217 if (read_samples > 0) {
218 data += read_samples * _audio_channels;
219 _samples_read += read_samples;
227 int channels = op_channel_count(_op, link);
228 if (channels != _audio_channels) {
230 <<
"Opus file has inconsistent channel count!\n";
233 _audio_channels = channels;
242 memset(data, 0, (
unsigned char *)end - (
unsigned char *)data);
A MovieAudio is actually any source that provides a sequence of audio samples.
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().
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
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.