annotate base/Resampler.cpp @ 863:1f98e28f70c6 tonioni

Toward using a sample mixer (with arbitrary frequency target) instead of dssi player plugin
author Chris Cannam
date Tue, 07 Jan 2014 10:57:28 +0000
parents e802e550a1f2
children 6a94bb528e9d
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@297 34 D(Quality quality, size_t channels, size_t chunkSize);
Chris@297 35 ~D();
Chris@297 36
Chris@297 37 size_t resample(float **in, float **out,
Chris@297 38 size_t incount, float ratio,
Chris@297 39 bool final);
Chris@297 40
Chris@297 41 size_t resampleInterleaved(float *in, float *out,
Chris@297 42 size_t incount, float ratio,
Chris@297 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@297 51 size_t m_channels;
Chris@297 52 size_t m_iinsize;
Chris@297 53 size_t m_ioutsize;
Chris@297 54 };
Chris@297 55
Chris@297 56 Resampler::D::D(Quality quality, size_t channels, size_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@297 92 size_t
Chris@297 93 Resampler::D::resample(float **in, float **out,
Chris@297 94 size_t incount, float 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@297 101 size_t outcount = lrintf(ceilf(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@297 111 for (size_t i = 0; i < incount; ++i) {
Chris@297 112 for (size_t 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@297 117 size_t gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final);
Chris@297 118
Chris@297 119 for (size_t i = 0; i < gen; ++i) {
Chris@297 120 for (size_t 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@297 128 size_t
Chris@297 129 Resampler::D::resampleInterleaved(float *in, float *out,
Chris@297 130 size_t incount, float ratio,
Chris@297 131 bool final)
Chris@297 132 {
Chris@297 133 SRC_DATA data;
Chris@297 134
Chris@297 135 size_t outcount = lrintf(ceilf(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@297 146 //!!! check err, respond appropriately
Chris@297 147
Chris@756 148 if (data.input_frames_used != incount) {
Chris@843 149 cerr << "Resampler: NOTE: input_frames_used == " << data.input_frames_used << " (while incount = " << incount << ")" << endl;
Chris@756 150 }
Chris@756 151
Chris@297 152 return data.output_frames_gen;
Chris@297 153 }
Chris@297 154
Chris@297 155 void
Chris@297 156 Resampler::D::reset()
Chris@297 157 {
Chris@297 158 src_reset(m_src);
Chris@297 159 }
Chris@297 160
Chris@297 161 Resampler::Resampler(Quality quality, size_t channels, size_t chunkSize)
Chris@297 162 {
Chris@297 163 m_d = new D(quality, channels, chunkSize);
Chris@297 164 }
Chris@297 165
Chris@297 166 Resampler::~Resampler()
Chris@297 167 {
Chris@297 168 delete m_d;
Chris@297 169 }
Chris@297 170
Chris@297 171 size_t
Chris@297 172 Resampler::resample(float **in, float **out,
Chris@297 173 size_t incount, float ratio,
Chris@297 174 bool final)
Chris@297 175 {
Chris@297 176 return m_d->resample(in, out, incount, ratio, final);
Chris@297 177 }
Chris@297 178
Chris@297 179 size_t
Chris@297 180 Resampler::resampleInterleaved(float *in, float *out,
Chris@297 181 size_t incount, float ratio,
Chris@297 182 bool final)
Chris@297 183 {
Chris@297 184 return m_d->resampleInterleaved(in, out, incount, ratio, final);
Chris@297 185 }
Chris@297 186
Chris@297 187 void
Chris@297 188 Resampler::reset()
Chris@297 189 {
Chris@297 190 m_d->reset();
Chris@297 191 }
Chris@297 192