svcore
1.9
|
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