CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2001-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 "MultiChannelAudioFileWriter.hxx" 00023 #include "AudioCodecs_Stream.hxx" 00024 #include "FileSystem.hxx" 00025 #include "AudioInPort.hxx" 00026 #include "Audio.hxx" 00027 #include "XMLStorage.hxx" // TODO: jsut for testing 00028 #include "ProcessingFactory.hxx" 00029 00030 00031 00032 namespace CLAM 00033 { 00034 00035 namespace Hidden 00036 { 00037 static const char * metadata[] = { 00038 "key", "MultiChannelAudioFileReaderConfig", 00039 "category", "Audio File I/O", 00040 "description", "MultiChannelAudioFileReaderConfig", 00041 0 00042 }; 00043 static FactoryRegistrator<ProcessingFactory, MultiChannelAudioFileWriter> reg = metadata; 00044 } 00045 00046 00047 MultiChannelAudioFileWriter::MultiChannelAudioFileWriter() 00048 : mNativeStream( NULL ) 00049 { 00050 Configure(MultiChannelAudioFileWriterConfig()); 00051 } 00052 00053 MultiChannelAudioFileWriter::MultiChannelAudioFileWriter( const ProcessingConfig& cfg ) 00054 : mNativeStream( NULL ) 00055 { 00056 Configure( cfg ); 00057 } 00058 00059 MultiChannelAudioFileWriter::~MultiChannelAudioFileWriter() 00060 { 00061 if ( mNativeStream ) 00062 delete mNativeStream; 00063 00064 DestroyOldInputs(); 00065 00066 if ( mConfig.HasTargetFile() ) 00067 FileSystem::GetInstance().UnlockFile( mConfig.GetTargetFile() ); 00068 00069 } 00070 00071 const char* MultiChannelAudioFileWriter::GetClassName() const 00072 { 00073 return "MultiChannelAudioFileWriter"; 00074 } 00075 00076 bool MultiChannelAudioFileWriter::ModifiesPortsAndControlsAtConfiguration() 00077 { 00078 return true; 00079 } 00080 00081 const ProcessingConfig& MultiChannelAudioFileWriter::GetConfig() const 00082 { 00083 return mConfig; 00084 } 00085 00086 bool MultiChannelAudioFileWriter::Do( std::vector<Audio>& inputs ) 00087 { 00088 typedef std::vector<Audio> InputVec; 00089 00090 if ( !AbleToExecute() ) 00091 return false; 00092 00093 // Checking that all inputs have the same size 00094 bool allInputsSameSize = true; 00095 TSize inputsSize = 0; 00096 00097 inputsSize = inputs[0].GetSize(); 00098 00099 for ( InputVec::iterator i = inputs.begin(); 00100 i!= inputs.end() && allInputsSameSize; 00101 i++ ) 00102 { 00103 allInputsSameSize = ( inputsSize == (*i).GetSize() ); 00104 } 00105 00106 00107 CLAM_ASSERT( allInputsSameSize, "Input sizes differ!" ); 00108 00109 // Now, let's build the samples matrix 00110 00111 int j = 0; 00112 00113 for( InputVec::iterator i = inputs.begin(); 00114 i != inputs.end(); i++ ) 00115 mSamplesMatrix[ j++ ] = (*i).GetBuffer().GetPtr(); 00116 00117 mNativeStream->WriteData( mChannelsToWrite.GetPtr(), mChannelsToWrite.Size(), 00118 mSamplesMatrix.GetPtr(), inputsSize ); 00119 00120 return true; 00121 00122 } 00123 00124 bool MultiChannelAudioFileWriter::Do() 00125 { 00126 if ( !AbleToExecute() ) 00127 return false; 00128 00129 // Checking that all inputs have the same size 00130 bool allInputsSameSize = true; 00131 TSize inputsSize = 0; 00132 00133 InputsRefVector inputsRef; 00134 00135 for ( VectorOfInputs::iterator i = mInputs.begin(); 00136 i!= mInputs.end(); i++ ) 00137 { 00138 inputsRef.push_back( &((*i)->GetAudio()) ); 00139 } 00140 00141 inputsSize = inputsRef[0]->GetSize(); 00142 00143 for ( InputsRefVector::iterator i = inputsRef.begin(); 00144 i!= inputsRef.end() && allInputsSameSize; 00145 i++ ) 00146 { 00147 allInputsSameSize = ( inputsSize == (*i)->GetSize() ); 00148 } 00149 00150 00151 CLAM_ASSERT( allInputsSameSize, "Input sizes differ!" ); 00152 00153 // Now, let's build the samples matrix 00154 00155 int j = 0; 00156 00157 for( InputsRefVector::iterator i = inputsRef.begin(); 00158 i != inputsRef.end(); i++ ) 00159 mSamplesMatrix[ j++ ] = (*i)->GetBuffer().GetPtr(); 00160 00161 mNativeStream->WriteData( mChannelsToWrite.GetPtr(), mChannelsToWrite.Size(), 00162 mSamplesMatrix.GetPtr(), inputsSize ); 00163 00164 for( VectorOfInputs::iterator i = mInputs.begin(); 00165 i!=mInputs.end(); i++ ) 00166 { 00167 (*i)->Consume(); 00168 } 00169 00170 return true; 00171 } 00172 00173 bool MultiChannelAudioFileWriter::ConcreteConfigure( const ProcessingConfig& cfg ) 00174 { 00175 const AudioOutFilename & filename = mConfig.GetTargetFile(); 00176 if ( mConfig.HasTargetFile() ) 00177 FileSystem::GetInstance().UnlockFile( filename ); 00178 00179 CopyAsConcreteConfig( mConfig, cfg ); 00180 00181 if (filename=="") 00182 { 00183 AddConfigErrorMessage("No file selected"); 00184 return false; 00185 } 00186 00187 unsigned nChannels = mConfig.HasNChannels()? mConfig.GetNChannels() : 1; 00188 if ( nChannels < 1 ) 00189 { 00190 AddConfigErrorMessage("Channels should be, at least, 1."); 00191 return false; 00192 } 00193 AudioFileHeader header; 00194 header.SetValues( 00195 mConfig.GetSampleRate(), 00196 nChannels, 00197 CLAM::EAudioFileFormat::FormatFromFilename(filename) ); 00198 mAudioFile.CreateNew(filename, header); 00199 if ( !mAudioFile.IsWritable() ) 00200 { 00201 AddConfigErrorMessage("The format does not support such number of channels, endiannes or sampling rate."); 00202 00203 return false; 00204 } 00205 00206 if ( FileSystem::GetInstance().IsFileLocked( filename ) ) 00207 { 00208 AddConfigErrorMessage("The file '"); 00209 AddConfigErrorMessage( filename ); 00210 AddConfigErrorMessage("' has been locked by another Processing"); 00211 00212 return false; 00213 } 00214 00215 FileSystem::GetInstance().LockFile( filename ); 00216 00217 00218 if ( !mInputs.empty() ) 00219 DestroyOldInputs(); 00220 00221 mChannelsToWrite.Resize( nChannels ); 00222 mChannelsToWrite.SetSize( nChannels ); 00223 mSamplesMatrix.Resize( nChannels ); 00224 mSamplesMatrix.SetSize( nChannels ); 00225 00226 for ( unsigned i = 0; i < nChannels; i++ ) 00227 { 00228 mChannelsToWrite[ i ] = i; 00229 mSamplesMatrix[ i ] = NULL; 00230 std::stringstream sstr; 00231 sstr << i; 00232 00233 mInputs.push_back( 00234 new AudioInPort( "Channel #" + sstr.str(), this) ); 00235 } 00236 00237 mNativeStream = mAudioFile.GetStream(); 00238 00239 if ( !mNativeStream ) 00240 { 00241 AddConfigErrorMessage("Could not acquire an audio file stream!"); 00242 return false; 00243 } 00244 00245 return true; 00246 } 00247 00248 bool MultiChannelAudioFileWriter::ConcreteStart() 00249 { 00250 if (mNativeStream == NULL ) 00251 mNativeStream = mAudioFile.GetStream(); 00252 mNativeStream->PrepareWriting(); 00253 00254 return true; 00255 } 00256 00257 bool MultiChannelAudioFileWriter::ConcreteStop() 00258 { 00259 mNativeStream->Dispose(); 00260 delete mNativeStream; 00261 mNativeStream = NULL; 00262 00263 return true; 00264 } 00265 00266 void MultiChannelAudioFileWriter::DestroyOldInputs() 00267 { 00268 for ( VectorOfInputs::iterator i = mInputs.begin(); 00269 i != mInputs.end(); i++ ) 00270 { 00271 if ( *i ) delete *i; 00272 } 00273 00274 mInputs.clear(); 00275 GetInPorts().Clear(); 00276 } 00277 } 00278