32VorbisAudioCursor(VorbisAudio *src,
istream *stream) :
37 nassertv(stream !=
nullptr);
38 nassertv(stream->good());
41 ov_callbacks callbacks;
42 callbacks.read_func = &cb_read_func;
43 callbacks.close_func = &cb_close_func;
44 callbacks.tell_func = &cb_tell_func;
46 if (vorbis_enable_seek) {
47 callbacks.seek_func = &cb_seek_func;
49 callbacks.seek_func =
nullptr;
52 if (ov_open_callbacks((
void*) stream, &_ov,
nullptr, 0, callbacks) != 0) {
54 <<
"Failed to read Ogg Vorbis file.\n";
58 double time_total = ov_time_total(&_ov, -1);
59 if (time_total != OV_EINVAL) {
63 vorbis_info *vi = ov_info(&_ov, -1);
64 _audio_channels = vi->channels;
65 _audio_rate = vi->rate;
67 _can_seek = vorbis_enable_seek && (ov_seekable(&_ov) != 0);
68 _can_seek_fast = _can_seek;
85void VorbisAudioCursor::
87 if (!vorbis_enable_seek) {
95 if (vorbis_seek_lap) {
96 result = ov_time_seek_lap(&_ov, t);
98 result = ov_time_seek(&_ov, t);
104 if (result == OV_ENOSEEK && t == 0.0) {
105 std::istream *stream = (std::istream *)_ov.datasource;
107 if (stream->rdbuf()->pubseekpos(0, std::ios::in) == (std::streampos)0) {
110 ov_callbacks callbacks = _ov.callbacks;
111 _ov.datasource =
nullptr;
114 if (ov_open_callbacks((
void *)stream, &_ov,
nullptr, 0, callbacks) != 0) {
116 <<
"Failed to reopen Ogg Vorbis file to seek to beginning.\n";
121 vorbis_info *vi = ov_info(&_ov, -1);
122 _audio_channels = vi->channels;
123 _audio_rate = vi->rate;
132 <<
"Seek failed. Ogg Vorbis stream may not be seekable.\n";
135 _last_seek = ov_time_tell(&_ov);
144void VorbisAudioCursor::
145read_samples(
int n, int16_t *data) {
146 int desired = n * _audio_channels;
148 char *buffer = (
char*) data;
149 int length = desired * 2;
156 long read_bytes = ov_read(&_ov, buffer, length, 0, 2, 1, &bitstream);
157 if (read_bytes > 0) {
158 buffer += read_bytes;
159 length -= read_bytes;
164 if (_bitstream != bitstream) {
167 vorbis_info *vi = ov_info(&_ov, -1);
168 if (vi->channels != _audio_channels || vi->rate != _audio_rate) {
170 <<
"Ogg Vorbis file has non-matching bitstreams!\n";
173 _audio_channels = vi->channels;
174 _audio_rate = vi->rate;
178 _bitstream = bitstream;
184 memset(buffer, 0, length);
185 n -= length / 2 / _audio_channels;
195size_t VorbisAudioCursor::
196cb_read_func(
void *ptr,
size_t size,
size_t nmemb,
void *datasource) {
198 nassertr(stream !=
nullptr, -1);
200 stream->read((
char *)ptr, size * nmemb);
207 return stream->gcount();
214int VorbisAudioCursor::
215cb_seek_func(
void *datasource, ogg_int64_t offset,
int whence) {
216 if (!vorbis_enable_seek) {
221 nassertr(stream !=
nullptr, -1);
225 stream->seekg(offset, std::ios::beg);
232 std::streambuf *buf = stream->rdbuf();
233 std::streampos pos = buf->pubseekoff(0, std::ios::cur, std::ios::in);
237 if (buf->pubseekoff(0, std::ios::end, std::ios::in) >= 0) {
239 buf->pubseekpos(pos, std::ios::in);
245 stream->seekg(offset, std::ios::cur);
249 stream->seekg(offset, std::ios::end);
254 <<
"Illegal parameter to seek in VorbisAudioCursor::cb_seek_func\n";
258 if (stream->fail()) {
261 <<
"Failure to seek to byte " << offset;
265 movies_cat.error(
false)
266 <<
" from current location!\n";
270 movies_cat.error(
false)
271 <<
" from end of file!\n";
275 movies_cat.error(
false) <<
"!\n";
288int VorbisAudioCursor::
289cb_close_func(
void *datasource) {
291 nassertr(stream !=
nullptr, -1);
294 vfs->close_read_file(stream);
304long VorbisAudioCursor::
305cb_tell_func(
void *datasource) {
307 nassertr(stream !=
nullptr, -1);
309 return stream->tellg();
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 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.