svcore  1.9
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 #include "Debug.h"
00030 
00031 class Resampler::D
00032 {
00033 public:
00034     D(Quality quality, int channels, int chunkSize);
00035     ~D();
00036 
00037     int resample(float **in, float **out,
00038                     int incount, float ratio,
00039                     bool final);
00040 
00041     int resampleInterleaved(float *in, float *out,
00042                                int incount, float ratio,
00043                                bool final);
00044 
00045     void reset();
00046 
00047 protected:
00048     SRC_STATE *m_src;
00049     float *m_iin;
00050     float *m_iout;
00051     int m_channels;
00052     int m_iinsize;
00053     int m_ioutsize;
00054 };
00055 
00056 Resampler::D::D(Quality quality, int channels, int chunkSize) :
00057     m_src(0),
00058     m_iin(0),
00059     m_iout(0),
00060     m_channels(channels),
00061     m_iinsize(0),
00062     m_ioutsize(0)
00063 {
00064     int err = 0;
00065     m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY :
00066                     quality == Fastest ? SRC_LINEAR :
00067                     SRC_SINC_FASTEST,
00068                     channels, &err);
00069 
00071 
00072     if (chunkSize > 0 && m_channels > 1) {
00074         m_iinsize = chunkSize * m_channels;
00075         m_ioutsize = chunkSize * m_channels * 2;
00076         m_iin = (float *)malloc(m_iinsize * sizeof(float));
00077         m_iout = (float *)malloc(m_ioutsize * sizeof(float));
00078     }
00079 }
00080 
00081 Resampler::D::~D()
00082 {
00083     src_delete(m_src);
00084     if (m_iinsize > 0) {
00085         free(m_iin);
00086     }
00087     if (m_ioutsize > 0) {
00088         free(m_iout);
00089     }
00090 }
00091 
00092 int
00093 Resampler::D::resample(float **in, float **out,
00094                        int incount, float ratio,
00095                        bool final)
00096 {
00097     if (m_channels == 1) {
00098         return resampleInterleaved(*in, *out, incount, ratio, final);
00099     }
00100 
00101     int outcount = lrintf(ceilf(incount * ratio));
00102 
00103     if (incount * m_channels > m_iinsize) {
00104         m_iinsize = incount * m_channels;
00105         m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float));
00106     }
00107     if (outcount * m_channels > m_ioutsize) {
00108         m_ioutsize = outcount * m_channels;
00109         m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float));
00110     }
00111     for (int i = 0; i < incount; ++i) {
00112         for (int c = 0; c < m_channels; ++c) {
00113             m_iin[i * m_channels + c] = in[c][i];
00114         }
00115     }
00116     
00117     int gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final);
00118 
00119     for (int i = 0; i < gen; ++i) {
00120         for (int c = 0; c < m_channels; ++c) {
00121             out[c][i] = m_iout[i * m_channels + c];
00122         }
00123     }
00124 
00125     return gen;
00126 }
00127 
00128 int
00129 Resampler::D::resampleInterleaved(float *in, float *out,
00130                                   int incount, float ratio,
00131                                   bool final)
00132 {
00133     SRC_DATA data;
00134 
00135     int outcount = lrintf(ceilf(incount * ratio));
00136 
00137     data.data_in = in;
00138     data.data_out = out;
00139     data.input_frames = incount;
00140     data.output_frames = outcount;
00141     data.src_ratio = ratio;
00142     data.end_of_input = (final ? 1 : 0);
00143 
00144     int err = src_process(m_src, &data);
00145 
00146     if (err) {
00147         cerr << "Resampler: ERROR: src_process returned error: " <<
00148             src_strerror(err) << endl;
00149         return 0;
00150     }
00151 
00152     if (data.input_frames_used != (int)incount) {
00153         cerr << "Resampler: NOTE: input_frames_used == " << data.input_frames_used << " (while incount = " << incount << ")" << endl;
00154     }
00155 
00156     return data.output_frames_gen;
00157 }
00158 
00159 void
00160 Resampler::D::reset()
00161 {
00162     src_reset(m_src);
00163 }
00164 
00165 Resampler::Resampler(Quality quality, int channels, int chunkSize)
00166 {
00167     m_d = new D(quality, channels, chunkSize);
00168 }
00169 
00170 Resampler::~Resampler()
00171 {
00172     delete m_d;
00173 }
00174 
00175 int 
00176 Resampler::resample(float **in, float **out,
00177                     int incount, float ratio,
00178                     bool final)
00179 {
00180     return m_d->resample(in, out, incount, ratio, final);
00181 }
00182 
00183 int 
00184 Resampler::resampleInterleaved(float *in, float *out,
00185                     int incount, float ratio,
00186                     bool final)
00187 {
00188     return m_d->resampleInterleaved(in, out, incount, ratio, final);
00189 }
00190 
00191 void
00192 Resampler::reset()
00193 {
00194     m_d->reset();
00195 }
00196