28 VorbisAudioCursor(VorbisAudio *src, istream *stream) :
33 nassertv(stream !=
nullptr);
34 nassertv(stream->good());
37 ov_callbacks callbacks;
38 callbacks.read_func = &cb_read_func;
39 callbacks.close_func = &cb_close_func;
40 callbacks.tell_func = &cb_tell_func;
42 if (vorbis_enable_seek) {
43 callbacks.seek_func = &cb_seek_func;
45 callbacks.seek_func =
nullptr;
48 if (ov_open_callbacks((
void*) stream, &_ov,
nullptr, 0, callbacks) != 0) {
50 <<
"Failed to read Ogg Vorbis file.\n";
54 double time_total = ov_time_total(&_ov, -1);
55 if (time_total != OV_EINVAL) {
59 vorbis_info *vi = ov_info(&_ov, -1);
60 _audio_channels = vi->channels;
61 _audio_rate = vi->rate;
63 _can_seek = vorbis_enable_seek && (ov_seekable(&_ov) != 0);
64 _can_seek_fast = _can_seek;
73 ~VorbisAudioCursor() {
81 void VorbisAudioCursor::
83 if (!vorbis_enable_seek) {
90 if (vorbis_seek_lap) {
91 if (ov_time_seek_lap(&_ov, t) != 0) {
93 <<
"Seek failed. Ogg Vorbis stream may not be seekable.\n";
97 if (ov_time_seek(&_ov, t) != 0) {
99 <<
"Seek failed. Ogg Vorbis stream may not be seekable.\n";
104 _last_seek = ov_time_tell(&_ov);
113 void VorbisAudioCursor::
114 read_samples(
int n, int16_t *data) {
115 int desired = n * _audio_channels;
117 char *buffer = (
char*) data;
118 int length = desired * 2;
125 long read_bytes = ov_read(&_ov, buffer, length, 0, 2, 1, &
bitstream);
126 if (read_bytes > 0) {
127 buffer += read_bytes;
128 length -= read_bytes;
136 vorbis_info *vi = ov_info(&_ov, -1);
137 if (vi->channels != _audio_channels || vi->rate != _audio_rate) {
139 <<
"Ogg Vorbis file has non-matching bitstreams!\n";
142 _audio_channels = vi->channels;
143 _audio_rate = vi->rate;
153 memset(buffer, 0, length);
154 n -= length / 2 / _audio_channels;
164 size_t VorbisAudioCursor::
165 cb_read_func(
void *ptr,
size_t size,
size_t nmemb,
void *datasource) {
166 istream *stream = (istream*) datasource;
167 nassertr(stream !=
nullptr, -1);
169 stream->read((
char *)ptr, size * nmemb);
176 return stream->gcount();
183 int VorbisAudioCursor::
184 cb_seek_func(
void *datasource, ogg_int64_t offset,
int whence) {
185 if (!vorbis_enable_seek) {
189 istream *stream = (istream*) datasource;
190 nassertr(stream !=
nullptr, -1);
194 stream->seekg(offset, std::ios::beg);
198 stream->seekg(offset, std::ios::cur);
202 stream->seekg(offset, std::ios::end);
207 <<
"Illegal parameter to seek in VorbisAudioCursor::cb_seek_func\n";
211 if (stream->fail()) {
214 <<
"Failure to seek to byte " << offset;
218 movies_cat.error(
false)
219 <<
" from current location!\n";
223 movies_cat.error(
false)
224 <<
" from end of file!\n";
228 movies_cat.error(
false) <<
"!\n";
241 int VorbisAudioCursor::
242 cb_close_func(
void *datasource) {
243 istream *stream = (istream*) datasource;
244 nassertr(stream !=
nullptr, -1);
257 long VorbisAudioCursor::
258 cb_tell_func(
void *datasource) {
259 istream *stream = (istream*) datasource;
260 nassertr(stream !=
nullptr, -1);
262 return stream->tellg();
265 #endif // HAVE_VORBIS 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.
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
A MovieAudio is actually any source that provides a sequence of audio samples.
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.
TypeHandle is the identifier used to differentiate C++ class types.