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