Chris@41
|
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
Chris@41
|
2 <HTML>
|
Chris@41
|
3
|
Chris@41
|
4 <HEAD>
|
Chris@41
|
5 <TITLE>
|
Chris@41
|
6 Secret Rabbit Code (aka libsamplerate)
|
Chris@41
|
7 </TITLE>
|
Chris@41
|
8 <META NAME="Author" CONTENT="Erik de Castro Lopo (erikd AT mega-nerd DOT com)">
|
Chris@41
|
9 <META NAME="Version" CONTENT="libsamplerate-0.1.8">
|
Chris@41
|
10 <META NAME="Description" CONTENT="The Secret Rabbit Code Home Page">
|
Chris@41
|
11 <META NAME="Keywords" CONTENT="libsamplerate sound resample audio dsp Linux">
|
Chris@41
|
12 <LINK REL=StyleSheet HREF="SRC.css" TYPE="text/css" MEDIA="all">
|
Chris@41
|
13 </HEAD>
|
Chris@41
|
14
|
Chris@41
|
15 <BODY TEXT="#FFFFFF" BGCOLOR="#000000" LINK="#FB1465" VLINK="#FB1465" ALINK="#FB1465">
|
Chris@41
|
16 <!-- pepper -->
|
Chris@41
|
17 <CENTER>
|
Chris@41
|
18 <IMG SRC="SRC.png" HEIGHT=100 WIDTH=760 ALT="SRC.png">
|
Chris@41
|
19 </CENTER>
|
Chris@41
|
20 <!-- pepper -->
|
Chris@41
|
21 <BR>
|
Chris@41
|
22 <!-- pepper -->
|
Chris@41
|
23 <TABLE ALIGN="center" WIDTH="98%">
|
Chris@41
|
24 <TR>
|
Chris@41
|
25 <TD VALIGN="top">
|
Chris@41
|
26 <BR>
|
Chris@41
|
27 <DIV CLASS="nav">
|
Chris@41
|
28 <BR>
|
Chris@41
|
29 <A HREF="index.html">Home</A><BR>
|
Chris@41
|
30 <A HREF="license.html">License</A><BR>
|
Chris@41
|
31 <A HREF="history.html">History</A><BR>
|
Chris@41
|
32 <A HREF="download.html">Download</A><BR>
|
Chris@41
|
33 <A HREF="quality.html">Quality</A><BR>
|
Chris@41
|
34 <A HREF="api.html">API</A><BR>
|
Chris@41
|
35 <A HREF="bugs.html">Bug Reporting</A><BR>
|
Chris@41
|
36 <A HREF="win32.html">On Win32</A><BR>
|
Chris@41
|
37 <A HREF="faq.html">FAQ</A><BR>
|
Chris@41
|
38 <A HREF="lists.html">Mailing Lists</A><BR>
|
Chris@41
|
39 <A HREF="ChangeLog">ChangeLog</A><BR>
|
Chris@41
|
40 <BR>
|
Chris@41
|
41 <DIV CLASS="block">
|
Chris@41
|
42 Author :<BR>Erik de Castro Lopo
|
Chris@41
|
43 <!-- pepper -->
|
Chris@41
|
44 <BR><BR>
|
Chris@41
|
45 <!-- pepper -->
|
Chris@41
|
46
|
Chris@41
|
47 </DIV>
|
Chris@41
|
48 <IMG SRC=
|
Chris@41
|
49 "/cgi-bin/Count.cgi?ft=6|frgb=55;55;55|tr=0|md=6|dd=B|st=1|sh=1|df=src_api.dat"
|
Chris@41
|
50 HEIGHT=30 WIDTH=100 ALT="counter.gif">
|
Chris@41
|
51 </DIV>
|
Chris@41
|
52
|
Chris@41
|
53 </TD>
|
Chris@41
|
54 <!-- pepper -->
|
Chris@41
|
55 <!-- ######################################################################## -->
|
Chris@41
|
56 <!-- pepper -->
|
Chris@41
|
57 <TD VALIGN="top">
|
Chris@41
|
58 <DIV CLASS="block">
|
Chris@41
|
59
|
Chris@41
|
60 <H1><B>Frequently Asked Questions</B></H1>
|
Chris@41
|
61 <P>
|
Chris@41
|
62 <A HREF="#Q001">Q1 : Is it normal for the output of libsamplerate to be louder
|
Chris@41
|
63 than its input?</A><BR><BR>
|
Chris@41
|
64 <A HREF="#Q002">Q2 : On Unix/Linux/MacOSX, what is the best way of detecting
|
Chris@41
|
65 the presence and location of libsamplerate and its header file using
|
Chris@41
|
66 autoconf?</A><BR><BR>
|
Chris@41
|
67 <A HREF="#Q003">Q3 : If I upsample and downsample to the original rate, for
|
Chris@41
|
68 example 44.1->96->44.1, do I get an identical signal as the one before the
|
Chris@41
|
69 up/down resampling?</A><BR><BR>
|
Chris@41
|
70 <A HREF="#Q004">Q4 : If I ran src_simple (libsamplerate) on small chunks (160
|
Chris@41
|
71 frames) would that sound bad?</A><BR><BR>
|
Chris@41
|
72 <A HREF="#Q005">Q5 : I'm using libsamplerate but the high quality settings
|
Chris@41
|
73 sound worse than the SRC_LINEAR converter. Why?</A><BR><BR>
|
Chris@41
|
74 <A HREF="#Q006">Q6 : I'm use the SRC_SINC_* converters and up-sampling by a ratio of
|
Chris@41
|
75 2. I reset the converter and put in 1000 samples and I expect to get 2000
|
Chris@41
|
76 samples out, but I'm getting less than that. Why?</A><BR><BR>
|
Chris@41
|
77 <A HREF="#Q007">Q7 : I have input and output sample rates that are integer
|
Chris@41
|
78 values, but the API wants me to divide one by the other and put the result
|
Chris@41
|
79 in a floating point number. Won't this case problems for long running
|
Chris@41
|
80 conversions?</A><BR><BR>
|
Chris@41
|
81 </P>
|
Chris@41
|
82 <HR>
|
Chris@41
|
83 <!-- ========================================================================= -->
|
Chris@41
|
84 <A NAME="Q001"></A>
|
Chris@41
|
85 <H2><BR><B>Q1 : Is it normal for the output of libsamplerate to be louder
|
Chris@41
|
86 than its input?</B></H2>
|
Chris@41
|
87 <P>
|
Chris@41
|
88 The output of libsamplerate will be roughly the same volume as the input.
|
Chris@41
|
89 However, even if the input is strictly in the range (-1.0, 1.0), it is still
|
Chris@41
|
90 possible for the output to contain peak values outside this range.
|
Chris@41
|
91 </P>
|
Chris@41
|
92 <P>
|
Chris@41
|
93 Consider four consecutive samples of [0.5 0.999 0.999 0.5].
|
Chris@41
|
94 If we are up sampling by a factor of two we need to insert samples between
|
Chris@41
|
95 each of the existing samples.
|
Chris@41
|
96 Its pretty obvious then, that the sample between the two 0.999 values should
|
Chris@41
|
97 and will be bigger than 0.999.
|
Chris@41
|
98 </P>
|
Chris@41
|
99 <P>
|
Chris@41
|
100 This means that anyone using libsamplerate should normalize its output before
|
Chris@41
|
101 doing things like saving the audio to a 16 bit WAV file.
|
Chris@41
|
102 </P>
|
Chris@41
|
103
|
Chris@41
|
104 <!-- pepper -->
|
Chris@41
|
105 <!-- ========================================================================= -->
|
Chris@41
|
106
|
Chris@41
|
107 <a NAME="Q002"></a>
|
Chris@41
|
108 <h2><br><b>Q2 : On Unix/Linux/MacOSX, what is the best way of detecting
|
Chris@41
|
109 the presence and location of libsamplerate and its header file using
|
Chris@41
|
110 autoconf?</b></h2>
|
Chris@41
|
111
|
Chris@41
|
112 <p>
|
Chris@41
|
113 libsamplerate uses the pkg-config (man pkg-config) method of registering itself
|
Chris@41
|
114 with the host system.
|
Chris@41
|
115 The best way of detecting its presence is using something like this in configure.ac
|
Chris@41
|
116 (or configure.in):
|
Chris@41
|
117 </p>
|
Chris@41
|
118
|
Chris@41
|
119 <pre>
|
Chris@41
|
120 PKG_CHECK_MODULES(SAMPLERATE, samplerate >= 0.1.3,
|
Chris@41
|
121 ac_cv_samplerate=1, ac_cv_samplerate=0)
|
Chris@41
|
122
|
Chris@41
|
123 AC_DEFINE_UNQUOTED([HAVE_SAMPLERATE],${ac_cv_samplerate},
|
Chris@41
|
124 [Set to 1 if you have libsamplerate.])
|
Chris@41
|
125
|
Chris@41
|
126 AC_SUBST(SAMPLERATE_CFLAGS)
|
Chris@41
|
127 AC_SUBST(SAMPLERATE_LIBS)
|
Chris@41
|
128 </pre>
|
Chris@41
|
129 <p>
|
Chris@41
|
130 This will automatically set the <b>SAMPLERATE_CFLAGS</b> and <b>SAMPLERATE_LIBS</b>
|
Chris@41
|
131 variables which can be used in Makefile.am or Makefile.in like this:
|
Chris@41
|
132 </p>
|
Chris@41
|
133 <pre>
|
Chris@41
|
134 SAMPLERATE_CFLAGS = @SAMPLERATE_CFLAGS@
|
Chris@41
|
135 SAMPLERATE_LIBS = @SAMPLERATE_LIBS@
|
Chris@41
|
136 </pre>
|
Chris@41
|
137
|
Chris@41
|
138 <p>
|
Chris@41
|
139 If you install libsamplerate from source, you will probably need to set the
|
Chris@41
|
140 <b>PKG_CONFIG_PATH</b> environment variable's suggested at the end of the
|
Chris@41
|
141 libsamplerate configure process. For instance on my system I get this:
|
Chris@41
|
142 </p>
|
Chris@41
|
143 <pre>
|
Chris@41
|
144 -=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-=-
|
Chris@41
|
145
|
Chris@41
|
146 Configuration summary :
|
Chris@41
|
147
|
Chris@41
|
148 Version : ..................... 0.1.3
|
Chris@41
|
149 Enable debugging : ............ no
|
Chris@41
|
150
|
Chris@41
|
151 Tools :
|
Chris@41
|
152
|
Chris@41
|
153 Compiler is GCC : ............. yes
|
Chris@41
|
154 GCC major version : ........... 3
|
Chris@41
|
155
|
Chris@41
|
156 Extra tools required for testing and examples :
|
Chris@41
|
157
|
Chris@41
|
158 Have FFTW : ................... yes
|
Chris@41
|
159 Have libsndfile : ............. yes
|
Chris@41
|
160 Have libefence : .............. no
|
Chris@41
|
161
|
Chris@41
|
162 Installation directories :
|
Chris@41
|
163
|
Chris@41
|
164 Library directory : ........... /usr/local/lib
|
Chris@41
|
165 Program directory : ........... /usr/local/bin
|
Chris@41
|
166 Pkgconfig directory : ......... /usr/local/lib/pkgconfig
|
Chris@41
|
167 </pre>
|
Chris@41
|
168
|
Chris@41
|
169
|
Chris@41
|
170 <!-- pepper -->
|
Chris@41
|
171 <!-- ========================================================================= -->
|
Chris@41
|
172 <A NAME="Q003"></A>
|
Chris@41
|
173 <H2><BR><B>Q3 : If I upsample and downsample to the original rate, for
|
Chris@41
|
174 example 44.1->96->44.1, do I get an identical signal as the one before the
|
Chris@41
|
175 up/down resampling?</B></H2>
|
Chris@41
|
176 <P>
|
Chris@41
|
177 The short answer is that for the general case, no, you don't.
|
Chris@41
|
178 The long answer is that for some signals, with some converters, you will
|
Chris@41
|
179 get very, very close.
|
Chris@41
|
180 </P>
|
Chris@41
|
181 <P>
|
Chris@41
|
182 In order to resample correctly (ie using the <B>SRC_SINC_*</B> converters),
|
Chris@41
|
183 filtering needs to be applied, regardless of whether its upsampling or
|
Chris@41
|
184 downsampling.
|
Chris@41
|
185 This filter needs to attenuate all frequencies above 0.5 times the minimum of
|
Chris@41
|
186 the source and destination sample rate (call this fshmin).
|
Chris@41
|
187 Since the filter needed to achieve full attenuation at this point, it has to
|
Chris@41
|
188 start rolling off a some frequency below this point.
|
Chris@41
|
189 It is this rolloff of the very highest frequencies which causes some of the
|
Chris@41
|
190 loss.
|
Chris@41
|
191 </P>
|
Chris@41
|
192 <P>
|
Chris@41
|
193 The other factor is that the filter itself can introduce transient artifacts
|
Chris@41
|
194 which causes the output to be different to the input.
|
Chris@41
|
195 </P>
|
Chris@41
|
196
|
Chris@41
|
197 <!-- pepper -->
|
Chris@41
|
198 <!-- ========================================================================= -->
|
Chris@41
|
199 <A NAME="Q004"></A>
|
Chris@41
|
200 <H2><BR><B>Q4 : If I ran src_simple on small chunks (say 160 frames) would that
|
Chris@41
|
201 sound bad?</B></H2>
|
Chris@41
|
202 <P>
|
Chris@41
|
203 Well if you are after odd sound effects, it might sound OK.
|
Chris@41
|
204 If you are after high quality sample rate conversion you will be disappointed.
|
Chris@41
|
205 </P>
|
Chris@41
|
206 <P>
|
Chris@41
|
207 The src_simple() was designed to provide a simple to use interface for people
|
Chris@41
|
208 who wanted to do sample rate conversion on say, a whole file all at once.
|
Chris@41
|
209 </P>
|
Chris@41
|
210
|
Chris@41
|
211 <!-- pepper -->
|
Chris@41
|
212 <!-- ========================================================================= -->
|
Chris@41
|
213 <A NAME="Q005"></A>
|
Chris@41
|
214 <H2><BR><B>Q5 : I'm using libsamplerate but the high quality settings
|
Chris@41
|
215 sound worse than the SRC_LINEAR converter. Why?</B></H2>
|
Chris@41
|
216 <P>
|
Chris@41
|
217 There are two possible problems.
|
Chris@41
|
218 Firstly, if you are using the src_simple() function on successive blocks
|
Chris@41
|
219 of a stream of samples, you will get bad results. The src_simple() function
|
Chris@41
|
220 is designed for use on a whole sound file, all at once, not on contiguous
|
Chris@41
|
221 segments of the same sound file.
|
Chris@41
|
222 To fix the problem, you need to move to the src_process() API or the callback
|
Chris@41
|
223 based API.
|
Chris@41
|
224 </P>
|
Chris@41
|
225 <P>
|
Chris@41
|
226 If you are already using the src_process() API or the callback based API and
|
Chris@41
|
227 the high quality settings sound worse than SRC_LINEAR, then you have other
|
Chris@41
|
228 problems.
|
Chris@41
|
229 Read on for more debugging hints.
|
Chris@41
|
230 </P>
|
Chris@41
|
231 <P>
|
Chris@41
|
232 All of the higher quality converters need to keep state while doing conversions
|
Chris@41
|
233 on segments of a large chunk of audio.
|
Chris@41
|
234 This state information is kept inside the private data pointed to by the
|
Chris@41
|
235 SRC_STATE pointer returned by the src_new() function.
|
Chris@41
|
236 This means, that when you want to start doing sample rate conversion on a
|
Chris@41
|
237 stream of data, you should call src_new() to get a new SRC_STATE pointer
|
Chris@41
|
238 (or alternatively, call src_reset() on an existing SRC_STATE pointer).
|
Chris@41
|
239 You should then pass this SRC_STATE pointer to the src_process() function
|
Chris@41
|
240 with each new block of audio data.
|
Chris@41
|
241 When you have completed the conversion, you can then call src_delete() on
|
Chris@41
|
242 the SRC_STATE pointer.
|
Chris@41
|
243 </P>
|
Chris@41
|
244 <P>
|
Chris@41
|
245 If you are doing all of the above correctly, you need to examine your usage
|
Chris@41
|
246 of the values passed to src_process() in the
|
Chris@41
|
247 <A HREF="api_misc.html#SRC_DATA">SRC_DATA</A>
|
Chris@41
|
248 struct.
|
Chris@41
|
249 Specifically:
|
Chris@41
|
250 </P>
|
Chris@41
|
251 <UL>
|
Chris@41
|
252 <LI> Check that input_frames and output_frames fields are being set in
|
Chris@41
|
253 terms of frames (number of sample values times channels) instead
|
Chris@41
|
254 of just the number of samples.
|
Chris@41
|
255 <LI> Check that you are using the return values input_frames_used and
|
Chris@41
|
256 output_frames_gen to update your source and destination pointers
|
Chris@41
|
257 correctly.
|
Chris@41
|
258 <LI> Check that you are updating the data_in and data_out pointers
|
Chris@41
|
259 correctly for each successive call.
|
Chris@41
|
260 </UL>
|
Chris@41
|
261 <P>
|
Chris@41
|
262 While doing the above, it is probably useful to compare what you are doing to
|
Chris@41
|
263 what is done in the example programs in the examples/ directory of the source
|
Chris@41
|
264 code tarball.
|
Chris@41
|
265 </P>
|
Chris@41
|
266 <P>
|
Chris@41
|
267 If you have done all of the above and are still having problems then its
|
Chris@41
|
268 probably time to email the author with the smallest chunk of code that
|
Chris@41
|
269 adequately demonstrates your problem.
|
Chris@41
|
270 This chunk should not need to be any more than 100 lines of code.
|
Chris@41
|
271 </P>
|
Chris@41
|
272
|
Chris@41
|
273 <!-- pepper -->
|
Chris@41
|
274 <!-- ========================================================================= -->
|
Chris@41
|
275 <A NAME="Q006"></A>
|
Chris@41
|
276 <H2><BR><B>Q6 : I'm use the SRC_SINC_* converters and up-sampling by a ratio of
|
Chris@41
|
277 2. I reset the converter and put in 1000 samples and I expect to get 2000
|
Chris@41
|
278 samples out, but I'm getting less than that. Why?</B></H2>
|
Chris@41
|
279 <P>
|
Chris@41
|
280 The short answer is that there is a transport delay inside the converter itself.
|
Chris@41
|
281 Long answer follows.
|
Chris@41
|
282 </P>
|
Chris@41
|
283 <P>
|
Chris@41
|
284 By way of example, the first time you call src_process() you might only get 1900
|
Chris@41
|
285 samples out.
|
Chris@41
|
286 However, after that first call all subsequent calls will probably get you about
|
Chris@41
|
287 2000 samples out for every 1000 samples you put in.
|
Chris@41
|
288 </P>
|
Chris@41
|
289 <P>
|
Chris@41
|
290 The main problems people have with this transport delay is that they need to read
|
Chris@41
|
291 out an exact number of samples and the transport delay scews this up.
|
Chris@41
|
292 The best way to overcome this problem is to always supply more samples on the
|
Chris@41
|
293 input than is actually needed to create the required number of output samples.
|
Chris@41
|
294 With reference to the example above, if you always supply 1500 samples at the
|
Chris@41
|
295 input, you will always get 2000 samples at the output.
|
Chris@41
|
296 You will always need to keep track of the number of input frames used on each
|
Chris@41
|
297 call to src_process() and deal with these values appropriately.
|
Chris@41
|
298 </P>
|
Chris@41
|
299
|
Chris@41
|
300 <!-- pepper -->
|
Chris@41
|
301 <!-- ========================================================================= -->
|
Chris@41
|
302 <A NAME="Q007"></A>
|
Chris@41
|
303 <H2><BR><B>Q7 : I have input and output sample rates that are integer
|
Chris@41
|
304 values, but the API wants me to divide one by the other and put the result
|
Chris@41
|
305 in a floating point number. Won't this case problems for long running
|
Chris@41
|
306 conversions?</B></H2>
|
Chris@41
|
307 <P>
|
Chris@41
|
308 The short answer is no, the precision of the ratio is many orders of magnitude
|
Chris@41
|
309 more than is really needed.
|
Chris@41
|
310 </P>
|
Chris@41
|
311 <P>
|
Chris@41
|
312 For the long answer, lets do come calculations.
|
Chris@41
|
313 Firstly, the <tt>src_ratio</tt> field is double precision floating point number
|
Chris@41
|
314 which has
|
Chris@41
|
315 <a href="http://en.wikipedia.org/wiki/Double_precision">
|
Chris@41
|
316 53 bits of precision</a>.
|
Chris@41
|
317 </P>
|
Chris@41
|
318 <P>
|
Chris@41
|
319 That means that the maximum error in your ratio converted to a double is one
|
Chris@41
|
320 bit in 2^53 which means the the double float value would be wrong by one sample
|
Chris@41
|
321 after 9007199254740992 samples have passed or wrong by more than half a sample
|
Chris@41
|
322 wrong after half that many (4503599627370496 samples) have passed.
|
Chris@41
|
323 </P>
|
Chris@41
|
324 <P>
|
Chris@41
|
325 Now if for example our output sample rate is 96kHz then
|
Chris@41
|
326 </P>
|
Chris@41
|
327 <pre>
|
Chris@41
|
328 4503599627370496 samples at 96kHz is 46912496118 seconds
|
Chris@41
|
329 46912496118 seconds is 781874935 minutes
|
Chris@41
|
330 781874935 minutes is 13031248 hours
|
Chris@41
|
331 13031248 hours is 542968 days
|
Chris@41
|
332 542968 days is 1486 years
|
Chris@41
|
333 </pre>
|
Chris@41
|
334 <P>
|
Chris@41
|
335 So, after 1486 years, the input will be wrong by more than half of one sampling
|
Chris@41
|
336 period.
|
Chris@41
|
337 </P>
|
Chris@41
|
338 <p>
|
Chris@41
|
339 All this assumes that the crystal oscillators uses to sample the audio stream
|
Chris@41
|
340 is perfect.
|
Chris@41
|
341 This is not the case.
|
Chris@41
|
342 According to
|
Chris@41
|
343 <a href="http://www.ieee-uffc.org/freqcontrol/quartz/vig/vigcomp.htm">
|
Chris@41
|
344 this web site</a>,
|
Chris@41
|
345 the accuracy of standard crystal oscillators (XO, TCXO, OCXO) is at best
|
Chris@41
|
346 1 in 100 million.
|
Chris@41
|
347 The <tt>src_ratio</tt> is therefore 45035996 times more accurate than the
|
Chris@41
|
348 crystal clock source used to sample the original audio signal and any potential
|
Chris@41
|
349 problem with the <tt>src_ratio</tt> being a floating point number will be
|
Chris@41
|
350 completely swamped by sampling inaccuracies.
|
Chris@41
|
351 </p>
|
Chris@41
|
352
|
Chris@41
|
353 <!-- <A HREF="mailto:aldel@mega-nerd.com">For the spam bots</A> -->
|
Chris@41
|
354
|
Chris@41
|
355 </DIV>
|
Chris@41
|
356 </TD></TR>
|
Chris@41
|
357 </TABLE>
|
Chris@41
|
358
|
Chris@41
|
359 </BODY>
|
Chris@41
|
360 </HTML>
|
Chris@41
|
361
|