Mercurial > hg > svcore
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 |