MultiChannelAudioFileWriter.cxx

Go to the documentation of this file.
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", "MultiChannelAudioFileWriter",
00039                 "category", "Audio File I/O",
00040                 "description", "MultiChannelAudioFileWriter",
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                 if ( mConfig.HasTargetFile() )
00176                         FileSystem::GetInstance().UnlockFile( mConfig.GetTargetFile() );
00177 
00178                 CopyAsConcreteConfig( mConfig, cfg );
00179 
00180                 const AudioOutFilename & filename = mConfig.GetTargetFile();
00181                 if (filename=="")
00182                 {
00183                         return AddConfigErrorMessage("No file selected");
00184                 }
00185                 
00186                 unsigned nChannels = mConfig.HasNChannels()? mConfig.GetNChannels() : 1;
00187                 if ( nChannels < 1 )
00188                 {
00189                         return AddConfigErrorMessage("Channels should be, at least, 1.");
00190                 }
00191                 AudioFileHeader header;
00192                 header.SetValues(
00193                         mConfig.GetSampleRate(),
00194                         nChannels,
00195                         CLAM::EAudioFileFormat::FormatFromFilename(filename) );
00196                 mAudioFile.CreateNew(filename, header);
00197                 if ( !mAudioFile.IsWritable() )
00198                 {
00199                         return AddConfigErrorMessage("The format does not support such number of channels, endiannes or sampling rate.");
00200                 }
00201 
00202                 if ( FileSystem::GetInstance().IsFileLocked( filename ) )
00203                 {
00204                         AddConfigErrorMessage("The file '");
00205                         AddConfigErrorMessage( filename );
00206                         AddConfigErrorMessage("' has been locked by another Processing");
00207 
00208                         return false;
00209                 }
00210 
00211                 FileSystem::GetInstance().LockFile( filename );
00212 
00213 
00214                 if ( !mInputs.empty() )
00215                         DestroyOldInputs();
00216 
00217                 mChannelsToWrite.Resize( nChannels );
00218                 mChannelsToWrite.SetSize( nChannels );
00219                 mSamplesMatrix.Resize( nChannels );
00220                 mSamplesMatrix.SetSize( nChannels );
00221 
00222                 for ( unsigned i = 0; i < nChannels; i++ )
00223                 {
00224                         mChannelsToWrite[ i ] = i;
00225                         mSamplesMatrix[ i ] = NULL;
00226                         std::stringstream sstr;
00227                         sstr << i;
00228                         
00229                         mInputs.push_back( 
00230                                 new AudioInPort( "Channel #" + sstr.str(), this) );
00231                 }
00232 
00233                 mNativeStream = mAudioFile.GetStream();
00234 
00235                 if ( !mNativeStream )
00236                 {
00237                         return AddConfigErrorMessage("Could not acquire an audio file stream!");
00238                 }
00239 
00240                 return true;
00241         }
00242 
00243         bool MultiChannelAudioFileWriter::ConcreteStart()
00244         {
00245                 if (mNativeStream == NULL )
00246                         mNativeStream = mAudioFile.GetStream();
00247                 mNativeStream->PrepareWriting();
00248 
00249                 return true;
00250         }
00251 
00252         bool MultiChannelAudioFileWriter::ConcreteStop()
00253         {
00254                 mNativeStream->Dispose();
00255                 delete mNativeStream;
00256                 mNativeStream = NULL;
00257 
00258                 return true;
00259         }
00260 
00261         void MultiChannelAudioFileWriter::DestroyOldInputs()
00262         {
00263                 for ( VectorOfInputs::iterator i = mInputs.begin();
00264                       i != mInputs.end(); i++ )
00265                 {
00266                         if ( *i ) delete *i;
00267                 }
00268 
00269                 mInputs.clear();
00270                 GetInPorts().Clear();
00271         }
00272 }
00273 
Generated by  doxygen 1.6.3