Panda3D

movieAudioCursor.cxx

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 
 All Classes Functions Variables Enumerations