tomwalters@3: // Copyright 2006-2010, Willem van Engen, Thomas Walters
tomwalters@3: //
tomwalters@3: // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@3: // http://www.acousticscale.org/AIMC
tomwalters@3: //
tomwalters@3: // This program is free software: you can redistribute it and/or modify
tomwalters@3: // it under the terms of the GNU General Public License as published by
tomwalters@3: // the Free Software Foundation, either version 3 of the License, or
tomwalters@3: // (at your option) any later version.
tomwalters@3: //
tomwalters@3: // This program is distributed in the hope that it will be useful,
tomwalters@3: // but WITHOUT ANY WARRANTY; without even the implied warranty of
tomwalters@3: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
tomwalters@3: // GNU General Public License for more details.
tomwalters@3: //
tomwalters@3: // You should have received a copy of the GNU General Public License
tomwalters@3: // along with this program. If not, see .
tomwalters@3:
tomwalters@3: /*! \file
tomwalters@3: * \brief Audio file input
tomwalters@3: *
tomwalters@3: * \author Willem van Engen
tomwalters@3: * \author Thomas Walters
tomwalters@3: * \date created 2006/09/21
tomwalters@3: * \version \$Id$
tomwalters@3: */
tomwalters@3:
tomwalters@3: #include
tomwalters@3:
tomwalters@3: #include "Modules/Input/ModuleFileInput.h"
tomwalters@3:
tomwalters@3: namespace aimc {
tomwalters@3: ModuleFileInput::ModuleFileInput(Parameters *params) : Module(params) {
tomwalters@6: module_description_ = "File input using libsndfile";
tomwalters@6: module_identifier_ = "file_input";
tomwalters@6: module_type_ = "input";
tomwalters@6: module_version_ = "$Id$";
tomwalters@6:
tomwalters@7: file_handle_ = NULL;
tomwalters@7: buffer_length_ = parameters_->DefaultInt("input.buffersize", 1024);
tomwalters@3:
tomwalters@3: file_position_samples_ = 0;
tomwalters@3: file_loaded_ = false;
tomwalters@3: audio_channels_ = 0;
tomwalters@3: sample_rate_ = 0.0f;
tomwalters@3: }
tomwalters@3:
tomwalters@3: ModuleFileInput::~ModuleFileInput() {
tomwalters@20: if (file_handle_ != NULL) {
tomwalters@7: sf_close(file_handle_);
tomwalters@20: file_handle_ = NULL;
tomwalters@20: }
tomwalters@3: }
tomwalters@3:
tomwalters@3: void ModuleFileInput::ResetInternal() {
tomwalters@3: output_.Initialize(audio_channels_, buffer_length_, sample_rate_);
tomwalters@3: output_.set_start_time(0);
tomwalters@3: }
tomwalters@3:
tomwalters@3: bool ModuleFileInput::LoadFile(const char* filename) {
tomwalters@20: // If there's a file open. Close it.
tomwalters@20: if (file_handle_ != NULL) {
tomwalters@20: sf_close(file_handle_);
tomwalters@20: file_handle_ = NULL;
tomwalters@20: }
tomwalters@7: // Open the file
tomwalters@7: SF_INFO sfinfo;
tomwalters@8: memset(reinterpret_cast(&sfinfo), 0, sizeof(SF_INFO));
tomwalters@20:
tomwalters@7: file_handle_ = sf_open(filename, SFM_READ, &sfinfo);
tomwalters@3:
tomwalters@7: if (file_handle_ == NULL) {
tomwalters@8: /*! \todo Also display error reason
tomwalters@8: */
tomwalters@7: LOG_ERROR(_T("Couldn't read audio file '%s'"), filename);
tomwalters@7: return false;
tomwalters@7: }
tomwalters@3:
tomwalters@3: file_loaded_ = true;
tomwalters@3: audio_channels_ = sfinfo.channels;
tomwalters@3: sample_rate_ = sfinfo.samplerate;
tomwalters@7: file_position_samples_ = 0;
tomwalters@3:
tomwalters@3: // A dummy signal bank to be passed to the Initialize() function.
tomwalters@3: SignalBank s;
tomwalters@3: s.Initialize(1, 1, 1);
tomwalters@3:
tomwalters@7: // Self-initialize by calling Module::Initialize() explicitly.
tomwalters@7: // The Initialize() call in this subclass is overloaded to prevent it from
tomwalters@7: // being called drectly.
tomwalters@3: return Module::Initialize(s);
tomwalters@3: }
tomwalters@3:
tomwalters@6:
tomwalters@6: /* Do not call Initialize() on ModuleFileInput directly
tomwalters@6: * instead call LoadFile() with a filename to load.
tomwalters@6: * This will automatically initialize the module.
tomwalters@6: */
tomwalters@3: bool ModuleFileInput::Initialize(const SignalBank& input) {
tomwalters@3: LOG_ERROR(_T("Do not call Initialize() on ModuleFileInput directly "
tomwalters@3: "instead call LoadFile() with a filename to load. "
tomwalters@3: "This will automatically initialize the module."));
tomwalters@3: return false;
tomwalters@3: }
tomwalters@3:
tomwalters@3: void ModuleFileInput::Process(const SignalBank& input) {
tomwalters@3: LOG_ERROR(_T("Call Process() on ModuleFileInput instead of passing in "
tomwalters@3: "a SignalBank"));
tomwalters@3: }
tomwalters@3:
tomwalters@3: bool ModuleFileInput::InitializeInternal(const SignalBank& input) {
tomwalters@6: if (!file_loaded_) {
tomwalters@6: LOG_ERROR(_T("No file loaded in FileOutputHTK"));
tomwalters@3: return false;
tomwalters@6: }
tomwalters@6: if (audio_channels_ < 1 || buffer_length_ < 1 || sample_rate_ < 0.0f) {
tomwalters@6: LOG_ERROR(_T("audio_channels, buffer_length_ or sample_rate too small"));
tomwalters@6: return false;
tomwalters@6: }
tomwalters@3: ResetInternal();
tomwalters@7: return true;
tomwalters@3: }
tomwalters@3:
tomwalters@3: void ModuleFileInput::Process() {
tomwalters@6: if (!file_loaded_)
tomwalters@6: return;
tomwalters@7: sf_count_t read;
tomwalters@3: vector buffer;
tomwalters@3: buffer.resize(buffer_length_ * audio_channels_);
tomwalters@3:
tomwalters@3: while (true) {
tomwalters@7: // Read buffersize bytes into buffer
tomwalters@7: read = sf_readf_float(file_handle_, &buffer[0], buffer_length_);
tomwalters@3:
tomwalters@3: // Place the contents of the buffer into the signal bank
tomwalters@3: int counter = 0;
tomwalters@3: for (int c = 0; c < audio_channels_; ++c) {
tomwalters@3: for (int i = 0; i < read; ++i) {
tomwalters@3: output_.set_sample(c, i, buffer[counter]);
tomwalters@3: ++counter;
tomwalters@3: }
tomwalters@3: }
tomwalters@3:
tomwalters@7: // If the number of saples read is less than the buffer length, the end
tomwalters@7: // of the file has been reached.
tomwalters@7: if (read < buffer_length_) {
tomwalters@7: // Zero samples at end
tomwalters@7: for (int c = 0; c < audio_channels_; ++c) {
tomwalters@3: for (int i = read; i < buffer_length_; ++i) {
tomwalters@3: output_.set_sample(c, i, 0.0f);
tomwalters@3: }
tomwalters@3: }
tomwalters@7: // When we're past the end of the buffer, stop looping.
tomwalters@7: if (read == 0)
tomwalters@3: break;
tomwalters@7: }
tomwalters@3:
tomwalters@7: // Update time
tomwalters@7: output_.set_start_time(file_position_samples_);
tomwalters@7: file_position_samples_ += read;
tomwalters@3: PushOutput();
tomwalters@3: }
tomwalters@3: }
tomwalters@3: } // namespace aimc