00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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"
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
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
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
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
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