cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: Secret Rabbit Code (aka libsamplerate) cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:
cannam@85: SRC.png cannam@85:
cannam@85: cannam@85:
cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:
cannam@85:
cannam@85: cannam@85: cannam@85:
cannam@85:
cannam@85: cannam@85:

Frequently Asked Questions

cannam@85:

cannam@85: Q1 : Is it normal for the output of libsamplerate to be louder cannam@85: than its input?

cannam@85: Q2 : On Unix/Linux/MacOSX, what is the best way of detecting cannam@85: the presence and location of libsamplerate and its header file using cannam@85: autoconf?

cannam@85: Q3 : If I upsample and downsample to the original rate, for cannam@85: example 44.1->96->44.1, do I get an identical signal as the one before the cannam@85: up/down resampling?

cannam@85: Q4 : If I ran src_simple (libsamplerate) on small chunks (160 cannam@85: frames) would that sound bad?

cannam@85: Q5 : I'm using libsamplerate but the high quality settings cannam@85: sound worse than the SRC_LINEAR converter. Why?

cannam@85: Q6 : I'm use the SRC_SINC_* converters and up-sampling by a ratio of cannam@85: 2. I reset the converter and put in 1000 samples and I expect to get 2000 cannam@85: samples out, but I'm getting less than that. Why?

cannam@85: Q7 : I have input and output sample rates that are integer cannam@85: values, but the API wants me to divide one by the other and put the result cannam@85: in a floating point number. Won't this case problems for long running cannam@85: conversions?

cannam@85:

cannam@85:
cannam@85: cannam@85: cannam@85:


Q1 : Is it normal for the output of libsamplerate to be louder cannam@85: than its input?

cannam@85:

cannam@85: The output of libsamplerate will be roughly the same volume as the input. cannam@85: However, even if the input is strictly in the range (-1.0, 1.0), it is still cannam@85: possible for the output to contain peak values outside this range. cannam@85:

cannam@85:

cannam@85: Consider four consecutive samples of [0.5 0.999 0.999 0.5]. cannam@85: If we are up sampling by a factor of two we need to insert samples between cannam@85: each of the existing samples. cannam@85: Its pretty obvious then, that the sample between the two 0.999 values should cannam@85: and will be bigger than 0.999. cannam@85:

cannam@85:

cannam@85: This means that anyone using libsamplerate should normalize its output before cannam@85: doing things like saving the audio to a 16 bit WAV file. cannam@85:

cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:


Q2 : On Unix/Linux/MacOSX, what is the best way of detecting cannam@85: the presence and location of libsamplerate and its header file using cannam@85: autoconf?

cannam@85: cannam@85:

cannam@85: libsamplerate uses the pkg-config (man pkg-config) method of registering itself cannam@85: with the host system. cannam@85: The best way of detecting its presence is using something like this in configure.ac cannam@85: (or configure.in): cannam@85:

cannam@85: cannam@85:
cannam@85:     PKG_CHECK_MODULES(SAMPLERATE, samplerate >= 0.1.3,
cannam@85:             ac_cv_samplerate=1, ac_cv_samplerate=0)
cannam@85: 
cannam@85:     AC_DEFINE_UNQUOTED([HAVE_SAMPLERATE],${ac_cv_samplerate},
cannam@85:             [Set to 1 if you have libsamplerate.])
cannam@85: 
cannam@85:     AC_SUBST(SAMPLERATE_CFLAGS)
cannam@85:     AC_SUBST(SAMPLERATE_LIBS)
cannam@85: 
cannam@85:

cannam@85: This will automatically set the SAMPLERATE_CFLAGS and SAMPLERATE_LIBS cannam@85: variables which can be used in Makefile.am or Makefile.in like this: cannam@85:

cannam@85:
cannam@85:         SAMPLERATE_CFLAGS = @SAMPLERATE_CFLAGS@
cannam@85:         SAMPLERATE_LIBS = @SAMPLERATE_LIBS@
cannam@85: 
cannam@85: cannam@85:

cannam@85: If you install libsamplerate from source, you will probably need to set the cannam@85: PKG_CONFIG_PATH environment variable's suggested at the end of the cannam@85: libsamplerate configure process. For instance on my system I get this: cannam@85:

cannam@85:
cannam@85:     -=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-=-
cannam@85: 
cannam@85:       Configuration summary :
cannam@85: 
cannam@85:         Version : ..................... 0.1.3
cannam@85:         Enable debugging : ............ no
cannam@85: 
cannam@85:       Tools :
cannam@85: 
cannam@85:         Compiler is GCC : ............. yes
cannam@85:         GCC major version : ........... 3
cannam@85: 
cannam@85:       Extra tools required for testing and examples :
cannam@85: 
cannam@85:         Have FFTW : ................... yes
cannam@85:         Have libsndfile : ............. yes
cannam@85:         Have libefence : .............. no
cannam@85: 
cannam@85:       Installation directories :
cannam@85: 
cannam@85:         Library directory : ........... /usr/local/lib
cannam@85:         Program directory : ........... /usr/local/bin
cannam@85:         Pkgconfig directory : ......... /usr/local/lib/pkgconfig
cannam@85: 
cannam@85: cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:


Q3 : If I upsample and downsample to the original rate, for cannam@85: example 44.1->96->44.1, do I get an identical signal as the one before the cannam@85: up/down resampling?

cannam@85:

cannam@85: The short answer is that for the general case, no, you don't. cannam@85: The long answer is that for some signals, with some converters, you will cannam@85: get very, very close. cannam@85:

cannam@85:

cannam@85: In order to resample correctly (ie using the SRC_SINC_* converters), cannam@85: filtering needs to be applied, regardless of whether its upsampling or cannam@85: downsampling. cannam@85: This filter needs to attenuate all frequencies above 0.5 times the minimum of cannam@85: the source and destination sample rate (call this fshmin). cannam@85: Since the filter needed to achieve full attenuation at this point, it has to cannam@85: start rolling off a some frequency below this point. cannam@85: It is this rolloff of the very highest frequencies which causes some of the cannam@85: loss. cannam@85:

cannam@85:

cannam@85: The other factor is that the filter itself can introduce transient artifacts cannam@85: which causes the output to be different to the input. cannam@85:

cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:


Q4 : If I ran src_simple on small chunks (say 160 frames) would that cannam@85: sound bad?

cannam@85:

cannam@85: Well if you are after odd sound effects, it might sound OK. cannam@85: If you are after high quality sample rate conversion you will be disappointed. cannam@85:

cannam@85:

cannam@85: The src_simple() was designed to provide a simple to use interface for people cannam@85: who wanted to do sample rate conversion on say, a whole file all at once. cannam@85:

cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:


Q5 : I'm using libsamplerate but the high quality settings cannam@85: sound worse than the SRC_LINEAR converter. Why?

cannam@85:

cannam@85: There are two possible problems. cannam@85: Firstly, if you are using the src_simple() function on successive blocks cannam@85: of a stream of samples, you will get bad results. The src_simple() function cannam@85: is designed for use on a whole sound file, all at once, not on contiguous cannam@85: segments of the same sound file. cannam@85: To fix the problem, you need to move to the src_process() API or the callback cannam@85: based API. cannam@85:

cannam@85:

cannam@85: If you are already using the src_process() API or the callback based API and cannam@85: the high quality settings sound worse than SRC_LINEAR, then you have other cannam@85: problems. cannam@85: Read on for more debugging hints. cannam@85:

cannam@85:

cannam@85: All of the higher quality converters need to keep state while doing conversions cannam@85: on segments of a large chunk of audio. cannam@85: This state information is kept inside the private data pointed to by the cannam@85: SRC_STATE pointer returned by the src_new() function. cannam@85: This means, that when you want to start doing sample rate conversion on a cannam@85: stream of data, you should call src_new() to get a new SRC_STATE pointer cannam@85: (or alternatively, call src_reset() on an existing SRC_STATE pointer). cannam@85: You should then pass this SRC_STATE pointer to the src_process() function cannam@85: with each new block of audio data. cannam@85: When you have completed the conversion, you can then call src_delete() on cannam@85: the SRC_STATE pointer. cannam@85:

cannam@85:

cannam@85: If you are doing all of the above correctly, you need to examine your usage cannam@85: of the values passed to src_process() in the cannam@85: SRC_DATA cannam@85: struct. cannam@85: Specifically: cannam@85:

cannam@85:
    cannam@85:
  • Check that input_frames and output_frames fields are being set in cannam@85: terms of frames (number of sample values times channels) instead cannam@85: of just the number of samples. cannam@85:
  • Check that you are using the return values input_frames_used and cannam@85: output_frames_gen to update your source and destination pointers cannam@85: correctly. cannam@85:
  • Check that you are updating the data_in and data_out pointers cannam@85: correctly for each successive call. cannam@85:
cannam@85:

cannam@85: While doing the above, it is probably useful to compare what you are doing to cannam@85: what is done in the example programs in the examples/ directory of the source cannam@85: code tarball. cannam@85:

cannam@85:

cannam@85: If you have done all of the above and are still having problems then its cannam@85: probably time to email the author with the smallest chunk of code that cannam@85: adequately demonstrates your problem. cannam@85: This chunk should not need to be any more than 100 lines of code. cannam@85:

cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:


Q6 : I'm use the SRC_SINC_* converters and up-sampling by a ratio of cannam@85: 2. I reset the converter and put in 1000 samples and I expect to get 2000 cannam@85: samples out, but I'm getting less than that. Why?

cannam@85:

cannam@85: The short answer is that there is a transport delay inside the converter itself. cannam@85: Long answer follows. cannam@85:

cannam@85:

cannam@85: By way of example, the first time you call src_process() you might only get 1900 cannam@85: samples out. cannam@85: However, after that first call all subsequent calls will probably get you about cannam@85: 2000 samples out for every 1000 samples you put in. cannam@85:

cannam@85:

cannam@85: The main problems people have with this transport delay is that they need to read cannam@85: out an exact number of samples and the transport delay scews this up. cannam@85: The best way to overcome this problem is to always supply more samples on the cannam@85: input than is actually needed to create the required number of output samples. cannam@85: With reference to the example above, if you always supply 1500 samples at the cannam@85: input, you will always get 2000 samples at the output. cannam@85: You will always need to keep track of the number of input frames used on each cannam@85: call to src_process() and deal with these values appropriately. cannam@85:

cannam@85: cannam@85: cannam@85: cannam@85: cannam@85:


Q7 : I have input and output sample rates that are integer cannam@85: values, but the API wants me to divide one by the other and put the result cannam@85: in a floating point number. Won't this case problems for long running cannam@85: conversions?

cannam@85:

cannam@85: The short answer is no, the precision of the ratio is many orders of magnitude cannam@85: more than is really needed. cannam@85:

cannam@85:

cannam@85: For the long answer, lets do come calculations. cannam@85: Firstly, the src_ratio field is double precision floating point number cannam@85: which has cannam@85: cannam@85: 53 bits of precision. cannam@85:

cannam@85:

cannam@85: That means that the maximum error in your ratio converted to a double is one cannam@85: bit in 2^53 which means the the double float value would be wrong by one sample cannam@85: after 9007199254740992 samples have passed or wrong by more than half a sample cannam@85: wrong after half that many (4503599627370496 samples) have passed. cannam@85:

cannam@85:

cannam@85: Now if for example our output sample rate is 96kHz then cannam@85:

cannam@85:
cannam@85:     4503599627370496 samples at 96kHz is 46912496118 seconds
cannam@85:     46912496118 seconds is 781874935 minutes
cannam@85:     781874935 minutes is 13031248 hours
cannam@85:     13031248 hours is 542968 days
cannam@85:     542968 days is 1486 years
cannam@85: 
cannam@85:

cannam@85: So, after 1486 years, the input will be wrong by more than half of one sampling cannam@85: period. cannam@85:

cannam@85:

cannam@85: All this assumes that the crystal oscillators uses to sample the audio stream cannam@85: is perfect. cannam@85: This is not the case. cannam@85: According to cannam@85: cannam@85: this web site, cannam@85: the accuracy of standard crystal oscillators (XO, TCXO, OCXO) is at best cannam@85: 1 in 100 million. cannam@85: The src_ratio is therefore 45035996 times more accurate than the cannam@85: crystal clock source used to sample the original audio signal and any potential cannam@85: problem with the src_ratio being a floating point number will be cannam@85: completely swamped by sampling inaccuracies. cannam@85:

cannam@85: cannam@85: cannam@85: cannam@85:
cannam@85:
cannam@85: cannam@85: cannam@85: cannam@85: