CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 // A reasonable multiple of four 00033 const TSize MpegAudioStream::mMaxDecodedBlockSize = 8192; 00034 00035 MpegAudioStream::MpegAudioStream() 00036 : mpHandle( NULL ) 00037 { 00038 } 00039 00040 MpegAudioStream::MpegAudioStream( const AudioFile& file ) 00041 : mpHandle( NULL ) 00042 { 00043 SetFOI( file ); 00044 } 00045 00046 MpegAudioStream::~MpegAudioStream() 00047 { 00048 00049 if ( mpHandle ) 00050 { 00051 if ( fclose(mpHandle) ) 00052 { 00053 std::string msgString = "Could not close "; 00054 msgString += mName; 00055 00056 CLAM_ASSERT( false, msgString.c_str() ); 00057 } 00058 } 00059 00060 } 00061 00062 void MpegAudioStream::SetFOI( const AudioFile& file ) 00063 { 00064 AudioFileToNative( file ); 00065 } 00066 00067 void MpegAudioStream::AudioFileToNative( const AudioFile& file ) 00068 { 00069 mName = file.GetLocation(); 00070 mEncodedSampleRate = (int)file.GetHeader().GetSampleRate(); 00071 mEncodedChannels = (int)file.GetHeader().GetChannels(); 00072 00073 mDecodeBuffer.resize( mEncodedChannels ); 00074 } 00075 00076 void MpegAudioStream::PrepareReading() 00077 { 00078 mpHandle = fopen( mName.c_str(), "rb"); 00079 00080 if ( !mpHandle ) 00081 { 00082 std::string msgString = "Could not open "; 00083 msgString += mName; 00084 msgString += " for reading!"; 00085 00086 CLAM_ASSERT( false, msgString.c_str() ); 00087 00088 } 00089 00090 mBitstream.Init( mpHandle ); 00091 00092 SetChannels( mEncodedChannels ); 00093 MarkAllChannelsAsConsumed(); 00094 00095 mSamplesDecoded = 0; 00096 mSamplesTransferred = 0; 00097 } 00098 00099 void MpegAudioStream::PrepareWriting() 00100 { 00101 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!"); 00102 } 00103 00104 void MpegAudioStream::PrepareReadWrite() 00105 { 00106 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!"); 00107 } 00108 00109 void MpegAudioStream::Dispose() 00110 { 00111 mBitstream.Finish(); 00112 } 00113 00114 void MpegAudioStream::DiskToMemoryTransfer() 00115 { 00116 unsigned samplesToRead = mInterleavedData.Size()/mEncodedChannels; 00117 00118 while( mDecodeBuffer[0].size() < samplesToRead 00119 && mBitstream.NextFrame() ) 00120 { 00121 mBitstream.SynthesizeCurrent(); 00122 00123 CLAM_ASSERT( mEncodedChannels == MAD_NCHANNELS( &mBitstream.CurrentFrame().header ), 00124 "This frame hasn't mEncodedChannels channels!" ); 00125 00126 CLAM_ASSERT( mEncodedChannels == mBitstream.CurrentSynthesis().pcm.channels, 00127 "Synthesis result does not have the expected number of channels" ); 00128 00129 TSize samplesDecodedThisTime = mBitstream.CurrentSynthesis().pcm.length; 00130 00131 for( int i = 0; i < mEncodedChannels; i++ ) 00132 { 00133 mad_fixed_t* channelData = mBitstream.CurrentSynthesis().pcm.samples[i]; 00134 00135 mDecodeBuffer[i].insert( mDecodeBuffer[i].end(), 00136 channelData, 00137 channelData + samplesDecodedThisTime ); 00138 } 00139 00140 mSamplesDecoded += mBitstream.CurrentSynthesis().pcm.length; 00141 00142 } 00143 00144 mFramesLastRead = mDecodeBuffer[0].size(); 00145 00146 if ( !mDecodeBuffer[0].empty() ) 00147 { 00148 00149 for ( int i = 0; i < mEncodedChannels; i++ ) 00150 if ( mDecodeBuffer[i].size() < samplesToRead ) 00151 { 00152 mDecodeBuffer[i].insert( mDecodeBuffer[i].end(), 00153 samplesToRead - mDecodeBuffer[i].size(), 00154 mad_fixed_t(0) ); 00155 00156 } 00157 00158 ConsumeDecodedSamples(); 00159 } 00160 00161 mEOFReached = mBitstream.EOS() && mDecodeBuffer[0].empty(); 00162 } 00163 00164 void MpegAudioStream::ConsumeDecodedSamples() 00165 { 00166 TSize samplesToRead = mInterleavedData.Size()/mEncodedChannels; 00167 00168 for ( int i = 0; i < mEncodedChannels; i++ ) 00169 { 00170 TIndex currOffset = 0; 00171 00172 for ( std::deque<mad_fixed_t>::iterator j = mDecodeBuffer[i].begin(); 00173 currOffset < mInterleavedData.Size(); 00174 j++, currOffset+=mEncodedChannels ) 00175 { 00176 double sampleValue = mad_f_todouble(*j); 00177 00178 // :TODO: Finding a nicer way to clamp things 00179 // to the -1,1 could be necessary 00180 // clipping 00181 if ( sampleValue > 1.0 ) 00182 sampleValue = 1.0; 00183 else if ( sampleValue < -1.0 ) 00184 sampleValue = -1.0; 00185 00186 00187 mInterleavedData[ currOffset + i ] = TData(sampleValue); 00188 } 00189 00190 mDecodeBuffer[i].erase( mDecodeBuffer[i].begin(), 00191 mDecodeBuffer[i].begin() + samplesToRead ); 00192 } 00193 00194 mSamplesTransferred += samplesToRead; 00195 00196 00197 } 00198 00199 void MpegAudioStream::MemoryToDiskTransfer() 00200 { 00201 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!"); 00202 } 00203 } 00204 00205 } 00206