annotate base/Resampler.cpp @ 388:370aa9714ef5

* Move plugin/transform to plain transform. This way transform can depend on model and GUI classes, but plugin doesn't have to.
author Chris Cannam
date Wed, 12 Mar 2008 18:02:17 +0000
parents c022976d18e8
children 02390a4c2abe
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@297 146 return data.output_frames_gen;
Chris@297 147 }
Chris@297 148
Chris@297 149 void
Chris@297 150 Resampler::D::reset()
Chris@297 151 {
Chris@297 152 src_reset(m_src);
Chris@297 153 }
Chris@297 154
Chris@297 155 Resampler::Resampler(Quality quality, size_t channels, size_t chunkSize)
Chris@297 156 {
Chris@297 157 m_d = new D(quality, channels, chunkSize);
Chris@297 158 }
Chris@297 159
Chris@297 160 Resampler::~Resampler()
Chris@297 161 {
Chris@297 162 delete m_d;
Chris@297 163 }
Chris@297 164
Chris@297 165 size_t
Chris@297 166 Resampler::resample(float **in, float **out,
Chris@297 167 size_t incount, float ratio,
Chris@297 168 bool final)
Chris@297 169 {
Chris@297 170 return m_d->resample(in, out, incount, ratio, final);
Chris@297 171 }
Chris@297 172
Chris@297 173 size_t
Chris@297 174 Resampler::resampleInterleaved(float *in, float *out,
Chris@297 175 size_t incount, float ratio,
Chris@297 176 bool final)
Chris@297 177 {
Chris@297 178 return m_d->resampleInterleaved(in, out, incount, ratio, final);
Chris@297 179 }
Chris@297 180
Chris@297 181 void
Chris@297 182 Resampler::reset()
Chris@297 183 {
Chris@297 184 m_d->reset();
Chris@297 185 }
Chris@297 186