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