comparison base/ResamplerSV.cpp @ 1228:a2091d148d7f project-file-rework

Cut down vastly on the number of config.pri files and places where their contents has to be effectively duplicated without them
author Chris Cannam
date Mon, 24 Oct 2016 17:53:33 +0100
parents base/Resampler.cpp@cc27f35aa75c
children
comparison
equal deleted inserted replaced
1224:ab050519c4ba 1228:a2091d148d7f
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 /*
3 Sonic Visualiser
4 An audio file viewer and annotation editor.
5 Centre for Digital Music, Queen Mary, University of London.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version. See the file
11 COPYING included with this distribution for more information.
12 */
13
14 /*
15 This is a modified version of a source file from the
16 Rubber Band audio timestretcher library.
17 This file copyright 2007 Chris Cannam.
18 */
19
20 #include "Resampler.h"
21
22 #include <cstdlib>
23 #include <cmath>
24
25 #include <iostream>
26
27 #include <samplerate.h>
28
29 #include "Debug.h"
30
31 class Resampler::D
32 {
33 public:
34 D(Quality quality, int channels, sv_frame_t chunkSize);
35 ~D();
36
37 sv_frame_t resample(float **in, float **out,
38 sv_frame_t incount, double ratio,
39 bool final);
40
41 sv_frame_t resampleInterleaved(float *in, float *out,
42 sv_frame_t incount, double ratio,
43 bool final);
44
45 void reset();
46
47 protected:
48 SRC_STATE *m_src;
49 float *m_iin;
50 float *m_iout;
51 int m_channels;
52 sv_frame_t m_iinsize;
53 sv_frame_t m_ioutsize;
54 };
55
56 Resampler::D::D(Quality quality, int channels, sv_frame_t chunkSize) :
57 m_src(0),
58 m_iin(0),
59 m_iout(0),
60 m_channels(channels),
61 m_iinsize(0),
62 m_ioutsize(0)
63 {
64 int err = 0;
65 m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY :
66 quality == Fastest ? SRC_LINEAR :
67 SRC_SINC_FASTEST,
68 channels, &err);
69
70 //!!! check err, throw
71
72 if (chunkSize > 0 && m_channels > 1) {
73 //!!! alignment?
74 m_iinsize = chunkSize * m_channels;
75 m_ioutsize = chunkSize * m_channels * 2;
76 m_iin = (float *)malloc(m_iinsize * sizeof(float));
77 m_iout = (float *)malloc(m_ioutsize * sizeof(float));
78 }
79 }
80
81 Resampler::D::~D()
82 {
83 src_delete(m_src);
84 if (m_iinsize > 0) {
85 free(m_iin);
86 }
87 if (m_ioutsize > 0) {
88 free(m_iout);
89 }
90 }
91
92 sv_frame_t
93 Resampler::D::resample(float **in, float **out,
94 sv_frame_t incount, double ratio,
95 bool final)
96 {
97 if (m_channels == 1) {
98 return resampleInterleaved(*in, *out, incount, ratio, final);
99 }
100
101 sv_frame_t outcount = lrint(ceil(double(incount) * ratio));
102
103 if (incount * m_channels > m_iinsize) {
104 m_iinsize = incount * m_channels;
105 m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float));
106 }
107 if (outcount * m_channels > m_ioutsize) {
108 m_ioutsize = outcount * m_channels;
109 m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float));
110 }
111 for (sv_frame_t i = 0; i < incount; ++i) {
112 for (int c = 0; c < m_channels; ++c) {
113 m_iin[i * m_channels + c] = in[c][i];
114 }
115 }
116
117 sv_frame_t gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final);
118
119 for (sv_frame_t i = 0; i < gen; ++i) {
120 for (int c = 0; c < m_channels; ++c) {
121 out[c][i] = m_iout[i * m_channels + c];
122 }
123 }
124
125 return gen;
126 }
127
128 sv_frame_t
129 Resampler::D::resampleInterleaved(float *in, float *out,
130 sv_frame_t incount, double ratio,
131 bool final)
132 {
133 SRC_DATA data;
134
135 sv_frame_t outcount = lrint(ceil(double(incount) * ratio));
136
137 data.data_in = in;
138 data.data_out = out;
139 data.input_frames = incount;
140 data.output_frames = outcount;
141 data.src_ratio = ratio;
142 data.end_of_input = (final ? 1 : 0);
143
144 int err = src_process(m_src, &data);
145
146 if (err) {
147 cerr << "Resampler: ERROR: src_process returned error: " <<
148 src_strerror(err) << endl;
149 return 0;
150 }
151
152 if (data.input_frames_used != incount) {
153 cerr << "Resampler: NOTE: input_frames_used == " << data.input_frames_used << " (while incount = " << incount << ")" << endl;
154 }
155
156 return data.output_frames_gen;
157 }
158
159 void
160 Resampler::D::reset()
161 {
162 src_reset(m_src);
163 }
164
165 Resampler::Resampler(Quality quality, int channels, sv_frame_t chunkSize)
166 {
167 m_d = new D(quality, channels, chunkSize);
168 }
169
170 Resampler::~Resampler()
171 {
172 delete m_d;
173 }
174
175 sv_frame_t
176 Resampler::resample(float **in, float **out,
177 sv_frame_t incount, double ratio,
178 bool final)
179 {
180 return m_d->resample(in, out, incount, ratio, final);
181 }
182
183 sv_frame_t
184 Resampler::resampleInterleaved(float *in, float *out,
185 sv_frame_t incount, double ratio,
186 bool final)
187 {
188 return m_d->resampleInterleaved(in, out, incount, ratio, final);
189 }
190
191 void
192 Resampler::reset()
193 {
194 m_d->reset();
195 }
196