annotate src/Modules/Input/ModuleFileInput.cc @ 6:8c859ef1fb75

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