diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/Modules/Output/FileOutputAIMC.cc	Thu May 27 07:25:03 2010 +0000
@@ -0,0 +1,181 @@
+// Copyright 2006-2010, Thomas Walters
+//
+// AIM-C: A C++ implementation of the Auditory Image Model
+// http://www.acousticscale.org/AIMC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*!
+ * \file
+ * \brief File output in the HTK format.
+ *
+ * \author Tom Walters <tom@acousticscale.org>
+ * \author Willem van Engen <cnbh@willem.engen.nl>
+ * \date created 2007/01/26
+ * \version \$Id: $
+ */
+
+#ifdef _WINDOWS
+#  include <direct.h>  // for _mkdir & _rmdir
+#else
+#  include <sys/types.h>
+#  include <dirent.h>  // for opendir & friends
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <cmath>
+
+#include "Modules/Output/FileOutputAIMC.h"
+
+namespace aimc {
+FileOutputAIMC::FileOutputAIMC(Parameters *params) : Module(params) {
+  module_description_ = "File output in AIMC format";
+  module_identifier_ = "htk_out";
+  module_type_ = "output";
+  module_version_ = "$Id: FileOutputAIMC.cc 51 2010-03-30 22:06:24Z tomwalters $";
+
+  file_handle_ = NULL;
+  header_written_ = false;
+  frame_period_ms_ = 0.0f;
+}
+
+FileOutputAIMC::~FileOutputAIMC() {
+  if (file_handle_ != NULL)
+    CloseFile();
+}
+
+bool FileOutputAIMC::OpenFile(const char* filename, float frame_period_ms) {
+  if (file_handle_ != NULL) {
+    LOG_ERROR(_T("Couldn't open output file. A file is already open."));
+    return false;
+  }
+
+  // Check that the output file exists and is writeable
+  if ((file_handle_ = fopen(filename, "wb")) == NULL) {
+    LOG_ERROR(_T("Couldn't open output file '%s' for writing."), filename);
+    return false;
+  }
+  sample_count_ = 0;
+  frame_period_ms_ = frame_period_ms;
+  header_written_ = false;
+  if (initialized_) {
+    WriteHeader();
+  }
+  return true;
+}
+
+bool FileOutputAIMC::InitializeInternal(const SignalBank &input) {
+  if (file_handle_ == NULL) {
+    LOG_ERROR(_T("Couldn't initialize file output. "
+                 "Please call FileOutputAIMC::OpenFile first"));
+    return false;
+  }
+  if (header_written_) {
+    LOG_ERROR(_T("A header has already been written on the output file. "
+                 "Please call FileOutputAIMC::CloseFile to close that file, "
+                 "and FileOutputAIMC::OpenFile to open an new one before "
+                 "calling FileOutputAIMC::Initialize again."));
+    return false;
+  }
+  channel_count_ = input.channel_count();
+  buffer_length_ = input.buffer_length();	
+  sample_rate_ = input.sample_rate();	
+  WriteHeader();
+  return true;
+}
+
+void FileOutputAIMC::ResetInternal() {
+  if (file_handle_ != NULL && !header_written_) {
+    WriteHeader();
+  }
+  if (file_handle_ != NULL)
+    CloseFile();
+}
+
+void FileOutputAIMC::WriteHeader() {
+  if (header_written_)
+    return;
+
+  /* File format:
+   * Header: Number of frames (uint32),
+   *         Frame period in milliseconds (float32),
+   *         Number of channels per frame (uint32),
+   *         Number of samples per channel of each frame (uint32)
+   *         Sample rate (float32)
+   *
+   * Data: Series of floats, by time, then channel, then frame
+   * f1c1t1,f1c1t2,f1c1t3...
+   */
+
+  uint32_t sample_count_out = sample_count_;
+  float sample_period_out = frame_period_ms_;
+  uint32_t channels_out = channel_count_;
+  uint32_t samples_out = buffer_length_;
+  float sample_rate = sample_rate_;
+
+  fwrite(&sample_count_out, sizeof(sample_count_out), 1, file_handle_);
+  fwrite(&sample_period_out, sizeof(sample_period_out), 1, file_handle_);
+  fwrite(&channels_out, sizeof(channels_out), 1, file_handle_);
+  fwrite(&samples_out, sizeof(samples_out), 1, file_handle_);
+  fwrite(&sample_rate, sizeof(sample_rate), 1, file_handle_);
+  fflush(file_handle_);
+
+  header_written_ = true;
+}
+
+void FileOutputAIMC::Process(const SignalBank &input) {
+  if (file_handle_ == NULL) {
+    LOG_ERROR(_T("Couldn't process file output. No file is open."
+                 "Please call FileOutputAIMC::OpenFile first"));
+    return;
+  }
+
+  if (!header_written_) {
+    LOG_ERROR(_T("No header has been written on the output file yet. Please "
+                 "call FileOutputAIMC::Initialize() before calling "
+                 "FileOutputAIMC::Process()"));
+    return;
+  }
+  float s;
+
+  for (int ch = 0; ch < input.channel_count(); ch++) {
+    for (int i = 0; i < input.buffer_length(); i++) {
+      s = input.sample(ch, i);
+      fwrite(&s, sizeof(s), 1, file_handle_);
+    }
+  }
+  sample_count_++;
+}
+
+bool FileOutputAIMC::CloseFile() {
+  if (file_handle_ == NULL)
+    return false;
+
+  // Write the first 4 bytes of the file
+  // with how many samples there are in the file
+  fflush(file_handle_);
+  rewind(file_handle_);
+  fflush(file_handle_);
+  uint32_t samples = sample_count_;
+  fwrite(&samples, sizeof(samples), 1, file_handle_);
+
+  // And close the file
+  fclose(file_handle_);
+  file_handle_ = NULL;
+  header_written_ = false;
+  return true;
+}
+}  // namespace aimc
+