00001 // Filename: movieAudioCursor.cxx 00002 // Created by: jyelon (02Jul07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "movieAudioCursor.h" 00016 00017 TypeHandle MovieAudioCursor::_type_handle; 00018 00019 //////////////////////////////////////////////////////////////////// 00020 // Function: MovieAudioCursor::Constructor 00021 // Access: Public 00022 // Description: This constructor returns a null audio stream --- a 00023 // stream of total silence, at 8000 samples per second. 00024 // To get more interesting audio, you need to construct 00025 // a subclass of this class. 00026 //////////////////////////////////////////////////////////////////// 00027 MovieAudioCursor:: 00028 MovieAudioCursor(MovieAudio *src) : 00029 _source(src), 00030 _audio_rate(8000), 00031 _audio_channels(1), 00032 _length(1.0E10), 00033 _can_seek(true), 00034 _can_seek_fast(true), 00035 _aborted(false), 00036 _samples_read(0) 00037 { 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: MovieAudioCursor::Destructor 00042 // Access: Public, Virtual 00043 // Description: 00044 //////////////////////////////////////////////////////////////////// 00045 MovieAudioCursor:: 00046 ~MovieAudioCursor() { 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: MovieAudioCursor::read_samples 00051 // Access: Public, Virtual 00052 // Description: Read audio samples from the stream. N is the 00053 // number of samples you wish to read. Your buffer 00054 // must be equal in size to N * channels. 00055 // Multiple-channel audio will be interleaved. 00056 //////////////////////////////////////////////////////////////////// 00057 void MovieAudioCursor:: 00058 read_samples(int n, PN_int16 *data) { 00059 00060 // This is the null implementation, which generates pure silence. 00061 // Normally, this method will be overridden by a subclass. 00062 00063 if (n <= 0) { 00064 return; 00065 } 00066 00067 int desired = n * _audio_channels; 00068 for (int i=0; i<desired; i++) { 00069 data[i] = 0; 00070 } 00071 _samples_read += n; 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: MovieAudioCursor::read_samples 00076 // Access: Published 00077 // Description: Read audio samples from the stream into a 00078 // Datagram. N is the number of samples you wish 00079 // to read. Multiple-channel audio will be interleaved. 00080 // 00081 // This is not particularly efficient, but it may be 00082 // a convenient way to manipulate samples in python. 00083 //////////////////////////////////////////////////////////////////// 00084 void MovieAudioCursor:: 00085 read_samples(int n, Datagram *dg) { 00086 PN_int16 tmp[4096]; 00087 while (n > 0) { 00088 int blocksize = (4096 / _audio_channels); 00089 if (blocksize > n) blocksize = n; 00090 int words = blocksize * _audio_channels; 00091 read_samples(blocksize, tmp); 00092 for (int i=0; i<words; i++) { 00093 dg->add_int16(tmp[i]); 00094 } 00095 n -= blocksize; 00096 } 00097 } 00098 00099 //////////////////////////////////////////////////////////////////// 00100 // Function: MovieAudioCursor::read_samples 00101 // Access: Published 00102 // Description: Read audio samples from the stream and returns 00103 // them as a string. The samples are stored little-endian 00104 // in the string. N is the number of samples you wish 00105 // to read. Multiple-channel audio will be interleaved. 00106 // 00107 // This is not particularly efficient, but it may be 00108 // a convenient way to manipulate samples in python. 00109 //////////////////////////////////////////////////////////////////// 00110 string MovieAudioCursor:: 00111 read_samples(int n) { 00112 ostringstream result; 00113 PN_int16 tmp[4096]; 00114 while (n > 0) { 00115 int blocksize = (4096 / _audio_channels); 00116 if (blocksize > n) blocksize = n; 00117 int words = blocksize * _audio_channels; 00118 read_samples(blocksize, tmp); 00119 for (int i=0; i<words; i++) { 00120 PN_int16 word = tmp[i]; 00121 result.put((char)(word & 255)); 00122 result.put((char)((word>>8) & 255)); 00123 } 00124 n -= blocksize; 00125 } 00126 return result.str(); 00127 } 00128 00129 00130 //////////////////////////////////////////////////////////////////// 00131 // Function: MovieAudioCursor::seek 00132 // Access: Published, Virtual 00133 // Description: Skips to the specified offset within the file. 00134 // 00135 // If the movie reports that it cannot seek, then 00136 // this method can still advance by reading samples 00137 // and discarding them. However, to move backward, 00138 // can_seek must be true. 00139 // 00140 // If the movie reports that it can_seek, it doesn't 00141 // mean that it can do so quickly. It may have to 00142 // rewind the movie and then fast forward to the 00143 // desired location. Only if can_seek_fast returns 00144 // true can seek operations be done in constant time. 00145 // 00146 // Seeking may not be precise, because AVI files 00147 // often have inaccurate indices. After 00148 // seeking, tell will indicate that the cursor is 00149 // at the target location. However, in truth, the data 00150 // you read may come from a slightly offset location. 00151 //////////////////////////////////////////////////////////////////// 00152 void MovieAudioCursor:: 00153 seek(double offset) { 00154 _last_seek = offset; 00155 _samples_read = 0; 00156 } 00157 00158 //////////////////////////////////////////////////////////////////// 00159 // Function: MovieAudioCursor::ready 00160 // Access: Public 00161 // Description: Returns the number of audio samples that are ready 00162 // to read. This is primarily relevant for sources like 00163 // microphones which produce samples at a fixed rate. 00164 // If you try to read more samples than are ready, the 00165 // result will be silent samples. 00166 // 00167 // Some audio streams do not have a limit on how fast 00168 // they can produce samples. Such streams will always 00169 // return 0x40000000 as the ready-count. This may well 00170 // exceed the length of the audio stream. You therefore 00171 // need to check length separately. 00172 // 00173 // If the aborted flag is set, that means the ready count 00174 // is no longer being replenished. For example, a 00175 // MovieAudioCursor might be reading from an internet 00176 // radio station, and it might buffer data to avoid 00177 // underruns. If it loses connection to the radio 00178 // station, it will set the aborted flag to indicate that 00179 // the buffer is no longer being replenished. But it is 00180 // still ok to read the samples that are in the buffer, 00181 // at least until they run out. Once those are gone, 00182 // there will be no more. 00183 // 00184 // An audio consumer needs to check the length, the 00185 // ready status, and the aborted flag. 00186 //////////////////////////////////////////////////////////////////// 00187 int MovieAudioCursor:: 00188 ready() const { 00189 return 0x40000000; 00190 } 00191