annotate trunk/src/Modules/Output/FileOutputHTK.cc @ 402:69466da9745e

- Massive refactoring to make module tree stuff work. In theory we now support configuration files again. The graphics stuff is untested as yet.
author tomwalters
date Mon, 18 Oct 2010 04:42:28 +0000
parents c74acd46121b
children 3b22559cd848
rev   line source
tomwalters@277 1 // Copyright 2006-2010, Thomas Walters
tomwalters@277 2 //
tomwalters@277 3 // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@277 4 // http://www.acousticscale.org/AIMC
tomwalters@277 5 //
tomwalters@318 6 // Licensed under the Apache License, Version 2.0 (the "License");
tomwalters@318 7 // you may not use this file except in compliance with the License.
tomwalters@318 8 // You may obtain a copy of the License at
tomwalters@277 9 //
tomwalters@318 10 // http://www.apache.org/licenses/LICENSE-2.0
tomwalters@277 11 //
tomwalters@318 12 // Unless required by applicable law or agreed to in writing, software
tomwalters@318 13 // distributed under the License is distributed on an "AS IS" BASIS,
tomwalters@318 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
tomwalters@318 15 // See the License for the specific language governing permissions and
tomwalters@318 16 // limitations under the License.
tomwalters@277 17
tomwalters@277 18 /*!
tomwalters@277 19 * \file
tomwalters@279 20 * \brief File output in the HTK format.
tomwalters@277 21 *
tomwalters@279 22 * \author Tom Walters <tom@acousticscale.org>
tomwalters@277 23 * \author Willem van Engen <cnbh@willem.engen.nl>
tomwalters@277 24 * \date created 2006/10/30
tomwalters@277 25 * \version \$Id$
tomwalters@277 26 */
tomwalters@277 27
tomwalters@277 28 #ifdef _WINDOWS
tomwalters@320 29 # include <direct.h> // for _mkdir & _rmdir
tomwalters@277 30 #else
tomwalters@279 31 # include <sys/types.h>
tomwalters@320 32 # include <dirent.h> // for opendir & friends
tomwalters@277 33 #endif
tomwalters@293 34
tomwalters@293 35 #include <stdint.h>
tomwalters@277 36 #include <stdio.h>
tomwalters@277 37 #include <string.h>
tomwalters@277 38 #include <cmath>
tomwalters@277 39
tomwalters@277 40 #include "Modules/Output/FileOutputHTK.h"
tomwalters@277 41
tomwalters@277 42 namespace aimc {
tomwalters@277 43 FileOutputHTK::FileOutputHTK(Parameters *params) : Module(params) {
tomwalters@278 44 module_description_ = "File output in HTK format";
tomwalters@278 45 module_identifier_ = "htk_out";
tomwalters@278 46 module_type_ = "output";
tomwalters@278 47 module_version_ = "$Id$";
tomwalters@402 48
tomwalters@402 49 file_suffix_ = parameters_->DefaultString("htk_out.file_suffix", ".htk");
tomwalters@278 50
tomwalters@279 51 file_handle_ = NULL;
tomwalters@279 52 header_written_ = false;
tomwalters@277 53 frame_period_ms_ = 0.0f;
tomwalters@402 54 previous_start_time_ = 0;
tomwalters@277 55 }
tomwalters@277 56
tomwalters@277 57 FileOutputHTK::~FileOutputHTK() {
tomwalters@279 58 if (file_handle_ != NULL)
tomwalters@279 59 CloseFile();
tomwalters@277 60 }
tomwalters@277 61
tomwalters@402 62 bool FileOutputHTK::InitializeInternal(const SignalBank &input) {
tomwalters@402 63 channel_count_ = input.channel_count();
tomwalters@402 64 buffer_length_ = input.buffer_length();
tomwalters@402 65 ResetInternal();
tomwalters@402 66 if (file_handle_ == NULL) {
tomwalters@402 67 LOG_ERROR(_T("Couldn't initialize file output."));
tomwalters@279 68 return false;
tomwalters@279 69 }
tomwalters@402 70 if (!header_written_) {
tomwalters@292 71 WriteHeader(channel_count_ * buffer_length_, frame_period_ms_);
tomwalters@292 72 }
tomwalters@402 73
tomwalters@277 74 return true;
tomwalters@277 75 }
tomwalters@277 76
tomwalters@277 77 void FileOutputHTK::ResetInternal() {
tomwalters@402 78 // Finalize and close the open file, if there is one.
tomwalters@277 79 if (file_handle_ != NULL && !header_written_) {
tomwalters@277 80 WriteHeader(channel_count_ * buffer_length_, frame_period_ms_);
tomwalters@277 81 }
tomwalters@292 82 if (file_handle_ != NULL)
tomwalters@292 83 CloseFile();
tomwalters@402 84
tomwalters@402 85 // Now open and set up the new file.
tomwalters@402 86 // Check that the output file exists and is writeable.
tomwalters@402 87 string out_filename;
tomwalters@402 88 out_filename = global_parameters_->GetString("output_filename_base") + file_suffix_;
tomwalters@402 89 if ((file_handle_ = fopen(out_filename.c_str(),
tomwalters@402 90 "wb")) == NULL) {
tomwalters@402 91 LOG_ERROR(_T("Couldn't open output file '%s' for writing."),
tomwalters@402 92 out_filename.c_str());
tomwalters@402 93 return;
tomwalters@402 94 }
tomwalters@402 95 sample_count_ = 0;
tomwalters@402 96 header_written_ = false;
tomwalters@402 97 WriteHeader(channel_count_ * buffer_length_, frame_period_ms_);
tomwalters@277 98 }
tomwalters@277 99
tomwalters@277 100 void FileOutputHTK::WriteHeader(int num_elements, float period_ms) {
tomwalters@279 101 if (header_written_)
tomwalters@279 102 return;
tomwalters@277 103
tomwalters@279 104 /* HTK format file: (taken from the HTK book - section 5.10.1)
tomwalters@279 105 * Header: 12 bytes in total, contains:
tomwalters@279 106 * sample_count - number of samples in file (4-byte integer)(long)
tomwalters@279 107 * sample_period - sample period in 100ns units (4-byte integer)(long)
tomwalters@279 108 * sample_size - number of bytes per sample (2-byte integer)(short)
tomwalters@279 109 * parameter_kind - a code indicating the sample kind (2-byte integer)(short)
tomwalters@279 110 */
tomwalters@277 111
tomwalters@279 112 // To be filled in when the file is done
tomwalters@279 113 int32_t sample_count = 0;
tomwalters@277 114
tomwalters@277 115 int32_t sample_period = floor(1e4 * period_ms);
tomwalters@289 116 int16_t sample_size = num_elements * sizeof(float); // NOLINT
tomwalters@277 117
tomwalters@277 118 // User-defined coefficients with energy term
tomwalters@279 119 int16_t parameter_kind = H_USER + H_E;
tomwalters@277 120
tomwalters@279 121 // Fix endianness
tomwalters@279 122 sample_count = ByteSwap32(sample_count);
tomwalters@279 123 sample_period = ByteSwap32(sample_period);
tomwalters@279 124 sample_size = ByteSwap16(sample_size);
tomwalters@279 125 parameter_kind = ByteSwap16(parameter_kind);
tomwalters@277 126
tomwalters@277 127 // Enter header values. sample_count is a dummy value which is filled in on
tomwalters@277 128 // file close
tomwalters@279 129 fwrite(&sample_count, sizeof(sample_count), 1, file_handle_);
tomwalters@279 130 fwrite(&sample_period, sizeof(sample_period), 1, file_handle_);
tomwalters@279 131 fwrite(&sample_size, sizeof(sample_size), 1, file_handle_);
tomwalters@279 132 fwrite(&parameter_kind, sizeof(parameter_kind), 1, file_handle_);
tomwalters@279 133 fflush(file_handle_);
tomwalters@277 134
tomwalters@279 135 header_written_ = true;
tomwalters@277 136 }
tomwalters@277 137
tomwalters@277 138 void FileOutputHTK::Process(const SignalBank &input) {
tomwalters@277 139 if (file_handle_ == NULL) {
tomwalters@277 140 LOG_ERROR(_T("Couldn't process file output. No file is open."
tomwalters@277 141 "Please call FileOutputHTK::OpenFile first"));
tomwalters@279 142 return;
tomwalters@277 143 }
tomwalters@277 144
tomwalters@277 145 if (!header_written_) {
tomwalters@292 146 LOG_ERROR(_T("No header has been written on the output file yet. Please "
tomwalters@402 147 "call FileOutputHTK::Initialize() or FileOutputHTK::Reset() "
tomwalters@402 148 " before calling FileOutputHTK::Process()"));
tomwalters@279 149 return;
tomwalters@277 150 }
tomwalters@279 151 float s;
tomwalters@277 152
tomwalters@279 153 for (int ch = 0; ch < input.channel_count(); ch++) {
tomwalters@277 154 for (int i = 0; i < input.buffer_length(); i++) {
tomwalters@277 155 s = input.sample(ch, i);
tomwalters@277 156 s = ByteSwapFloat(s);
tomwalters@280 157 fwrite(&s, sizeof(s), 1, file_handle_);
tomwalters@277 158 }
tomwalters@277 159 }
tomwalters@279 160 sample_count_++;
tomwalters@402 161 frame_period_ms_ = 1000.0
tomwalters@402 162 * (input.start_time() - previous_start_time_)
tomwalters@402 163 / input.sample_rate();
tomwalters@402 164 previous_start_time_ = input.start_time();
tomwalters@277 165 }
tomwalters@277 166
tomwalters@277 167 bool FileOutputHTK::CloseFile() {
tomwalters@279 168 if (file_handle_ == NULL)
tomwalters@277 169 return false;
tomwalters@277 170
tomwalters@279 171 // Write the first 4 bytes of the file
tomwalters@279 172 // with how many samples there are in the file
tomwalters@279 173 fflush(file_handle_);
tomwalters@279 174 rewind(file_handle_);
tomwalters@279 175 fflush(file_handle_);
tomwalters@277 176 int32_t samples = sample_count_;
tomwalters@279 177 samples = ByteSwap32(samples);
tomwalters@279 178 fwrite(&samples, sizeof(samples), 1, file_handle_);
tomwalters@277 179
tomwalters@279 180 // And close the file
tomwalters@279 181 fclose(file_handle_);
tomwalters@279 182 file_handle_ = NULL;
tomwalters@292 183 header_written_ = false;
tomwalters@279 184 return true;
tomwalters@277 185 }
tomwalters@277 186
tomwalters@277 187 float FileOutputHTK::ByteSwapFloat(float d) {
tomwalters@277 188 // Endianness fix
tomwalters@277 189 float a;
tomwalters@277 190 unsigned char *dst = (unsigned char *)&a;
tomwalters@277 191 unsigned char *src = (unsigned char *)&d;
tomwalters@277 192
tomwalters@277 193 dst[0] = src[3];
tomwalters@277 194 dst[1] = src[2];
tomwalters@277 195 dst[2] = src[1];
tomwalters@277 196 dst[3] = src[0];
tomwalters@277 197
tomwalters@277 198 return a;
tomwalters@277 199 }
tomwalters@280 200 } // namespace aimc
tomwalters@277 201