annotate base/Resampler.cpp @ 983:a8f91db36e9d

If the old and new-style user resource prefixes return different results, move across resources from old to new to prime the new path first time we look it up
author Chris Cannam
date Wed, 10 Sep 2014 09:40:45 +0100
parents 6a94bb528e9d
children cc27f35aa75c
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@928 34 D(Quality quality, int channels, int chunkSize);
Chris@297 35 ~D();
Chris@297 36
Chris@928 37 int resample(float **in, float **out,
Chris@928 38 int incount, float ratio,
Chris@297 39 bool final);
Chris@297 40
Chris@928 41 int resampleInterleaved(float *in, float *out,
Chris@928 42 int 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@928 51 int m_channels;
Chris@928 52 int m_iinsize;
Chris@928 53 int m_ioutsize;
Chris@297 54 };
Chris@297 55
Chris@928 56 Resampler::D::D(Quality quality, int channels, int 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@928 92 int
Chris@297 93 Resampler::D::resample(float **in, float **out,
Chris@928 94 int 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@928 101 int 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@928 111 for (int 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@928 117 int gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final);
Chris@297 118
Chris@928 119 for (int 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@928 128 int
Chris@297 129 Resampler::D::resampleInterleaved(float *in, float *out,
Chris@928 130 int incount, float ratio,
Chris@297 131 bool final)
Chris@297 132 {
Chris@297 133 SRC_DATA data;
Chris@297 134
Chris@928 135 int 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@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@928 152 if (data.input_frames_used != (int)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@928 165 Resampler::Resampler(Quality quality, int channels, int 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@928 175 int
Chris@297 176 Resampler::resample(float **in, float **out,
Chris@928 177 int incount, float 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@928 183 int
Chris@297 184 Resampler::resampleInterleaved(float *in, float *out,
Chris@928 185 int incount, float ratio,
Chris@297 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