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