00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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