annotate trunk/src/Modules/Output/FileOutputAIMC.cc @ 320:c74acd46121b

- Added support for a very basic AIM-C file format
author tomwalters@google.com
date Thu, 27 May 2010 07:25:03 +0000
parents
children 1c0723041971
rev   line source
tomwalters@320 1 // Copyright 2006-2010, Thomas Walters
tomwalters@320 2 //
tomwalters@320 3 // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@320 4 // http://www.acousticscale.org/AIMC
tomwalters@320 5 //
tomwalters@320 6 // Licensed under the Apache License, Version 2.0 (the "License");
tomwalters@320 7 // you may not use this file except in compliance with the License.
tomwalters@320 8 // You may obtain a copy of the License at
tomwalters@320 9 //
tomwalters@320 10 // http://www.apache.org/licenses/LICENSE-2.0
tomwalters@320 11 //
tomwalters@320 12 // Unless required by applicable law or agreed to in writing, software
tomwalters@320 13 // distributed under the License is distributed on an "AS IS" BASIS,
tomwalters@320 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
tomwalters@320 15 // See the License for the specific language governing permissions and
tomwalters@320 16 // limitations under the License.
tomwalters@320 17
tomwalters@320 18 /*!
tomwalters@320 19 * \file
tomwalters@320 20 * \brief File output in the HTK format.
tomwalters@320 21 *
tomwalters@320 22 * \author Tom Walters <tom@acousticscale.org>
tomwalters@320 23 * \author Willem van Engen <cnbh@willem.engen.nl>
tomwalters@320 24 * \date created 2007/01/26
tomwalters@320 25 * \version \$Id: $
tomwalters@320 26 */
tomwalters@320 27
tomwalters@320 28 #ifdef _WINDOWS
tomwalters@320 29 # include <direct.h> // for _mkdir & _rmdir
tomwalters@320 30 #else
tomwalters@320 31 # include <sys/types.h>
tomwalters@320 32 # include <dirent.h> // for opendir & friends
tomwalters@320 33 #endif
tomwalters@320 34
tomwalters@320 35 #include <stdint.h>
tomwalters@320 36 #include <stdio.h>
tomwalters@320 37 #include <string.h>
tomwalters@320 38 #include <cmath>
tomwalters@320 39
tomwalters@320 40 #include "Modules/Output/FileOutputAIMC.h"
tomwalters@320 41
tomwalters@320 42 namespace aimc {
tomwalters@320 43 FileOutputAIMC::FileOutputAIMC(Parameters *params) : Module(params) {
tomwalters@320 44 module_description_ = "File output in AIMC format";
tomwalters@320 45 module_identifier_ = "htk_out";
tomwalters@320 46 module_type_ = "output";
tomwalters@320 47 module_version_ = "$Id: FileOutputAIMC.cc 51 2010-03-30 22:06:24Z tomwalters $";
tomwalters@320 48
tomwalters@320 49 file_handle_ = NULL;
tomwalters@320 50 header_written_ = false;
tomwalters@320 51 frame_period_ms_ = 0.0f;
tomwalters@320 52 }
tomwalters@320 53
tomwalters@320 54 FileOutputAIMC::~FileOutputAIMC() {
tomwalters@320 55 if (file_handle_ != NULL)
tomwalters@320 56 CloseFile();
tomwalters@320 57 }
tomwalters@320 58
tomwalters@320 59 bool FileOutputAIMC::OpenFile(const char* filename, float frame_period_ms) {
tomwalters@320 60 if (file_handle_ != NULL) {
tomwalters@320 61 LOG_ERROR(_T("Couldn't open output file. A file is already open."));
tomwalters@320 62 return false;
tomwalters@320 63 }
tomwalters@320 64
tomwalters@320 65 // Check that the output file exists and is writeable
tomwalters@320 66 if ((file_handle_ = fopen(filename, "wb")) == NULL) {
tomwalters@320 67 LOG_ERROR(_T("Couldn't open output file '%s' for writing."), filename);
tomwalters@320 68 return false;
tomwalters@320 69 }
tomwalters@320 70 sample_count_ = 0;
tomwalters@320 71 frame_period_ms_ = frame_period_ms;
tomwalters@320 72 header_written_ = false;
tomwalters@320 73 if (initialized_) {
tomwalters@320 74 WriteHeader();
tomwalters@320 75 }
tomwalters@320 76 return true;
tomwalters@320 77 }
tomwalters@320 78
tomwalters@320 79 bool FileOutputAIMC::InitializeInternal(const SignalBank &input) {
tomwalters@320 80 if (file_handle_ == NULL) {
tomwalters@320 81 LOG_ERROR(_T("Couldn't initialize file output. "
tomwalters@320 82 "Please call FileOutputAIMC::OpenFile first"));
tomwalters@320 83 return false;
tomwalters@320 84 }
tomwalters@320 85 if (header_written_) {
tomwalters@320 86 LOG_ERROR(_T("A header has already been written on the output file. "
tomwalters@320 87 "Please call FileOutputAIMC::CloseFile to close that file, "
tomwalters@320 88 "and FileOutputAIMC::OpenFile to open an new one before "
tomwalters@320 89 "calling FileOutputAIMC::Initialize again."));
tomwalters@320 90 return false;
tomwalters@320 91 }
tomwalters@320 92 channel_count_ = input.channel_count();
tomwalters@320 93 buffer_length_ = input.buffer_length();
tomwalters@320 94 sample_rate_ = input.sample_rate();
tomwalters@320 95 WriteHeader();
tomwalters@320 96 return true;
tomwalters@320 97 }
tomwalters@320 98
tomwalters@320 99 void FileOutputAIMC::ResetInternal() {
tomwalters@320 100 if (file_handle_ != NULL && !header_written_) {
tomwalters@320 101 WriteHeader();
tomwalters@320 102 }
tomwalters@320 103 if (file_handle_ != NULL)
tomwalters@320 104 CloseFile();
tomwalters@320 105 }
tomwalters@320 106
tomwalters@320 107 void FileOutputAIMC::WriteHeader() {
tomwalters@320 108 if (header_written_)
tomwalters@320 109 return;
tomwalters@320 110
tomwalters@320 111 /* File format:
tomwalters@320 112 * Header: Number of frames (uint32),
tomwalters@320 113 * Frame period in milliseconds (float32),
tomwalters@320 114 * Number of channels per frame (uint32),
tomwalters@320 115 * Number of samples per channel of each frame (uint32)
tomwalters@320 116 * Sample rate (float32)
tomwalters@320 117 *
tomwalters@320 118 * Data: Series of floats, by time, then channel, then frame
tomwalters@320 119 * f1c1t1,f1c1t2,f1c1t3...
tomwalters@320 120 */
tomwalters@320 121
tomwalters@320 122 uint32_t sample_count_out = sample_count_;
tomwalters@320 123 float sample_period_out = frame_period_ms_;
tomwalters@320 124 uint32_t channels_out = channel_count_;
tomwalters@320 125 uint32_t samples_out = buffer_length_;
tomwalters@320 126 float sample_rate = sample_rate_;
tomwalters@320 127
tomwalters@320 128 fwrite(&sample_count_out, sizeof(sample_count_out), 1, file_handle_);
tomwalters@320 129 fwrite(&sample_period_out, sizeof(sample_period_out), 1, file_handle_);
tomwalters@320 130 fwrite(&channels_out, sizeof(channels_out), 1, file_handle_);
tomwalters@320 131 fwrite(&samples_out, sizeof(samples_out), 1, file_handle_);
tomwalters@320 132 fwrite(&sample_rate, sizeof(sample_rate), 1, file_handle_);
tomwalters@320 133 fflush(file_handle_);
tomwalters@320 134
tomwalters@320 135 header_written_ = true;
tomwalters@320 136 }
tomwalters@320 137
tomwalters@320 138 void FileOutputAIMC::Process(const SignalBank &input) {
tomwalters@320 139 if (file_handle_ == NULL) {
tomwalters@320 140 LOG_ERROR(_T("Couldn't process file output. No file is open."
tomwalters@320 141 "Please call FileOutputAIMC::OpenFile first"));
tomwalters@320 142 return;
tomwalters@320 143 }
tomwalters@320 144
tomwalters@320 145 if (!header_written_) {
tomwalters@320 146 LOG_ERROR(_T("No header has been written on the output file yet. Please "
tomwalters@320 147 "call FileOutputAIMC::Initialize() before calling "
tomwalters@320 148 "FileOutputAIMC::Process()"));
tomwalters@320 149 return;
tomwalters@320 150 }
tomwalters@320 151 float s;
tomwalters@320 152
tomwalters@320 153 for (int ch = 0; ch < input.channel_count(); ch++) {
tomwalters@320 154 for (int i = 0; i < input.buffer_length(); i++) {
tomwalters@320 155 s = input.sample(ch, i);
tomwalters@320 156 fwrite(&s, sizeof(s), 1, file_handle_);
tomwalters@320 157 }
tomwalters@320 158 }
tomwalters@320 159 sample_count_++;
tomwalters@320 160 }
tomwalters@320 161
tomwalters@320 162 bool FileOutputAIMC::CloseFile() {
tomwalters@320 163 if (file_handle_ == NULL)
tomwalters@320 164 return false;
tomwalters@320 165
tomwalters@320 166 // Write the first 4 bytes of the file
tomwalters@320 167 // with how many samples there are in the file
tomwalters@320 168 fflush(file_handle_);
tomwalters@320 169 rewind(file_handle_);
tomwalters@320 170 fflush(file_handle_);
tomwalters@320 171 uint32_t samples = sample_count_;
tomwalters@320 172 fwrite(&samples, sizeof(samples), 1, file_handle_);
tomwalters@320 173
tomwalters@320 174 // And close the file
tomwalters@320 175 fclose(file_handle_);
tomwalters@320 176 file_handle_ = NULL;
tomwalters@320 177 header_written_ = false;
tomwalters@320 178 return true;
tomwalters@320 179 }
tomwalters@320 180 } // namespace aimc
tomwalters@320 181