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@322
|
70 frame_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@322
|
122 uint32_t frame_count_out = frame_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@322
|
128 fwrite(&frame_count_out, sizeof(frame_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@322
|
159 frame_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@322
|
171 uint32_t frame_count = frame_count_;
|
tomwalters@322
|
172 fwrite(&frame_count, sizeof(frame_count), 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
|