tomwalters@46: // Copyright 2006-2010, Thomas Walters tomwalters@46: // tomwalters@46: // AIM-C: A C++ implementation of the Auditory Image Model tomwalters@46: // http://www.acousticscale.org/AIMC tomwalters@46: // tomwalters@46: // Licensed under the Apache License, Version 2.0 (the "License"); tomwalters@46: // you may not use this file except in compliance with the License. tomwalters@46: // You may obtain a copy of the License at tomwalters@46: // tomwalters@46: // http://www.apache.org/licenses/LICENSE-2.0 tomwalters@46: // tomwalters@46: // Unless required by applicable law or agreed to in writing, software tomwalters@46: // distributed under the License is distributed on an "AS IS" BASIS, tomwalters@46: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. tomwalters@46: // See the License for the specific language governing permissions and tomwalters@46: // limitations under the License. tomwalters@46: tomwalters@46: /*! tomwalters@46: * \file tomwalters@46: * \brief File output in the HTK format. tomwalters@46: * tomwalters@46: * \author Tom Walters tomwalters@46: * \author Willem van Engen tomwalters@46: * \date created 2007/01/26 tomwalters@46: * \version \$Id: $ tomwalters@46: */ tomwalters@46: tomwalters@603: #include "Modules/Output/FileOutputAIMC.h" tomwalters@603: tomwalters@46: #ifdef _WINDOWS tomwalters@46: # include // for _mkdir & _rmdir tomwalters@46: #else tomwalters@46: # include tomwalters@46: # include // for opendir & friends tomwalters@46: #endif tomwalters@46: tomwalters@46: #include tomwalters@46: #include tomwalters@46: #include tomwalters@46: #include tom@253: #include tomwalters@46: tomwalters@46: namespace aimc { tomwalters@46: FileOutputAIMC::FileOutputAIMC(Parameters *params) : Module(params) { tomwalters@46: module_description_ = "File output in AIMC format"; tomwalters@232: module_identifier_ = "aimc_out"; tomwalters@46: module_type_ = "output"; tomwalters@46: module_version_ = "$Id: FileOutputAIMC.cc 51 2010-03-30 22:06:24Z tomwalters $"; tom@253: file_suffix_ = parameters_->DefaultString("file_suffix", ".aimc"); tomwalters@603: dump_strobes_ = parameters_->DefaultBool("dump_strobes", false); tomwalters@603: strobes_file_suffix_ = parameters_->DefaultString("strobes_file_suffix", ".strobes"); tomwalters@46: tomwalters@46: file_handle_ = NULL; tomwalters@603: strobes_file_handle_ = NULL; tomwalters@46: header_written_ = false; tomwalters@46: frame_period_ms_ = 0.0f; tomwalters@46: } tomwalters@46: tomwalters@46: FileOutputAIMC::~FileOutputAIMC() { tomwalters@46: if (file_handle_ != NULL) tomwalters@46: CloseFile(); tomwalters@603: if (strobes_file_handle_ != NULL) tomwalters@603: CloseStrobesFile(); tomwalters@603: } tomwalters@603: tomwalters@603: bool FileOutputAIMC::OpenStrobesFile(string &filename) { tomwalters@603: if (strobes_file_handle_ != NULL) { tomwalters@603: LOG_ERROR(_T("Couldn't open strobes output file. A file is already open.")); tomwalters@603: return false; tomwalters@603: } tomwalters@603: // Check that the output file exists and is writeable tomwalters@603: if ((strobes_file_handle_ = fopen(filename.c_str(), "wb")) == NULL) { tomwalters@603: LOG_ERROR(_T("Couldn't open output file '%s' for writing."), filename.c_str()); tomwalters@603: return false; tomwalters@603: } tomwalters@603: return true; tomwalters@46: } tomwalters@46: tom@253: bool FileOutputAIMC::OpenFile(string &filename) { tomwalters@46: if (file_handle_ != NULL) { tomwalters@46: LOG_ERROR(_T("Couldn't open output file. A file is already open.")); tomwalters@46: return false; tomwalters@46: } tomwalters@46: tomwalters@46: // Check that the output file exists and is writeable tom@253: if ((file_handle_ = fopen(filename.c_str(), "wb")) == NULL) { tom@253: LOG_ERROR(_T("Couldn't open output file '%s' for writing."), filename.c_str()); tomwalters@46: return false; tomwalters@46: } tom@253: // Write temporary values for the frame count and frame period. tomwalters@159: frame_count_ = 0; tom@253: frame_period_ms_ = 0.0; tomwalters@46: header_written_ = false; tomwalters@46: if (initialized_) { tomwalters@46: WriteHeader(); tomwalters@46: } tomwalters@603: tomwalters@46: return true; tomwalters@46: } tomwalters@46: tomwalters@46: bool FileOutputAIMC::InitializeInternal(const SignalBank &input) { tom@253: channel_count_ = input.channel_count(); tom@253: buffer_length_ = input.buffer_length(); tom@253: sample_rate_ = input.sample_rate(); tom@253: ResetInternal(); tomwalters@46: if (file_handle_ == NULL) { tom@253: LOG_ERROR(_T("Couldn't initialize file output.")); tomwalters@46: return false; tomwalters@46: } tomwalters@46: return true; tomwalters@46: } tomwalters@46: tomwalters@46: void FileOutputAIMC::ResetInternal() { tomwalters@46: if (file_handle_ != NULL && !header_written_) { tomwalters@46: WriteHeader(); tomwalters@46: } tomwalters@46: if (file_handle_ != NULL) tomwalters@46: CloseFile(); tom@253: tom@253: string out_filename; tom@253: out_filename = global_parameters_->GetString("output_filename_base") + file_suffix_; tom@253: OpenFile(out_filename); tomwalters@603: if (dump_strobes_) { tomwalters@603: if (strobes_file_handle_ != NULL) { tomwalters@603: CloseStrobesFile(); tomwalters@603: } tomwalters@603: string strobes_filename = tomwalters@603: global_parameters_->GetString("output_filename_base") tomwalters@603: + strobes_file_suffix_; tomwalters@603: OpenStrobesFile(strobes_filename); tomwalters@603: } tomwalters@46: } tomwalters@46: tomwalters@46: void FileOutputAIMC::WriteHeader() { tomwalters@46: if (header_written_) tomwalters@46: return; tomwalters@46: tomwalters@46: /* File format: tomwalters@46: * Header: Number of frames (uint32), tomwalters@46: * Frame period in milliseconds (float32), tomwalters@46: * Number of channels per frame (uint32), tomwalters@46: * Number of samples per channel of each frame (uint32) tomwalters@46: * Sample rate (float32) tomwalters@46: * tomwalters@46: * Data: Series of floats, by time, then channel, then frame tomwalters@46: * f1c1t1,f1c1t2,f1c1t3... tomwalters@46: */ tomwalters@46: tomwalters@159: uint32_t frame_count_out = frame_count_; tomwalters@46: float sample_period_out = frame_period_ms_; tomwalters@46: uint32_t channels_out = channel_count_; tomwalters@46: uint32_t samples_out = buffer_length_; tomwalters@46: float sample_rate = sample_rate_; tomwalters@46: tomwalters@159: fwrite(&frame_count_out, sizeof(frame_count_out), 1, file_handle_); tomwalters@46: fwrite(&sample_period_out, sizeof(sample_period_out), 1, file_handle_); tomwalters@46: fwrite(&channels_out, sizeof(channels_out), 1, file_handle_); tomwalters@46: fwrite(&samples_out, sizeof(samples_out), 1, file_handle_); tomwalters@46: fwrite(&sample_rate, sizeof(sample_rate), 1, file_handle_); tomwalters@46: fflush(file_handle_); tomwalters@46: tomwalters@46: header_written_ = true; tomwalters@46: } tomwalters@46: tomwalters@46: void FileOutputAIMC::Process(const SignalBank &input) { tomwalters@46: if (file_handle_ == NULL) { tomwalters@46: LOG_ERROR(_T("Couldn't process file output. No file is open." tomwalters@46: "Please call FileOutputAIMC::OpenFile first")); tomwalters@46: return; tomwalters@46: } tomwalters@46: tomwalters@46: if (!header_written_) { tomwalters@46: LOG_ERROR(_T("No header has been written on the output file yet. Please " tomwalters@46: "call FileOutputAIMC::Initialize() before calling " tomwalters@46: "FileOutputAIMC::Process()")); tomwalters@46: return; tomwalters@46: } tomwalters@46: float s; tomwalters@46: tomwalters@46: for (int ch = 0; ch < input.channel_count(); ch++) { tomwalters@46: for (int i = 0; i < input.buffer_length(); i++) { tomwalters@46: s = input.sample(ch, i); tomwalters@46: fwrite(&s, sizeof(s), 1, file_handle_); tomwalters@46: } tomwalters@46: } tomwalters@159: frame_count_++; tomwalters@603: tomwalters@603: if (dump_strobes_) { tomwalters@603: if (strobes_file_handle_ == NULL) { tomwalters@603: LOG_ERROR(_T("Couldn't process file output for strobes. No srobes file is open." tomwalters@603: "Please call FileOutputAIMC::OpenStrobesFile first")); tomwalters@603: return; tomwalters@603: } tomwalters@603: int strobe; tomwalters@603: for (int ch = 0; ch < input.channel_count(); ch++) { tomwalters@603: const int kStartOfStrobeRow = -65535; tomwalters@603: strobe = kStartOfStrobeRow; tomwalters@603: fwrite(&strobe, sizeof(strobe), 1, strobes_file_handle_); tomwalters@603: for (int i = 0; i < static_cast(input.get_strobes(ch).size()); tomwalters@603: i++) { tomwalters@603: strobe = input.get_strobes(ch)[i]; tomwalters@603: fwrite(&strobe, sizeof(strobe), 1, strobes_file_handle_); tomwalters@603: } tomwalters@603: } tomwalters@603: } tomwalters@603: tomwalters@603: } tomwalters@603: tomwalters@603: bool FileOutputAIMC::CloseStrobesFile() { tomwalters@603: if (strobes_file_handle_ == NULL) tomwalters@603: return false; tomwalters@603: tomwalters@603: // And close the file tomwalters@603: fclose(strobes_file_handle_); tomwalters@603: strobes_file_handle_ = NULL; tomwalters@603: return true; tomwalters@46: } tomwalters@46: tomwalters@46: bool FileOutputAIMC::CloseFile() { tomwalters@46: if (file_handle_ == NULL) tomwalters@46: return false; tomwalters@46: tomwalters@46: // Write the first 4 bytes of the file tomwalters@46: // with how many samples there are in the file tomwalters@46: fflush(file_handle_); tomwalters@46: rewind(file_handle_); tomwalters@46: fflush(file_handle_); tomwalters@159: uint32_t frame_count = frame_count_; tom@253: float sample_period_out = frame_period_ms_; tomwalters@159: fwrite(&frame_count, sizeof(frame_count), 1, file_handle_); tom@253: fwrite(&sample_period_out, sizeof(sample_period_out), 1, file_handle_); tomwalters@46: tomwalters@46: // And close the file tomwalters@46: fclose(file_handle_); tomwalters@46: file_handle_ = NULL; tomwalters@46: header_written_ = false; tomwalters@46: return true; tomwalters@46: } tomwalters@46: } // namespace aimc tomwalters@46: