annotate src/Modules/Output/FileOutputHTK.cc @ 232:af531fc3f280

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