annotate 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
rev   line source
tomwalters@275 1 // Copyright 2006-2010, Willem van Engen, Thomas Walters
tomwalters@275 2 //
tomwalters@275 3 // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@275 4 // http://www.acousticscale.org/AIMC
tomwalters@275 5 //
tomwalters@275 6 // This program is free software: you can redistribute it and/or modify
tomwalters@275 7 // it under the terms of the GNU General Public License as published by
tomwalters@275 8 // the Free Software Foundation, either version 3 of the License, or
tomwalters@275 9 // (at your option) any later version.
tomwalters@275 10 //
tomwalters@275 11 // This program is distributed in the hope that it will be useful,
tomwalters@275 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
tomwalters@275 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
tomwalters@275 14 // GNU General Public License for more details.
tomwalters@275 15 //
tomwalters@275 16 // You should have received a copy of the GNU General Public License
tomwalters@275 17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
tomwalters@275 18
tomwalters@275 19 /*! \file
tomwalters@275 20 * \brief Audio file input
tomwalters@275 21 *
tomwalters@275 22 * \author Willem van Engen <cnbh@willem.engen.nl>
tomwalters@275 23 * \author Thomas Walters <tom@acousticscale.org>
tomwalters@275 24 * \date created 2006/09/21
tomwalters@275 25 * \version \$Id$
tomwalters@275 26 */
tomwalters@275 27
tomwalters@275 28 #include <vector>
tomwalters@275 29
tomwalters@275 30 #include "Modules/Input/ModuleFileInput.h"
tomwalters@275 31
tomwalters@275 32 namespace aimc {
tomwalters@275 33 ModuleFileInput::ModuleFileInput(Parameters *params) : Module(params) {
tomwalters@275 34 file_handle_ = NULL;
tomwalters@275 35 buffer_length_ = parameters_->DefaultInt("input.buffersize", 1024);
tomwalters@275 36
tomwalters@275 37 file_position_samples_ = 0;
tomwalters@275 38 file_loaded_ = false;
tomwalters@275 39 audio_channels_ = 0;
tomwalters@275 40 buffer_length_ = 0;
tomwalters@275 41 sample_rate_ = 0.0f;
tomwalters@275 42 }
tomwalters@275 43
tomwalters@275 44 ModuleFileInput::~ModuleFileInput() {
tomwalters@275 45 if (file_handle_)
tomwalters@275 46 sf_close(file_handle_);
tomwalters@275 47 }
tomwalters@275 48
tomwalters@275 49 void ModuleFileInput::ResetInternal() {
tomwalters@275 50 output_.Initialize(audio_channels_, buffer_length_, sample_rate_);
tomwalters@275 51 output_.set_start_time(0);
tomwalters@275 52 }
tomwalters@275 53
tomwalters@275 54 bool ModuleFileInput::LoadFile(const char* filename) {
tomwalters@275 55 // Open the file
tomwalters@275 56 SF_INFO sfinfo;
tomwalters@275 57 memset((void*)&sfinfo, 0, sizeof(SF_INFO));
tomwalters@275 58 file_handle_ = sf_open(filename, SFM_READ, &sfinfo);
tomwalters@275 59
tomwalters@275 60 if (file_handle_ == NULL) {
tomwalters@275 61 //! \todo Also display error reason
tomwalters@275 62 LOG_ERROR(_T("Couldn't read audio file '%s'"), filename);
tomwalters@275 63 return false;
tomwalters@275 64 }
tomwalters@275 65
tomwalters@275 66 file_loaded_ = true;
tomwalters@275 67 audio_channels_ = sfinfo.channels;
tomwalters@275 68 sample_rate_ = sfinfo.samplerate;
tomwalters@275 69 file_position_samples_ = 0;
tomwalters@275 70
tomwalters@275 71 // A dummy signal bank to be passed to the Initialize() function.
tomwalters@275 72 SignalBank s;
tomwalters@275 73 s.Initialize(1, 1, 1);
tomwalters@275 74
tomwalters@275 75 // Self-initialize by calling Module::Initialize() explicitly.
tomwalters@275 76 // The Initialize() call in this subclass is overloaded to prevent it from
tomwalters@275 77 // being called drectly.
tomwalters@275 78 return Module::Initialize(s);
tomwalters@275 79 }
tomwalters@275 80
tomwalters@275 81 bool ModuleFileInput::Initialize(const SignalBank& input) {
tomwalters@275 82 LOG_ERROR(_T("Do not call Initialize() on ModuleFileInput directly "
tomwalters@275 83 "instead call LoadFile() with a filename to load. "
tomwalters@275 84 "This will automatically initialize the module."));
tomwalters@275 85 return false;
tomwalters@275 86 }
tomwalters@275 87
tomwalters@275 88 void ModuleFileInput::Process(const SignalBank& input) {
tomwalters@275 89 LOG_ERROR(_T("Call Process() on ModuleFileInput instead of passing in "
tomwalters@275 90 "a SignalBank"));
tomwalters@275 91 }
tomwalters@275 92
tomwalters@275 93 bool ModuleFileInput::InitializeInternal(const SignalBank& input) {
tomwalters@275 94 if (!file_loaded_)
tomwalters@275 95 return false;
tomwalters@275 96 ResetInternal();
tomwalters@275 97 return true;
tomwalters@275 98 }
tomwalters@275 99
tomwalters@275 100 void ModuleFileInput::Process() {
tomwalters@275 101 sf_count_t read;
tomwalters@275 102 vector<float> buffer;
tomwalters@275 103 buffer.resize(buffer_length_ * audio_channels_);
tomwalters@275 104
tomwalters@275 105 while (true) {
tomwalters@275 106 // Read buffersize bytes into buffer
tomwalters@275 107 read = sf_readf_float(file_handle_, &buffer[0], buffer_length_);
tomwalters@275 108
tomwalters@275 109 // Place the contents of the buffer into the signal bank
tomwalters@275 110 int counter = 0;
tomwalters@275 111 for (int c = 0; c < audio_channels_; ++c) {
tomwalters@275 112 for (int i = 0; i < read; ++i) {
tomwalters@275 113 output_.set_sample(c, i, buffer[counter]);
tomwalters@275 114 ++counter;
tomwalters@275 115 }
tomwalters@275 116 }
tomwalters@275 117
tomwalters@275 118 // If the number of saples read is less than the buffer length, the end
tomwalters@275 119 // of the file has been reached.
tomwalters@275 120 if (read < buffer_length_) {
tomwalters@275 121 // Zero samples at end
tomwalters@275 122 for (int c = 0; c < audio_channels_; ++c) {
tomwalters@275 123 for (int i = read; i < buffer_length_; ++i) {
tomwalters@275 124 output_.set_sample(c, i, 0.0f);
tomwalters@275 125 }
tomwalters@275 126 }
tomwalters@275 127 // When we're past the end of the buffer, stop looping.
tomwalters@275 128 if (read == 0)
tomwalters@275 129 break;
tomwalters@275 130 }
tomwalters@275 131
tomwalters@275 132 // Update time
tomwalters@275 133 output_.set_start_time(file_position_samples_);
tomwalters@275 134 file_position_samples_ += read;
tomwalters@275 135
tomwalters@275 136 PushOutput();
tomwalters@275 137 }
tomwalters@275 138 }
tomwalters@275 139 } // namespace aimc