Chris@297: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@297: /* Chris@297: Sonic Visualiser Chris@297: An audio file viewer and annotation editor. Chris@297: Centre for Digital Music, Queen Mary, University of London. Chris@297: Chris@297: This program is free software; you can redistribute it and/or Chris@297: modify it under the terms of the GNU General Public License as Chris@297: published by the Free Software Foundation; either version 2 of the Chris@297: License, or (at your option) any later version. See the file Chris@297: COPYING included with this distribution for more information. Chris@297: */ Chris@297: Chris@297: /* Chris@297: This is a modified version of a source file from the Chris@297: Rubber Band audio timestretcher library. Chris@297: This file copyright 2007 Chris Cannam. Chris@297: */ Chris@297: Chris@297: #include "Resampler.h" Chris@297: Chris@297: #include Chris@297: #include Chris@297: Chris@297: #include Chris@297: Chris@297: #include Chris@297: Chris@297: class Resampler::D Chris@297: { Chris@297: public: Chris@297: D(Quality quality, size_t channels, size_t chunkSize); Chris@297: ~D(); Chris@297: Chris@297: size_t resample(float **in, float **out, Chris@297: size_t incount, float ratio, Chris@297: bool final); Chris@297: Chris@297: size_t resampleInterleaved(float *in, float *out, Chris@297: size_t incount, float ratio, Chris@297: bool final); Chris@297: Chris@297: void reset(); Chris@297: Chris@297: protected: Chris@297: SRC_STATE *m_src; Chris@297: float *m_iin; Chris@297: float *m_iout; Chris@297: size_t m_channels; Chris@297: size_t m_iinsize; Chris@297: size_t m_ioutsize; Chris@297: }; Chris@297: Chris@297: Resampler::D::D(Quality quality, size_t channels, size_t chunkSize) : Chris@297: m_src(0), Chris@297: m_iin(0), Chris@297: m_iout(0), Chris@297: m_channels(channels), Chris@297: m_iinsize(0), Chris@297: m_ioutsize(0) Chris@297: { Chris@297: int err = 0; Chris@297: m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY : Chris@297: quality == Fastest ? SRC_LINEAR : Chris@297: SRC_SINC_FASTEST, Chris@297: channels, &err); Chris@297: Chris@297: //!!! check err, throw Chris@297: Chris@297: if (chunkSize > 0 && m_channels > 1) { Chris@297: //!!! alignment? Chris@297: m_iinsize = chunkSize * m_channels; Chris@297: m_ioutsize = chunkSize * m_channels * 2; Chris@297: m_iin = (float *)malloc(m_iinsize * sizeof(float)); Chris@297: m_iout = (float *)malloc(m_ioutsize * sizeof(float)); Chris@297: } Chris@297: } Chris@297: Chris@297: Resampler::D::~D() Chris@297: { Chris@297: src_delete(m_src); Chris@297: if (m_iinsize > 0) { Chris@297: free(m_iin); Chris@297: } Chris@297: if (m_ioutsize > 0) { Chris@297: free(m_iout); Chris@297: } Chris@297: } Chris@297: Chris@297: size_t Chris@297: Resampler::D::resample(float **in, float **out, Chris@297: size_t incount, float ratio, Chris@297: bool final) Chris@297: { Chris@297: if (m_channels == 1) { Chris@297: return resampleInterleaved(*in, *out, incount, ratio, final); Chris@297: } Chris@297: Chris@297: size_t outcount = lrintf(ceilf(incount * ratio)); Chris@297: Chris@297: if (incount * m_channels > m_iinsize) { Chris@297: m_iinsize = incount * m_channels; Chris@297: m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float)); Chris@297: } Chris@297: if (outcount * m_channels > m_ioutsize) { Chris@297: m_ioutsize = outcount * m_channels; Chris@297: m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float)); Chris@297: } Chris@297: for (size_t i = 0; i < incount; ++i) { Chris@297: for (size_t c = 0; c < m_channels; ++c) { Chris@297: m_iin[i * m_channels + c] = in[c][i]; Chris@297: } Chris@297: } Chris@297: Chris@297: size_t gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final); Chris@297: Chris@297: for (size_t i = 0; i < gen; ++i) { Chris@297: for (size_t c = 0; c < m_channels; ++c) { Chris@297: out[c][i] = m_iout[i * m_channels + c]; Chris@297: } Chris@297: } Chris@297: Chris@297: return gen; Chris@297: } Chris@297: Chris@297: size_t Chris@297: Resampler::D::resampleInterleaved(float *in, float *out, Chris@297: size_t incount, float ratio, Chris@297: bool final) Chris@297: { Chris@297: SRC_DATA data; Chris@297: Chris@297: size_t outcount = lrintf(ceilf(incount * ratio)); Chris@297: Chris@297: data.data_in = in; Chris@297: data.data_out = out; Chris@297: data.input_frames = incount; Chris@297: data.output_frames = outcount; Chris@297: data.src_ratio = ratio; Chris@297: data.end_of_input = (final ? 1 : 0); Chris@297: Chris@297: int err = src_process(m_src, &data); Chris@297: Chris@297: //!!! check err, respond appropriately Chris@297: Chris@297: return data.output_frames_gen; Chris@297: } Chris@297: Chris@297: void Chris@297: Resampler::D::reset() Chris@297: { Chris@297: src_reset(m_src); Chris@297: } Chris@297: Chris@297: Resampler::Resampler(Quality quality, size_t channels, size_t chunkSize) Chris@297: { Chris@297: m_d = new D(quality, channels, chunkSize); Chris@297: } Chris@297: Chris@297: Resampler::~Resampler() Chris@297: { Chris@297: delete m_d; Chris@297: } Chris@297: Chris@297: size_t Chris@297: Resampler::resample(float **in, float **out, Chris@297: size_t incount, float ratio, Chris@297: bool final) Chris@297: { Chris@297: return m_d->resample(in, out, incount, ratio, final); Chris@297: } Chris@297: Chris@297: size_t Chris@297: Resampler::resampleInterleaved(float *in, float *out, Chris@297: size_t incount, float ratio, Chris@297: bool final) Chris@297: { Chris@297: return m_d->resampleInterleaved(in, out, incount, ratio, final); Chris@297: } Chris@297: Chris@297: void Chris@297: Resampler::reset() Chris@297: { Chris@297: m_d->reset(); Chris@297: } Chris@297: