annotate base/Resampler.cpp @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +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