annotate base/Resampler.cpp @ 1158:d9c766274c8b

Merge
author Chris Cannam
date Sat, 30 Jan 2016 12:08:50 +0000
parents cc27f35aa75c
children
rev   line source
Chris@297 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@297 2 /*
Chris@297 3 Sonic Visualiser
Chris@297 4 An audio file viewer and annotation editor.
Chris@297 5 Centre for Digital Music, Queen Mary, University of London.
Chris@297 6
Chris@297 7 This program is free software; you can redistribute it and/or
Chris@297 8 modify it under the terms of the GNU General Public License as
Chris@297 9 published by the Free Software Foundation; either version 2 of the
Chris@297 10 License, or (at your option) any later version. See the file
Chris@297 11 COPYING included with this distribution for more information.
Chris@297 12 */
Chris@297 13
Chris@297 14 /*
Chris@297 15 This is a modified version of a source file from the
Chris@297 16 Rubber Band audio timestretcher library.
Chris@297 17 This file copyright 2007 Chris Cannam.
Chris@297 18 */
Chris@297 19
Chris@297 20 #include "Resampler.h"
Chris@297 21
Chris@297 22 #include <cstdlib>
Chris@297 23 #include <cmath>
Chris@297 24
Chris@297 25 #include <iostream>
Chris@297 26
Chris@297 27 #include <samplerate.h>
Chris@297 28
Chris@843 29 #include "Debug.h"
Chris@843 30
Chris@297 31 class Resampler::D
Chris@297 32 {
Chris@297 33 public:
Chris@1038 34 D(Quality quality, int channels, sv_frame_t chunkSize);
Chris@297 35 ~D();
Chris@297 36
Chris@1038 37 sv_frame_t resample(float **in, float **out,
Chris@1038 38 sv_frame_t incount, double ratio,
Chris@1038 39 bool final);
Chris@297 40
Chris@1038 41 sv_frame_t resampleInterleaved(float *in, float *out,
Chris@1038 42 sv_frame_t incount, double ratio,
Chris@1038 43 bool final);
Chris@297 44
Chris@297 45 void reset();
Chris@297 46
Chris@297 47 protected:
Chris@297 48 SRC_STATE *m_src;
Chris@297 49 float *m_iin;
Chris@297 50 float *m_iout;
Chris@928 51 int m_channels;
Chris@1038 52 sv_frame_t m_iinsize;
Chris@1038 53 sv_frame_t m_ioutsize;
Chris@297 54 };
Chris@297 55
Chris@1038 56 Resampler::D::D(Quality quality, int channels, sv_frame_t chunkSize) :
Chris@297 57 m_src(0),
Chris@297 58 m_iin(0),
Chris@297 59 m_iout(0),
Chris@297 60 m_channels(channels),
Chris@297 61 m_iinsize(0),
Chris@297 62 m_ioutsize(0)
Chris@297 63 {
Chris@297 64 int err = 0;
Chris@297 65 m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY :
Chris@297 66 quality == Fastest ? SRC_LINEAR :
Chris@297 67 SRC_SINC_FASTEST,
Chris@297 68 channels, &err);
Chris@297 69
Chris@297 70 //!!! check err, throw
Chris@297 71
Chris@297 72 if (chunkSize > 0 && m_channels > 1) {
Chris@297 73 //!!! alignment?
Chris@297 74 m_iinsize = chunkSize * m_channels;
Chris@297 75 m_ioutsize = chunkSize * m_channels * 2;
Chris@297 76 m_iin = (float *)malloc(m_iinsize * sizeof(float));
Chris@297 77 m_iout = (float *)malloc(m_ioutsize * sizeof(float));
Chris@297 78 }
Chris@297 79 }
Chris@297 80
Chris@297 81 Resampler::D::~D()
Chris@297 82 {
Chris@297 83 src_delete(m_src);
Chris@297 84 if (m_iinsize > 0) {
Chris@297 85 free(m_iin);
Chris@297 86 }
Chris@297 87 if (m_ioutsize > 0) {
Chris@297 88 free(m_iout);
Chris@297 89 }
Chris@297 90 }
Chris@297 91
Chris@1038 92 sv_frame_t
Chris@297 93 Resampler::D::resample(float **in, float **out,
Chris@1038 94 sv_frame_t incount, double ratio,
Chris@297 95 bool final)
Chris@297 96 {
Chris@297 97 if (m_channels == 1) {
Chris@297 98 return resampleInterleaved(*in, *out, incount, ratio, final);
Chris@297 99 }
Chris@297 100
Chris@1038 101 sv_frame_t outcount = lrint(ceil(double(incount) * ratio));
Chris@297 102
Chris@297 103 if (incount * m_channels > m_iinsize) {
Chris@297 104 m_iinsize = incount * m_channels;
Chris@297 105 m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float));
Chris@297 106 }
Chris@297 107 if (outcount * m_channels > m_ioutsize) {
Chris@297 108 m_ioutsize = outcount * m_channels;
Chris@297 109 m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float));
Chris@297 110 }
Chris@1038 111 for (sv_frame_t i = 0; i < incount; ++i) {
Chris@928 112 for (int c = 0; c < m_channels; ++c) {
Chris@297 113 m_iin[i * m_channels + c] = in[c][i];
Chris@297 114 }
Chris@297 115 }
Chris@297 116
Chris@1038 117 sv_frame_t gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final);
Chris@297 118
Chris@1038 119 for (sv_frame_t i = 0; i < gen; ++i) {
Chris@928 120 for (int c = 0; c < m_channels; ++c) {
Chris@297 121 out[c][i] = m_iout[i * m_channels + c];
Chris@297 122 }
Chris@297 123 }
Chris@297 124
Chris@297 125 return gen;
Chris@297 126 }
Chris@297 127
Chris@1038 128 sv_frame_t
Chris@297 129 Resampler::D::resampleInterleaved(float *in, float *out,
Chris@1038 130 sv_frame_t incount, double ratio,
Chris@297 131 bool final)
Chris@297 132 {
Chris@297 133 SRC_DATA data;
Chris@297 134
Chris@1038 135 sv_frame_t outcount = lrint(ceil(double(incount) * ratio));
Chris@297 136
Chris@297 137 data.data_in = in;
Chris@297 138 data.data_out = out;
Chris@297 139 data.input_frames = incount;
Chris@297 140 data.output_frames = outcount;
Chris@297 141 data.src_ratio = ratio;
Chris@297 142 data.end_of_input = (final ? 1 : 0);
Chris@297 143
Chris@297 144 int err = src_process(m_src, &data);
Chris@297 145
Chris@928 146 if (err) {
Chris@928 147 cerr << "Resampler: ERROR: src_process returned error: " <<
Chris@928 148 src_strerror(err) << endl;
Chris@928 149 return 0;
Chris@928 150 }
Chris@297 151
Chris@1038 152 if (data.input_frames_used != incount) {
Chris@843 153 cerr << "Resampler: NOTE: input_frames_used == " << data.input_frames_used << " (while incount = " << incount << ")" << endl;
Chris@756 154 }
Chris@756 155
Chris@297 156 return data.output_frames_gen;
Chris@297 157 }
Chris@297 158
Chris@297 159 void
Chris@297 160 Resampler::D::reset()
Chris@297 161 {
Chris@297 162 src_reset(m_src);
Chris@297 163 }
Chris@297 164
Chris@1038 165 Resampler::Resampler(Quality quality, int channels, sv_frame_t chunkSize)
Chris@297 166 {
Chris@297 167 m_d = new D(quality, channels, chunkSize);
Chris@297 168 }
Chris@297 169
Chris@297 170 Resampler::~Resampler()
Chris@297 171 {
Chris@297 172 delete m_d;
Chris@297 173 }
Chris@297 174
Chris@1038 175 sv_frame_t
Chris@297 176 Resampler::resample(float **in, float **out,
Chris@1038 177 sv_frame_t incount, double ratio,
Chris@297 178 bool final)
Chris@297 179 {
Chris@297 180 return m_d->resample(in, out, incount, ratio, final);
Chris@297 181 }
Chris@297 182
Chris@1038 183 sv_frame_t
Chris@297 184 Resampler::resampleInterleaved(float *in, float *out,
Chris@1038 185 sv_frame_t incount, double ratio,
Chris@1038 186 bool final)
Chris@297 187 {
Chris@297 188 return m_d->resampleInterleaved(in, out, incount, ratio, final);
Chris@297 189 }
Chris@297 190
Chris@297 191 void
Chris@297 192 Resampler::reset()
Chris@297 193 {
Chris@297 194 m_d->reset();
Chris@297 195 }
Chris@297 196