annotate base/Resampler.cpp @ 808:67003fb58ba4

Merge from branch "qt5". This revision actually builds with Qt4 (late releases) or Qt5, though it will warn on configure with Qt4.
author Chris Cannam
date Tue, 14 May 2013 12:36:05 +0100
parents 02390a4c2abe
children e802e550a1f2
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@297 29 class Resampler::D
Chris@297 30 {
Chris@297 31 public:
Chris@297 32 D(Quality quality, size_t channels, size_t chunkSize);
Chris@297 33 ~D();
Chris@297 34
Chris@297 35 size_t resample(float **in, float **out,
Chris@297 36 size_t incount, float ratio,
Chris@297 37 bool final);
Chris@297 38
Chris@297 39 size_t resampleInterleaved(float *in, float *out,
Chris@297 40 size_t incount, float ratio,
Chris@297 41 bool final);
Chris@297 42
Chris@297 43 void reset();
Chris@297 44
Chris@297 45 protected:
Chris@297 46 SRC_STATE *m_src;
Chris@297 47 float *m_iin;
Chris@297 48 float *m_iout;
Chris@297 49 size_t m_channels;
Chris@297 50 size_t m_iinsize;
Chris@297 51 size_t m_ioutsize;
Chris@297 52 };
Chris@297 53
Chris@297 54 Resampler::D::D(Quality quality, size_t channels, size_t chunkSize) :
Chris@297 55 m_src(0),
Chris@297 56 m_iin(0),
Chris@297 57 m_iout(0),
Chris@297 58 m_channels(channels),
Chris@297 59 m_iinsize(0),
Chris@297 60 m_ioutsize(0)
Chris@297 61 {
Chris@297 62 int err = 0;
Chris@297 63 m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY :
Chris@297 64 quality == Fastest ? SRC_LINEAR :
Chris@297 65 SRC_SINC_FASTEST,
Chris@297 66 channels, &err);
Chris@297 67
Chris@297 68 //!!! check err, throw
Chris@297 69
Chris@297 70 if (chunkSize > 0 && m_channels > 1) {
Chris@297 71 //!!! alignment?
Chris@297 72 m_iinsize = chunkSize * m_channels;
Chris@297 73 m_ioutsize = chunkSize * m_channels * 2;
Chris@297 74 m_iin = (float *)malloc(m_iinsize * sizeof(float));
Chris@297 75 m_iout = (float *)malloc(m_ioutsize * sizeof(float));
Chris@297 76 }
Chris@297 77 }
Chris@297 78
Chris@297 79 Resampler::D::~D()
Chris@297 80 {
Chris@297 81 src_delete(m_src);
Chris@297 82 if (m_iinsize > 0) {
Chris@297 83 free(m_iin);
Chris@297 84 }
Chris@297 85 if (m_ioutsize > 0) {
Chris@297 86 free(m_iout);
Chris@297 87 }
Chris@297 88 }
Chris@297 89
Chris@297 90 size_t
Chris@297 91 Resampler::D::resample(float **in, float **out,
Chris@297 92 size_t incount, float ratio,
Chris@297 93 bool final)
Chris@297 94 {
Chris@297 95 if (m_channels == 1) {
Chris@297 96 return resampleInterleaved(*in, *out, incount, ratio, final);
Chris@297 97 }
Chris@297 98
Chris@297 99 size_t outcount = lrintf(ceilf(incount * ratio));
Chris@297 100
Chris@297 101 if (incount * m_channels > m_iinsize) {
Chris@297 102 m_iinsize = incount * m_channels;
Chris@297 103 m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float));
Chris@297 104 }
Chris@297 105 if (outcount * m_channels > m_ioutsize) {
Chris@297 106 m_ioutsize = outcount * m_channels;
Chris@297 107 m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float));
Chris@297 108 }
Chris@297 109 for (size_t i = 0; i < incount; ++i) {
Chris@297 110 for (size_t c = 0; c < m_channels; ++c) {
Chris@297 111 m_iin[i * m_channels + c] = in[c][i];
Chris@297 112 }
Chris@297 113 }
Chris@297 114
Chris@297 115 size_t gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final);
Chris@297 116
Chris@297 117 for (size_t i = 0; i < gen; ++i) {
Chris@297 118 for (size_t c = 0; c < m_channels; ++c) {
Chris@297 119 out[c][i] = m_iout[i * m_channels + c];
Chris@297 120 }
Chris@297 121 }
Chris@297 122
Chris@297 123 return gen;
Chris@297 124 }
Chris@297 125
Chris@297 126 size_t
Chris@297 127 Resampler::D::resampleInterleaved(float *in, float *out,
Chris@297 128 size_t incount, float ratio,
Chris@297 129 bool final)
Chris@297 130 {
Chris@297 131 SRC_DATA data;
Chris@297 132
Chris@297 133 size_t outcount = lrintf(ceilf(incount * ratio));
Chris@297 134
Chris@297 135 data.data_in = in;
Chris@297 136 data.data_out = out;
Chris@297 137 data.input_frames = incount;
Chris@297 138 data.output_frames = outcount;
Chris@297 139 data.src_ratio = ratio;
Chris@297 140 data.end_of_input = (final ? 1 : 0);
Chris@297 141
Chris@297 142 int err = src_process(m_src, &data);
Chris@297 143
Chris@297 144 //!!! check err, respond appropriately
Chris@297 145
Chris@756 146 if (data.input_frames_used != incount) {
Chris@756 147 std::cerr << "Resampler: NOTE: input_frames_used == " << data.input_frames_used << " (while incount = " << incount << ")" << std::endl;
Chris@756 148 }
Chris@756 149
Chris@297 150 return data.output_frames_gen;
Chris@297 151 }
Chris@297 152
Chris@297 153 void
Chris@297 154 Resampler::D::reset()
Chris@297 155 {
Chris@297 156 src_reset(m_src);
Chris@297 157 }
Chris@297 158
Chris@297 159 Resampler::Resampler(Quality quality, size_t channels, size_t chunkSize)
Chris@297 160 {
Chris@297 161 m_d = new D(quality, channels, chunkSize);
Chris@297 162 }
Chris@297 163
Chris@297 164 Resampler::~Resampler()
Chris@297 165 {
Chris@297 166 delete m_d;
Chris@297 167 }
Chris@297 168
Chris@297 169 size_t
Chris@297 170 Resampler::resample(float **in, float **out,
Chris@297 171 size_t incount, float ratio,
Chris@297 172 bool final)
Chris@297 173 {
Chris@297 174 return m_d->resample(in, out, incount, ratio, final);
Chris@297 175 }
Chris@297 176
Chris@297 177 size_t
Chris@297 178 Resampler::resampleInterleaved(float *in, float *out,
Chris@297 179 size_t incount, float ratio,
Chris@297 180 bool final)
Chris@297 181 {
Chris@297 182 return m_d->resampleInterleaved(in, out, incount, ratio, final);
Chris@297 183 }
Chris@297 184
Chris@297 185 void
Chris@297 186 Resampler::reset()
Chris@297 187 {
Chris@297 188 m_d->reset();
Chris@297 189 }
Chris@297 190