Mercurial > hg > svcore
comparison base/Resampler.cpp @ 297:c022976d18e8
* Merge from sv-match-alignment branch (excluding alignment-specific document).
- add aggregate wave model (not yet complete enough to be added as a true
model in a layer, but there's potential)
- add play solo mode
- add alignment model -- unused in plain SV
- fix two plugin leaks
- add m3u playlist support (opens all files at once, potentially hazardous)
- fix retrieval of pre-encoded URLs
- add ability to resample audio files on import, so as to match rates with
other files previously loaded; add preference for same
- add preliminary support in transform code for range and rate of transform
input
- reorganise preferences dialog, move dark-background option to preferences,
add option for temporary directory location
author | Chris Cannam |
---|---|
date | Fri, 28 Sep 2007 13:56:38 +0000 |
parents | |
children | 02390a4c2abe |
comparison
equal
deleted
inserted
replaced
296:2b6c99b607f1 | 297:c022976d18e8 |
---|---|
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 class Resampler::D | |
30 { | |
31 public: | |
32 D(Quality quality, size_t channels, size_t chunkSize); | |
33 ~D(); | |
34 | |
35 size_t resample(float **in, float **out, | |
36 size_t incount, float ratio, | |
37 bool final); | |
38 | |
39 size_t resampleInterleaved(float *in, float *out, | |
40 size_t incount, float ratio, | |
41 bool final); | |
42 | |
43 void reset(); | |
44 | |
45 protected: | |
46 SRC_STATE *m_src; | |
47 float *m_iin; | |
48 float *m_iout; | |
49 size_t m_channels; | |
50 size_t m_iinsize; | |
51 size_t m_ioutsize; | |
52 }; | |
53 | |
54 Resampler::D::D(Quality quality, size_t channels, size_t chunkSize) : | |
55 m_src(0), | |
56 m_iin(0), | |
57 m_iout(0), | |
58 m_channels(channels), | |
59 m_iinsize(0), | |
60 m_ioutsize(0) | |
61 { | |
62 int err = 0; | |
63 m_src = src_new(quality == Best ? SRC_SINC_BEST_QUALITY : | |
64 quality == Fastest ? SRC_LINEAR : | |
65 SRC_SINC_FASTEST, | |
66 channels, &err); | |
67 | |
68 //!!! check err, throw | |
69 | |
70 if (chunkSize > 0 && m_channels > 1) { | |
71 //!!! alignment? | |
72 m_iinsize = chunkSize * m_channels; | |
73 m_ioutsize = chunkSize * m_channels * 2; | |
74 m_iin = (float *)malloc(m_iinsize * sizeof(float)); | |
75 m_iout = (float *)malloc(m_ioutsize * sizeof(float)); | |
76 } | |
77 } | |
78 | |
79 Resampler::D::~D() | |
80 { | |
81 src_delete(m_src); | |
82 if (m_iinsize > 0) { | |
83 free(m_iin); | |
84 } | |
85 if (m_ioutsize > 0) { | |
86 free(m_iout); | |
87 } | |
88 } | |
89 | |
90 size_t | |
91 Resampler::D::resample(float **in, float **out, | |
92 size_t incount, float ratio, | |
93 bool final) | |
94 { | |
95 if (m_channels == 1) { | |
96 return resampleInterleaved(*in, *out, incount, ratio, final); | |
97 } | |
98 | |
99 size_t outcount = lrintf(ceilf(incount * ratio)); | |
100 | |
101 if (incount * m_channels > m_iinsize) { | |
102 m_iinsize = incount * m_channels; | |
103 m_iin = (float *)realloc(m_iin, m_iinsize * sizeof(float)); | |
104 } | |
105 if (outcount * m_channels > m_ioutsize) { | |
106 m_ioutsize = outcount * m_channels; | |
107 m_iout = (float *)realloc(m_iout, m_ioutsize * sizeof(float)); | |
108 } | |
109 for (size_t i = 0; i < incount; ++i) { | |
110 for (size_t c = 0; c < m_channels; ++c) { | |
111 m_iin[i * m_channels + c] = in[c][i]; | |
112 } | |
113 } | |
114 | |
115 size_t gen = resampleInterleaved(m_iin, m_iout, incount, ratio, final); | |
116 | |
117 for (size_t i = 0; i < gen; ++i) { | |
118 for (size_t c = 0; c < m_channels; ++c) { | |
119 out[c][i] = m_iout[i * m_channels + c]; | |
120 } | |
121 } | |
122 | |
123 return gen; | |
124 } | |
125 | |
126 size_t | |
127 Resampler::D::resampleInterleaved(float *in, float *out, | |
128 size_t incount, float ratio, | |
129 bool final) | |
130 { | |
131 SRC_DATA data; | |
132 | |
133 size_t outcount = lrintf(ceilf(incount * ratio)); | |
134 | |
135 data.data_in = in; | |
136 data.data_out = out; | |
137 data.input_frames = incount; | |
138 data.output_frames = outcount; | |
139 data.src_ratio = ratio; | |
140 data.end_of_input = (final ? 1 : 0); | |
141 | |
142 int err = src_process(m_src, &data); | |
143 | |
144 //!!! check err, respond appropriately | |
145 | |
146 return data.output_frames_gen; | |
147 } | |
148 | |
149 void | |
150 Resampler::D::reset() | |
151 { | |
152 src_reset(m_src); | |
153 } | |
154 | |
155 Resampler::Resampler(Quality quality, size_t channels, size_t chunkSize) | |
156 { | |
157 m_d = new D(quality, channels, chunkSize); | |
158 } | |
159 | |
160 Resampler::~Resampler() | |
161 { | |
162 delete m_d; | |
163 } | |
164 | |
165 size_t | |
166 Resampler::resample(float **in, float **out, | |
167 size_t incount, float ratio, | |
168 bool final) | |
169 { | |
170 return m_d->resample(in, out, incount, ratio, final); | |
171 } | |
172 | |
173 size_t | |
174 Resampler::resampleInterleaved(float *in, float *out, | |
175 size_t incount, float ratio, | |
176 bool final) | |
177 { | |
178 return m_d->resampleInterleaved(in, out, incount, ratio, final); | |
179 } | |
180 | |
181 void | |
182 Resampler::reset() | |
183 { | |
184 m_d->reset(); | |
185 } | |
186 |