Panda3D
movieAudioCursor.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file movieAudioCursor.cxx
10  * @author jyelon
11  * @date 2007-07-02
12  */
13 
14 #include "movieAudioCursor.h"
15 
16 TypeHandle MovieAudioCursor::_type_handle;
17 
18 /**
19  * This constructor returns a null audio stream --- a stream of total silence,
20  * at 8000 samples per second. To get more interesting audio, you need to
21  * construct a subclass of this class.
22  */
25  _source(src),
26  _audio_rate(8000),
27  _audio_channels(1),
28  _length(1.0E10),
29  _can_seek(true),
30  _can_seek_fast(true),
31  _aborted(false),
32  _samples_read(0)
33 {
34 }
35 
36 /**
37  *
38  */
39 MovieAudioCursor::
40 ~MovieAudioCursor() {
41 }
42 
43 /**
44  * Read audio samples from the stream. N is the number of samples you wish to
45  * read. Your buffer must be equal in size to N * channels. Multiple-channel
46  * audio will be interleaved.
47  */
49 read_samples(int n, int16_t *data) {
50 
51  // This is the null implementation, which generates pure silence. Normally,
52  // this method will be overridden by a subclass.
53 
54  if (n <= 0) {
55  return;
56  }
57 
58  int desired = n * _audio_channels;
59  for (int i=0; i<desired; i++) {
60  data[i] = 0;
61  }
62  _samples_read += n;
63 }
64 
65 /**
66  * Read audio samples from the stream into a Datagram. N is the number of
67  * samples you wish to read. Multiple-channel audio will be interleaved.
68  *
69  * This is not particularly efficient, but it may be a convenient way to
70  * manipulate samples in python.
71  */
73 read_samples(int n, Datagram *dg) {
74  int16_t tmp[4096];
75  while (n > 0) {
76  int blocksize = (4096 / _audio_channels);
77  if (blocksize > n) blocksize = n;
78  int words = blocksize * _audio_channels;
79  read_samples(blocksize, tmp);
80  for (int i=0; i<words; i++) {
81  dg->add_int16(tmp[i]);
82  }
83  n -= blocksize;
84  }
85 }
86 
87 /**
88  * Read audio samples from the stream and returns them as a string. The
89  * samples are stored little-endian in the string. N is the number of samples
90  * you wish to read. Multiple-channel audio will be interleaved.
91  *
92  * This is not particularly efficient, but it may be a convenient way to
93  * manipulate samples in python.
94  */
95 std::string MovieAudioCursor::
96 read_samples(int n) {
97  std::ostringstream result;
98  int16_t tmp[4096];
99  while (n > 0) {
100  int blocksize = (4096 / _audio_channels);
101  if (blocksize > n) blocksize = n;
102  int words = blocksize * _audio_channels;
103  read_samples(blocksize, tmp);
104  for (int i=0; i<words; i++) {
105  int16_t word = tmp[i];
106  result.put((char)(word & 255));
107  result.put((char)((word>>8) & 255));
108  }
109  n -= blocksize;
110  }
111  return result.str();
112 }
113 
114 
115 /**
116  * Skips to the specified offset within the file.
117  *
118  * If the movie reports that it cannot seek, then this method can still
119  * advance by reading samples and discarding them. However, to move backward,
120  * can_seek must be true.
121  *
122  * If the movie reports that it can_seek, it doesn't mean that it can do so
123  * quickly. It may have to rewind the movie and then fast forward to the
124  * desired location. Only if can_seek_fast returns true can seek operations
125  * be done in constant time.
126  *
127  * Seeking may not be precise, because AVI files often have inaccurate
128  * indices. After seeking, tell will indicate that the cursor is at the
129  * target location. However, in truth, the data you read may come from a
130  * slightly offset location.
131  */
133 seek(double offset) {
134  _last_seek = offset;
135  _samples_read = 0;
136 }
137 
138 /**
139  * Returns the number of audio samples that are ready to read. This is
140  * primarily relevant for sources like microphones which produce samples at a
141  * fixed rate. If you try to read more samples than are ready, the result
142  * will be silent samples.
143  *
144  * Some audio streams do not have a limit on how fast they can produce
145  * samples. Such streams will always return 0x40000000 as the ready-count.
146  * This may well exceed the length of the audio stream. You therefore need to
147  * check length separately.
148  *
149  * If the aborted flag is set, that means the ready count is no longer being
150  * replenished. For example, a MovieAudioCursor might be reading from an
151  * internet radio station, and it might buffer data to avoid underruns. If it
152  * loses connection to the radio station, it will set the aborted flag to
153  * indicate that the buffer is no longer being replenished. But it is still
154  * ok to read the samples that are in the buffer, at least until they run out.
155  * Once those are gone, there will be no more.
156  *
157  * An audio consumer needs to check the length, the ready status, and the
158  * aborted flag.
159  */
161 ready() const {
162  return 0x40000000;
163 }
void add_int16(int16_t value)
Adds a signed 16-bit integer to the datagram.
Definition: datagram.I:58
void read_samples(int n, Datagram *dg)
Read audio samples from the stream into a Datagram.
MovieAudioCursor(MovieAudio *src)
This constructor returns a null audio stream — a stream of total silence, at 8000 samples per second.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:44
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
virtual int ready() const
Returns the number of audio samples that are ready to read.
virtual void seek(double offset)
Skips to the specified offset within the file.