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