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