15 #include "vorbisAudioCursor.h"
16 #include "virtualFileSystem.h"
30 VorbisAudioCursor(VorbisAudio *src, istream *stream) :
35 nassertv(stream != NULL);
36 nassertv(stream->good());
39 ov_callbacks callbacks;
40 callbacks.read_func = &cb_read_func;
41 callbacks.close_func = &cb_close_func;
42 callbacks.tell_func = &cb_tell_func;
44 if (vorbis_enable_seek) {
45 callbacks.seek_func = &cb_seek_func;
47 callbacks.seek_func = NULL;
50 if (ov_open_callbacks((
void*) stream, &_ov, NULL, 0, callbacks) != 0) {
52 <<
"Failed to read Ogg Vorbis file.\n";
56 double time_total = ov_time_total(&_ov, -1);
57 if (time_total != OV_EINVAL) {
61 vorbis_info *vi = ov_info(&_ov, -1);
62 _audio_channels = vi->channels;
63 _audio_rate = vi->rate;
65 _can_seek = vorbis_enable_seek && (ov_seekable(&_ov) != 0);
66 _can_seek_fast = _can_seek;
77 ~VorbisAudioCursor() {
88 void VorbisAudioCursor::
90 if (!vorbis_enable_seek) {
97 if (vorbis_seek_lap) {
98 if (ov_time_seek_lap(&_ov, t) != 0) {
100 <<
"Seek failed. Ogg Vorbis stream may not be seekable.\n";
104 if (ov_time_seek(&_ov, t) != 0) {
106 <<
"Seek failed. Ogg Vorbis stream may not be seekable.\n";
111 _last_seek = ov_time_tell(&_ov);
123 void VorbisAudioCursor::
124 read_samples(
int n, PN_int16 *data) {
125 int desired = n * _audio_channels;
127 char *buffer = (
char*) data;
128 int length = desired * 2;
135 long read_bytes = ov_read(&_ov, buffer, length, 0, 2, 1, &bitstream);
136 if (read_bytes > 0) {
137 buffer += read_bytes;
138 length -= read_bytes;
143 if (_bitstream != bitstream) {
146 vorbis_info *vi = ov_info(&_ov, -1);
147 if (vi->channels != _audio_channels || vi->rate != _audio_rate) {
149 <<
"Ogg Vorbis file has non-matching bitstreams!\n";
152 _audio_channels = vi->channels;
153 _audio_rate = vi->rate;
157 _bitstream = bitstream;
163 memset(buffer, 0, length);
164 n -= length / 2 / _audio_channels;
176 size_t VorbisAudioCursor::
177 cb_read_func(
void *ptr,
size_t size,
size_t nmemb,
void *datasource) {
178 istream *stream = (istream*) datasource;
179 nassertr(stream != NULL, -1);
181 stream->read((
char *)ptr, size * nmemb);
188 return stream->gcount();
197 int VorbisAudioCursor::
198 cb_seek_func(
void *datasource, ogg_int64_t offset,
int whence) {
199 if (!vorbis_enable_seek) {
203 istream *stream = (istream*) datasource;
204 nassertr(stream != NULL, -1);
208 stream->seekg(offset, ios::beg);
212 stream->seekg(offset, ios::cur);
216 stream->seekg(offset, ios::end);
221 <<
"Illegal parameter to seek in VorbisAudioCursor::cb_seek_func\n";
225 if (stream->fail()) {
229 <<
"Failure to seek to byte " << offset;
233 movies_cat.error(
false)
234 <<
" from current location!\n";
238 movies_cat.error(
false)
239 <<
" from end of file!\n";
243 movies_cat.error(
false) <<
"!\n";
258 int VorbisAudioCursor::
259 cb_close_func(
void *datasource) {
260 istream *stream = (istream*) datasource;
261 nassertr(stream != NULL, -1);
276 long VorbisAudioCursor::
277 cb_tell_func(
void *datasource) {
278 istream *stream = (istream*) datasource;
279 nassertr(stream != NULL, -1);
281 return stream->tellg();
284 #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(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.
TypeHandle is the identifier used to differentiate C++ class types.