Open source high-quality pro audio sample rate converter library released from Voxengo

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

I've just checked the "power of 2" downsampling - it is only marginally more efficient at the last step than fractional delay interpolation. Interpolator uses just 40 taps, that's why it can hardly be beaten by the "power of 2" resampling.

Can't tell about "power of 2" upsampling yet, but I think it won't be much different.
Last edited by Aleksey Vaneev on Wed Aug 21, 2013 4:01 pm, edited 2 times in total.
Image

Post

If you look at http://src.infinitewave.ca/ , Secret rabbit code is not that good, its "high dynamic range" applies to the upper part of the spectrum only.

r8brain-free-src achieves 260 dB SNR when resampling a sine-wave signal. But only 170 dB SNR when resampling white-noise signal (probably due to a simultaneous intermix of large and low-amplitude signals in the noise). It's a quirky thing - to benchmark SRC algorithms.

The maximal theoretical SNR of 64-bit "double" type (53-bit mantissa) is 319 dB, but in practice around 310 dB.
Image

Post

Aleksey Vaneev wrote: r8brain-free-src does not offer continuous sample rate change, but I think for continuous change using a cross-fade technique is a lot better thing and does not compromise quality of SRC.
Well, it depends on what you want to vary the sample-rate for.. but in general continuous "audio-rate" sample-rate variation is a huge can of worms, because from the theoretical point of view the sinc-interpolation isn't really valid anymore (it's basically just the special case that you get with fixed-rate).

From when I last messed with that stuff (not that I have a really good solution, but I've spent some time trying to find one).. one trick one can do is to use band-limited zero-order-hold (or something similar, like interpolation of the approximated derivative) instead of sinc-reconstruction, to push the noise from the modulation to the high frequencies. It's still very much wrong from the theoretical point of view, but works reasonably.

In any case it's a whole different problem from just doing fixed-rate or "slowly-changing" sample-rate conversion (where "slowly-changing" basically comes down to "modulation isn't fast enough to introduce significant side-bands").

Post

In my opinion, continuous sample rate changes can be done without issues, even by using r8brain-free-src if the destination sample rate is always higher than the source sample rate. The CDSPFracInterpolator class can be easily changed to non-constant sample step size.

Of course even slow changes to sample rate cause transient artifacts by itself, but the bank of fractional delay filters won't fail.
Image

Post

Great ! Thanks for this, could you elaborate a little bit about why Reaper (or other's as I don't want to put the stigma on Reaper) resampling fails (in someway) ?
I was interested in this a few months before and someone gave me link a link to a website referencing most of audio applications (daws, wave editors, etc...) and showing graphically the differences between them while resampling (or changing bit depth) but I was not aware enough to understand. I was recommended to use r8brain to do my downsampling :)

EDIT : I should read thread more carefully before posting. Someone already posted a link to the website I was thinking of, and Aleksey already answered about Reaper's src. Anyway thanks !
Last edited by Davias on Wed Aug 21, 2013 8:16 pm, edited 1 time in total.

Post

Well, while SRC algorithm can be analysed technically, I myself sometimes hear artifacts that are not just aliasing or damped highs. Sometimes SRC sounds "non-transparent", like convolved with some room impulse response.
Image

Post

The "power of 2" resampling was added. The "power of 2" upsampling turned out to be considerably more efficient than fractional interpolation.
Image

Post

Thank you very much :love: I'm going to try it asap :wink:

Post

I was lucky to find an even better, "Vaneev" windowing function for fractional delay filters. This allowed to reduce the number of taps from 40 to 38 and that strangely gave not just 5%, but around 9% more overall speed to the conversion, probably because windowing function is now more optimal, with less "near zero" values in the filter.

So, now even white-noise resampling achieves 220 dB SNR.
Image

Post

Hopefully at some point Cockos will include both r8b and SoX. SoX seems to be an even better solution than r8b, judging by infinitewave graphs...

Post

Yes, SoX looks good, but infinitewave should benchmark this newer r8brain-free-src library with comparable settings first. infinitewave includes older r8brain algorithm version.
Image

Post

Given many SRC algorithms now approach the theoretical maximum of noise-free resampling, the speed of conversion becomes another important factor.
Image

Post

Thanks for sharing this, especially so liberally licensed. :)

I have just quickly reimplemented Combo Model F's internal IR resampling, and it seems to work great. I did encounter a two minor issues:

1. My x86 build environment (MSVC 2008) seems to be missing <stdint.h>. However, <stdint.h> seems to be required only when using IPP, so I propose the following simple patch on r8bbase.h:

Code: Select all

diff --git a/r8bbase.h b/r8bbase.h
index 4b820b1..71ed9a1 100644
--- a/r8bbase.h
+++ b/r8bbase.h
@@ -142,12 +142,15 @@
 #ifndef R8BBASE_INCLUDED
 #define R8BBASE_INCLUDED
 
-#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
 #include "r8bconf.h"
 
+#if R8B_IPP
+	#include <stdint.h>
+#endif // R8B_IPP
+
 #if defined( R8B_WIN )
 	#include <windows.h>
 #else // R8B_WIN
2. There seems to be some VOX_WIN #ifdefs left, which I guess should have been replaced with R8B_WIN, so here is another r8bbase.h patch:

Code: Select all

diff --git a/r8bbase.h b/r8bbase.h
index 71ed9a1..34240e7 100644
--- a/r8bbase.h
+++ b/r8bbase.h
@@ -532,24 +532,24 @@ struct CSyncObject
 public:
 	CSyncObject()
 	{
-		#if defined( VOX_WIN )
+		#if defined( R8B_WIN )
 			InitializeCriticalSectionAndSpinCount( &CritSec, 4000 );
-		#else // VOX_WIN
+		#else // R8B_WIN
 			pthread_mutexattr_t MutexAttrs;
 			pthread_mutexattr_init( &MutexAttrs );
 			pthread_mutexattr_settype( &MutexAttrs, PTHREAD_MUTEX_RECURSIVE );
 			pthread_mutex_init( &Mutex, &MutexAttrs );
 			pthread_mutexattr_destroy( &MutexAttrs );
-		#endif // VOX_WIN
+		#endif // R8B_WIN
 	}
 
 	~CSyncObject()
 	{
-		#if defined( VOX_WIN )
+		#if defined( R8B_WIN )
 			DeleteCriticalSection( &CritSec );
-		#else // VOX_WIN
+		#else // R8B_WIN
 			pthread_mutex_destroy( &Mutex );
-		#endif // VOX_WIN
+		#endif // R8B_WIN
 	}
 
 	/**
@@ -559,11 +559,11 @@ public:
 
 	void acquire()
 	{
-		#if defined( VOX_WIN )
+		#if defined( R8B_WIN )
 			EnterCriticalSection( &CritSec );
-		#else // VOX_WIN
+		#else // R8B_WIN
 			pthread_mutex_lock( &Mutex );
-		#endif // VOX_WIN
+		#endif // R8B_WIN
 	}
 
 	/**
@@ -573,22 +573,22 @@ public:
 
 	void release()
 	{
-		#if defined( VOX_WIN )
+		#if defined( R8B_WIN )
 			LeaveCriticalSection( &CritSec );
-		#else // VOX_WIN
+		#else // R8B_WIN
 			pthread_mutex_unlock( &Mutex );
-		#endif // VOX_WIN
+		#endif // R8B_WIN
 	}
 
 private:
-	#if defined( VOX_WIN )
+	#if defined( R8B_WIN )
 		CRITICAL_SECTION CritSec; ///< Standard Windows critical section
 			///< structure.
 			///<
-	#else // VOX_WIN
+	#else // R8B_WIN
 		pthread_mutex_t Mutex; ///< pthread.h mutex object.
 			///<
-	#endif // VOX_WIN
+	#endif // R8B_WIN
 };
 
 /**

Post

Yes, VOX_WIN defs are an error, I will fix it.

I will remove <stdint.h> dependency completely by using unsigned char instead of uint8_t. stdint.h is a standard header for GCC, Mac OS X and Linux, and the latest Intel C++.

I also plan to add "filter phasing" option so that min-phase filters can be also used.

Thanks for checking!
Image

Post

Aleksey Vaneev wrote:stdint.h is a standard header for GCC, Mac OS X and Linux, and the latest Intel C++.
It is a standard header for MSVC 2010 and 2012 as well. However, on x86 I still support WinXP SP1 (for now anyway), so I use an older compiler for that platform.

--

Just to make sure I am correctly understanding how this library is licensed: If I use this in a (closed-source) project, say Combo Model F, you are happy as long as I credit you (as specified in other/License.txt) in the PDF documentation, right?

Post Reply

Return to “DSP and Plugin Development”