MpegAudioStream.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "MpegAudioStream.hxx"
00023 #include "AudioFile.hxx"
00024 #include "Assert.hxx"
00025 #include <iostream>
00026
00027 namespace CLAM
00028 {
00029
00030 namespace AudioCodecs
00031 {
00032
00033 const TSize MpegAudioStream::mMaxDecodedBlockSize = 8192;
00034
00035 MpegAudioStream::MpegAudioStream( const AudioFile& file )
00036 : mpHandle( NULL )
00037 {
00038 mName = file.GetLocation();
00039 mEncodedSampleRate = (int)file.GetHeader().GetSampleRate();
00040 mChannels = (int)file.GetHeader().GetChannels();
00041 mDecodeBuffer.resize( mChannels );
00042 }
00043
00044 MpegAudioStream::~MpegAudioStream()
00045 {
00046 if ( not mpHandle ) return;
00047 fclose(mpHandle);
00048 }
00049
00050 void MpegAudioStream::PrepareReading()
00051 {
00052 mpHandle = fopen( mName.c_str(), "rb");
00053
00054 if ( !mpHandle )
00055 {
00056 std::string msgString = "Could not open ";
00057 msgString += mName;
00058 msgString += " for reading!";
00059
00060 CLAM_ASSERT( false, msgString.c_str() );
00061 }
00062
00063 mBitstream.Init( mpHandle );
00064
00065 mSamplesDecoded = 0;
00066 mFramePosition = 0;
00067 _mp3Frame = 0;
00068 }
00069
00070 void MpegAudioStream::PrepareWriting()
00071 {
00072 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!");
00073 }
00074
00075 void MpegAudioStream::Dispose()
00076 {
00077 mBitstream.Finish();
00078 }
00079
00080 void MpegAudioStream::DiskToMemoryTransfer()
00081 {
00082 unsigned nFrames = mInterleavedData.size()/mChannels;
00083 while( mDecodeBuffer[0].size() < nFrames
00084 && mBitstream.NextFrame() )
00085 {
00086 unsigned long filePos = mBitstream.CurrentFrameFileOffset();
00087 if (_mp3Frame>=_seekCache.size())
00088 _seekCache.push_back(filePos);
00089 else
00090 {
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 CLAM_WARNING(filePos==_seekCache[_mp3Frame],
00102 "MP3 indexing not matching");
00103 }
00104 mBitstream.SynthesizeCurrent();
00105
00106 CLAM_ASSERT( mChannels == MAD_NCHANNELS( &mBitstream.CurrentFrame().header ),
00107 "MpegAudioStream: A frame had not the expected channels." );
00108 CLAM_ASSERT( mChannels == mBitstream.CurrentSynthesis().pcm.channels,
00109 "MpegAudioStream: Synthesis result had not the expected number of channels" );
00110
00111 TSize samplesDecodedThisTime = mBitstream.CurrentSynthesis().pcm.length;
00112 for(unsigned i = 0; i < mChannels; i++ )
00113 {
00114 mad_fixed_t* channelData = mBitstream.CurrentSynthesis().pcm.samples[i];
00115 mDecodeBuffer[i].insert( mDecodeBuffer[i].end(),
00116 channelData,
00117 channelData + samplesDecodedThisTime );
00118 }
00119 mSamplesDecoded += samplesDecodedThisTime;
00120 _mp3Frame++;
00121 }
00122
00123 mFramesLastRead = mDecodeBuffer[0].size();
00124 mEOFReached = mBitstream.EOS() && mDecodeBuffer[0].empty();
00125
00126 if (mDecodeBuffer[0].empty()) return;
00127
00128 for (unsigned i = 0; i < mChannels; i++ )
00129 {
00130 if ( mDecodeBuffer[i].size() < nFrames )
00131 {
00132 mDecodeBuffer[i].insert(
00133 mDecodeBuffer[i].end(),
00134 nFrames - mDecodeBuffer[i].size(),
00135 mad_fixed_t(0) );
00136 }
00137 }
00138 ConsumeDecodedSamples();
00139 }
00140
00141 void MpegAudioStream::ConsumeDecodedSamples()
00142 {
00143 unsigned nFrames = mInterleavedData.size()/mChannels;
00144 for (unsigned i = 0; i < mChannels; i++ )
00145 {
00146 unsigned currOffset = 0;
00147 for ( std::deque<mad_fixed_t>::iterator j = mDecodeBuffer[i].begin();
00148 currOffset < mInterleavedData.size();
00149 j++, currOffset+=mChannels )
00150 {
00151 double sampleValue = mad_f_todouble(*j);
00152
00153
00154
00155
00156 if ( sampleValue > 1.0 )
00157 sampleValue = 1.0;
00158 else if ( sampleValue < -1.0 )
00159 sampleValue = -1.0;
00160
00161 mInterleavedData[ currOffset + i ] = TData(sampleValue);
00162 }
00163 mDecodeBuffer[i].erase( mDecodeBuffer[i].begin(),
00164 mDecodeBuffer[i].begin() + nFrames );
00165 }
00166 mFramePosition += nFrames;
00167 }
00168
00169 void MpegAudioStream::MemoryToDiskTransfer()
00170 {
00171 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!");
00172 }
00173
00174 void MpegAudioStream::SeekTo(unsigned long framePosition)
00175 {
00176
00177 if (framePosition==mFramePosition) return;
00178 unsigned mp3FrameSize = 32*MAD_NSBSAMPLES(&mBitstream.CurrentFrame().header);
00179 unsigned targetMp3Frame = framePosition/mp3FrameSize;
00180 std::cout << "targetMp3Frame: " << targetMp3Frame << std::endl;
00181
00182 unsigned maxForwarJump = _seekCache.size()+100;
00183 if (targetMp3Frame>maxForwarJump) targetMp3Frame=maxForwarJump;
00184 if (targetMp3Frame>=_seekCache.size())
00185 {
00186
00187 fseek(mpHandle, _seekCache[_seekCache.size()-2], SEEK_SET);
00188 mBitstream.Init();
00189 for (unsigned mp3Frame=_seekCache.size();
00190 mp3Frame<=targetMp3Frame; mp3Frame++)
00191 {
00192 if (not mBitstream.NextFrame()) return;
00193 unsigned long filePos = mBitstream.CurrentFrameFileOffset();
00194
00195
00196
00197
00198
00199
00200 if (filePos<=_seekCache.back()) continue;
00201 _seekCache.push_back(filePos);
00202 }
00203 }
00204 unsigned skip = targetMp3Frame>4?3:0;
00205 unsigned jumpingFrame = targetMp3Frame-skip;
00206 std::cout << "jumpingFrame:" << jumpingFrame << std::endl;
00207 fseek(mpHandle, _seekCache[jumpingFrame], SEEK_SET);
00208 mBitstream.Init();
00209 _mp3Frame = targetMp3Frame;
00210
00211 mFramePosition = mp3FrameSize * _mp3Frame;
00212 if (targetMp3Frame == 0) return;
00213 unsigned long previousFrameFilePos = _seekCache[targetMp3Frame-1];
00214 while (true)
00215 {
00216 mBitstream.NextFrame();
00217 unsigned long filePos = mBitstream.CurrentFrameFileOffset();
00218
00219
00220
00221
00222
00223 if (filePos >= previousFrameFilePos) break;
00224 }
00225 mBitstream.SynthesizeCurrent();
00226
00227 unsigned long filePos = mBitstream.CurrentFrameFileOffset();
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 }
00243 }
00244
00245 }
00246