diff trunk/src/Modules/Input/ModuleFileInput.cc @ 275:ce2bab04f155

- Imported file input using libsndfile from old AIM-C and updated to the new API - Modified the Module base class to propogate Reset() calls down the module chain. - This required changing all Reset() functions in subclasses to ResetInternal() - Removed some unneeded imports from the Gaussians test
author tomwalters
date Tue, 16 Feb 2010 18:00:16 +0000
parents
children 5b8b9ea1218a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/Modules/Input/ModuleFileInput.cc	Tue Feb 16 18:00:16 2010 +0000
@@ -0,0 +1,139 @@
+// Copyright 2006-2010, Willem van Engen, Thomas Walters
+//
+// AIM-C: A C++ implementation of the Auditory Image Model
+// http://www.acousticscale.org/AIMC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+/*! \file
+ *  \brief Audio file input
+ *
+ *  \author Willem van Engen <cnbh@willem.engen.nl>
+ *  \author Thomas Walters <tom@acousticscale.org>
+ *  \date created 2006/09/21
+ *  \version \$Id$
+ */
+
+#include <vector>
+
+#include "Modules/Input/ModuleFileInput.h"
+
+namespace aimc {
+ModuleFileInput::ModuleFileInput(Parameters *params) : Module(params) {
+	file_handle_ = NULL;
+	buffer_length_ = parameters_->DefaultInt("input.buffersize", 1024);
+
+  file_position_samples_ = 0;
+  file_loaded_ = false;
+  audio_channels_ = 0;
+  buffer_length_ = 0;
+  sample_rate_ = 0.0f;
+}
+
+ModuleFileInput::~ModuleFileInput() {
+  if (file_handle_)
+	  sf_close(file_handle_);
+}
+
+void ModuleFileInput::ResetInternal() {
+  output_.Initialize(audio_channels_, buffer_length_, sample_rate_);
+  output_.set_start_time(0);
+}
+
+bool ModuleFileInput::LoadFile(const char* filename) {
+	// Open the file
+	SF_INFO sfinfo;
+	memset((void*)&sfinfo, 0, sizeof(SF_INFO));
+	file_handle_ = sf_open(filename, SFM_READ, &sfinfo);
+
+	if (file_handle_ == NULL) {
+		//! \todo Also display error reason
+		LOG_ERROR(_T("Couldn't read audio file '%s'"), filename);
+		return false;
+	}
+
+  file_loaded_ = true;
+  audio_channels_ = sfinfo.channels;
+  sample_rate_ = sfinfo.samplerate;
+	file_position_samples_ = 0;
+
+  // A dummy signal bank to be passed to the Initialize() function.
+  SignalBank s;
+  s.Initialize(1, 1, 1);
+
+	// Self-initialize by calling Module::Initialize() explicitly. 
+	// The Initialize() call in this subclass is overloaded to prevent it from
+	// being called drectly. 
+  return Module::Initialize(s);
+}
+
+bool ModuleFileInput::Initialize(const SignalBank& input) {
+  LOG_ERROR(_T("Do not call Initialize() on ModuleFileInput directly "
+               "instead call LoadFile() with a filename to load. "
+               "This will automatically initialize the module."));
+  return false;
+}
+
+void ModuleFileInput::Process(const SignalBank& input) {
+  LOG_ERROR(_T("Call Process() on ModuleFileInput instead of passing in "
+               "a SignalBank"));
+}
+
+bool ModuleFileInput::InitializeInternal(const SignalBank& input) {
+  if (!file_loaded_)
+    return false;
+  ResetInternal();
+	return true;
+}
+
+void ModuleFileInput::Process() {
+	sf_count_t read;
+  vector<float> buffer;
+  buffer.resize(buffer_length_ * audio_channels_);
+
+  while (true) {
+	  // Read buffersize bytes into buffer
+	  read = sf_readf_float(file_handle_, &buffer[0], buffer_length_);
+
+    // Place the contents of the buffer into the signal bank
+    int counter = 0;
+    for (int c = 0; c < audio_channels_; ++c) {
+      for (int i = 0; i < read; ++i) {
+        output_.set_sample(c, i, buffer[counter]);
+        ++counter;
+      }
+    }
+
+	  // If the number of saples read is less than the buffer length, the end 
+	  // of the file has been reached.
+	  if (read < buffer_length_) {
+		  // Zero samples at end
+		  for (int c = 0; c < audio_channels_; ++c) {
+        for (int i = read; i < buffer_length_; ++i) {
+          output_.set_sample(c, i, 0.0f);
+        }
+      }
+		  // When we're past the end of the buffer, stop looping.
+		  if (read == 0)
+        break;
+	  }
+
+	  // Update time
+	  output_.set_start_time(file_position_samples_);
+	  file_position_samples_ += read;
+
+    PushOutput();
+  }
+}
+}  // namespace aimc