Resampler.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
00002 /*
00003     Sonic Visualiser
00004     An audio file viewer and annotation editor.
00005     Centre for Digital Music, Queen Mary, University of London.
00006     
00007     This program is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License as
00009     published by the Free Software Foundation; either version 2 of the
00010     License, or (at your option) any later version.  See the file
00011     COPYING included with this distribution for more information.
00012 */
00013 
00014 /*
00015    This is a modified version of a source file from the 
00016    Rubber Band audio timestretcher library.
00017    This file copyright 2007 Chris Cannam.
00018 */
00019 
00020 #include "Resampler.h"
00021 
00022 #include <cstdlib>
00023 #include <cmath>
00024 
00025 #include <iostream>
00026 
00027 #include <samplerate.h>
00028 
00029 class Resampler::D
00030 {
00031 public:
00032     D(Quality quality, size_t channels, size_t chunkSize);
00033     ~D();
00034 
00035     size_t resample(float **in, float **out,
00036                     size_t incount, float ratio,
00037                     bool final);
00038 
00039     size_t resampleInterleaved(float *in, float *out,
00040                                size_t incount, float ratio,
00041                                bool final);
00042 
00043     void reset();
00044 
00045 protected:
00046     SRC_STATE *m_src;
00047     float *m_iin;
00048     float *m_iout;
00049     size_t m_channels;
00050     size_t m_iinsize;
00051     size_t m_ioutsize;
00052 };
00053 
00054 Resampler::D::D(Quality quality, size_t channels, size_t chunkSize) :
00055     m_src(0),
00056     m_iin(0),
00057     m_iout(0),
00058     m_channels(channels),
00059     m_iinsize(0),
00060     m_ioutsize(0)
00061 {
00062     int err = 0;
00063     m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY :
00064                     quality == Fastest ? SRC_LINEAR :
00065                     SRC_SINC_FASTEST,
00066                     channels, &err);
00067 
00069 
00070     if (chunkSize > 0 && m_channels > 1) {
00072         m_iinsize = chunkSize * m_channels;
00073         m_ioutsize = chunkSize * m_channels * 2;
00074         m_iin = (float *)malloc(m_iinsize * sizeof(float));
00075         m_iout = (float *)malloc(m_ioutsize * sizeof(float));
00076     }
00077 }
00078 
00079 Resampler::D::~D()
00080 {
00081     src_delete(m_src);
00082     if (m_iinsize > 0) {
00083         free(m_iin);
00084     }
00085     if (m_ioutsize > 0) {
00086         free(m_iout);
00087     }
00088 }
00089 
00090 size_t
00091 Resampler::D::resample(float **in, float **out,
00092                        size_t incount, float ratio,
00093                        bool final)
00094 {
00095     if (m_channels == 1) {
00096         return resampleInterleaved(*in, *out, incount, ratio, final);
00097     }
00098 
00099     size_t outcount = lrintf(ceilf(incount * ratio));
00100 
00101     if (incount * m_channels > m_iinsize) {
00102         m_iinsize = incount * m_channels;
00103         m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float));
00104     }
00105     if (outcount * m_channels > m_ioutsize) {
00106         m_ioutsize = outcount * m_channels;
00107         m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float));
00108     }
00109     for (size_t i = 0; i < incount; ++i) {
00110         for (size_t c = 0; c < m_channels; ++c) {
00111             m_iin[i * m_channels + c] = in[c][i];
00112         }
00113     }
00114     
00115     size_t gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final);
00116 
00117     for (size_t i = 0; i < gen; ++i) {
00118         for (size_t c = 0; c < m_channels; ++c) {
00119             out[c][i] = m_iout[i * m_channels + c];
00120         }
00121     }
00122 
00123     return gen;
00124 }
00125 
00126 size_t
00127 Resampler::D::resampleInterleaved(float *in, float *out,
00128                                   size_t incount, float ratio,
00129                                   bool final)
00130 {
00131     SRC_DATA data;
00132 
00133     size_t outcount = lrintf(ceilf(incount * ratio));
00134 
00135     data.data_in = in;
00136     data.data_out = out;
00137     data.input_frames = incount;
00138     data.output_frames = outcount;
00139     data.src_ratio = ratio;
00140     data.end_of_input = (final ? 1 : 0);
00141 
00142     int err = src_process(m_src, &data);
00143 
00145 
00146     return data.output_frames_gen;
00147 }
00148 
00149 void
00150 Resampler::D::reset()
00151 {
00152     src_reset(m_src);
00153 }
00154 
00155 Resampler::Resampler(Quality quality, size_t channels, size_t chunkSize)
00156 {
00157     m_d = new D(quality, channels, chunkSize);
00158 }
00159 
00160 Resampler::~Resampler()
00161 {
00162     delete m_d;
00163 }
00164 
00165 size_t 
00166 Resampler::resample(float **in, float **out,
00167                     size_t incount, float ratio,
00168                     bool final)
00169 {
00170     return m_d->resample(in, out, incount, ratio, final);
00171 }
00172 
00173 size_t 
00174 Resampler::resampleInterleaved(float *in, float *out,
00175                     size_t incount, float ratio,
00176                     bool final)
00177 {
00178     return m_d->resampleInterleaved(in, out, incount, ratio, final);
00179 }
00180 
00181 void
00182 Resampler::reset()
00183 {
00184     m_d->reset();
00185 }
00186 

Generated on Wed Feb 20 15:45:27 2008 for SonicVisualiser by  doxygen 1.5.1