tomwalters@275: // Copyright 2006-2010, Willem van Engen, Thomas Walters tomwalters@275: // tomwalters@275: // AIM-C: A C++ implementation of the Auditory Image Model tomwalters@275: // http://www.acousticscale.org/AIMC tomwalters@275: // tomwalters@318: // Licensed under the Apache License, Version 2.0 (the "License"); tomwalters@318: // you may not use this file except in compliance with the License. tomwalters@318: // You may obtain a copy of the License at tomwalters@275: // tomwalters@318: // http://www.apache.org/licenses/LICENSE-2.0 tomwalters@275: // tomwalters@318: // Unless required by applicable law or agreed to in writing, software tomwalters@318: // distributed under the License is distributed on an "AS IS" BASIS, tomwalters@318: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. tomwalters@318: // See the License for the specific language governing permissions and tomwalters@318: // limitations under the License. tomwalters@275: tomwalters@275: /*! \file tomwalters@275: * \brief Audio file input tomwalters@275: * tomwalters@275: * \author Willem van Engen tomwalters@275: * \author Thomas Walters tomwalters@275: * \date created 2006/09/21 tomwalters@275: * \version \$Id$ tomwalters@275: */ tomwalters@275: tomwalters@275: #include tomwalters@275: tomwalters@275: #include "Modules/Input/ModuleFileInput.h" tomwalters@275: tomwalters@275: namespace aimc { tomwalters@275: ModuleFileInput::ModuleFileInput(Parameters *params) : Module(params) { tomwalters@278: module_description_ = "File input using libsndfile"; tomwalters@278: module_identifier_ = "file_input"; tomwalters@278: module_type_ = "input"; tomwalters@278: module_version_ = "$Id$"; tomwalters@278: tomwalters@279: file_handle_ = NULL; tomwalters@279: buffer_length_ = parameters_->DefaultInt("input.buffersize", 1024); tomwalters@275: tomwalters@275: file_position_samples_ = 0; tomwalters@275: file_loaded_ = false; tomwalters@275: audio_channels_ = 0; tomwalters@275: sample_rate_ = 0.0f; tomwalters@275: } tomwalters@275: tomwalters@275: ModuleFileInput::~ModuleFileInput() { tomwalters@292: if (file_handle_ != NULL) { tomwalters@279: sf_close(file_handle_); tomwalters@292: file_handle_ = NULL; tomwalters@292: } tomwalters@275: } tomwalters@275: tomwalters@275: void ModuleFileInput::ResetInternal() { tomwalters@292: // If there's a file open. Close it. tomwalters@292: if (file_handle_ != NULL) { tomwalters@292: sf_close(file_handle_); tomwalters@292: file_handle_ = NULL; tomwalters@292: } tom@420: // Open a file tomwalters@279: SF_INFO sfinfo; tomwalters@280: memset(reinterpret_cast(&sfinfo), 0, sizeof(SF_INFO)); tomwalters@292: tomwalters@402: file_loaded_ = false; tomwalters@402: file_handle_ = sf_open(global_parameters_->GetString("input_filename"), tomwalters@402: SFM_READ, tomwalters@402: &sfinfo); tomwalters@275: tomwalters@279: if (file_handle_ == NULL) { tomwalters@280: /*! \todo Also display error reason tomwalters@280: */ tomwalters@402: LOG_ERROR(_T("Couldn't read audio file '%s'"), tomwalters@402: global_parameters_->GetString("input_filename")); tom@420: return; tomwalters@279: } tomwalters@402: tomwalters@275: file_loaded_ = true; tomwalters@402: done_ = false; tomwalters@275: audio_channels_ = sfinfo.channels; tomwalters@275: sample_rate_ = sfinfo.samplerate; tomwalters@279: file_position_samples_ = 0; tomwalters@275: tomwalters@402: if (audio_channels_ < 1 || buffer_length_ < 1 || sample_rate_ < 0.0f) { tomwalters@402: LOG_ERROR(_T("Problem with file: audio_channels = %d, buffer_length_ = %d, sample_rate = %f"), audio_channels_, buffer_length_, sample_rate_); tom@420: return; tomwalters@402: } tomwalters@275: tomwalters@402: output_.Initialize(audio_channels_, buffer_length_, sample_rate_); tomwalters@402: output_.set_start_time(0); tom@420: } tom@420: tom@420: bool ModuleFileInput::InitializeInternal(const SignalBank& input) { tom@420: ResetInternal(); tomwalters@402: return true; tomwalters@275: } tomwalters@275: tomwalters@275: void ModuleFileInput::Process(const SignalBank& input) { tomwalters@278: if (!file_loaded_) tomwalters@278: return; tomwalters@279: sf_count_t read; tomwalters@275: vector buffer; tomwalters@275: buffer.resize(buffer_length_ * audio_channels_); tomwalters@275: tomwalters@402: // Read buffersize bytes into buffer tomwalters@402: read = sf_readf_float(file_handle_, &buffer[0], buffer_length_); hamel@449: tomwalters@402: // Place the contents of the buffer into the signal bank tomwalters@402: int counter = 0; hamel@448: for (int i = 0; i < read; ++i) { hamel@448: for (int c = 0; c < audio_channels_; ++c) { tomwalters@402: output_.set_sample(c, i, buffer[counter]); tomwalters@402: ++counter; tomwalters@402: } tomwalters@402: } tomwalters@275: tom@442: // If the number of samples read is less than the buffer length, the end tomwalters@402: // of the file has been reached. tomwalters@402: if (read < buffer_length_) { tomwalters@402: // Zero samples at end hamel@448: for (int i = read; i < buffer_length_; ++i) { hamel@448: for (int c = 0; c < audio_channels_; ++c) { tomwalters@402: output_.set_sample(c, i, 0.0f); tomwalters@275: } tomwalters@275: } tomwalters@402: // When we're past the end of the buffer, set the tomwalters@402: // module state to 'done' and exit. tomwalters@402: if (read == 0) tomwalters@402: done_ = true; tomwalters@402: return; tomwalters@402: } tomwalters@275: tomwalters@402: // Update time. tomwalters@402: output_.set_start_time(file_position_samples_); tomwalters@402: file_position_samples_ += read; tomwalters@402: PushOutput(); tomwalters@275: } tomwalters@275: } // namespace aimc