annotate src/Modules/Output/FileOutputHTK.cc @ 611:0fbaf443ec82

Carfac C++ revision 3, indluding more style improvements. The output structs are now classes again, and have separate storage methods for each output structure along with flags in the Run and RunSegment methods to allow for only storing NAPs if desired.
author alexbrandmeyer
date Fri, 17 May 2013 19:52:45 +0000
parents b953e295b49e
children
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_) {
tom@247 71 WriteHeader(channel_count_ * buffer_length_);
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_) {
tom@247 80 WriteHeader(channel_count_ * buffer_length_);
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;
tom@247 97 WriteHeader(channel_count_ * buffer_length_);
tomwalters@5 98 }
tomwalters@5 99
tom@247 100 void FileOutputHTK::WriteHeader(int num_elements) {
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
tom@247 115 int32_t sample_period = floor(1e4 * frame_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() "
tom@255 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
tom@247 173 // and the next 4 bytes with the frame period.
tomwalters@7 174 fflush(file_handle_);
tomwalters@7 175 rewind(file_handle_);
tomwalters@7 176 fflush(file_handle_);
tomwalters@5 177 int32_t samples = sample_count_;
tomwalters@7 178 samples = ByteSwap32(samples);
tom@247 179 int32_t sample_period = floor(1e4 * frame_period_ms_);
tom@247 180 sample_period = ByteSwap32(sample_period);
tomwalters@7 181 fwrite(&samples, sizeof(samples), 1, file_handle_);
tom@247 182 fwrite(&sample_period, sizeof(sample_period), 1, file_handle_);
tomwalters@5 183
tomwalters@7 184 // And close the file
tomwalters@7 185 fclose(file_handle_);
tomwalters@7 186 file_handle_ = NULL;
tomwalters@20 187 header_written_ = false;
tomwalters@7 188 return true;
tomwalters@5 189 }
tomwalters@5 190
tomwalters@5 191 float FileOutputHTK::ByteSwapFloat(float d) {
tomwalters@5 192 // Endianness fix
tomwalters@5 193 float a;
tomwalters@5 194 unsigned char *dst = (unsigned char *)&a;
tomwalters@5 195 unsigned char *src = (unsigned char *)&d;
tomwalters@5 196
tomwalters@5 197 dst[0] = src[3];
tomwalters@5 198 dst[1] = src[2];
tomwalters@5 199 dst[2] = src[1];
tomwalters@5 200 dst[3] = src[0];
tomwalters@5 201
tomwalters@5 202 return a;
tomwalters@5 203 }
tomwalters@8 204 } // namespace aimc
tomwalters@5 205