Voxengo Premium Membership - All Voxengo Plugins For a Fixed One-Time Fee
Forums     Discussions     Free Audio Plugins r8brain API questions


First of all a big "thanks!" for offering such a nice and easy to use resampling library for free use.  You've made my life a lot easier... :)

I've successfully implemented r8brain in my freeware audio converter tool.  But I've a few questions, if you don't mind:

(1) For 6 channel audio data I'm calling r8b_executeMem2 with 48000 samples of channel 1, then with 48000 samples of channel 2, then with 48000 samples of channel 3 etc.  When I've fed 48000 samples of channel 6, I'm again beginning with channel 1.  Now I'm wondering: r8brain can't know which channel I'm feeding.  Doesn't that hurt resampling or dithering quality?  Because r8brain can't really store any "history" data?

(2) Let's say I want to resample from "48000" to "50500.5".  Now I'm feeding r8brain 48000 samples.  Obviously r8brain cannot really output 50500.5 samples.  So it has to either output 50500.0 or 50501.0 samples.  Now if I do this in a loop I'm missing 0.5 samples each second (or I have 0.5 samples too many each second).  What is the best way to handle this?  Do I need to feed 96000 samples so that I can receive 101001 samples?  That's no big problem for 48000 -> 50500.5.  But how can I solve this when I have really weird output rates, e.g.  48000.00123456789?  Is there an easy general way to solve this?

(3) If I feed 48000 samples at a time, r8brain cannot "mix"/interpolate the sample number 47999 of frame 1 with sample 0 of frame 2.  Doesn't that hurt audio quality?  Of course the problem is only there once every second if I feed 48000 samples, but still?

Maybe these are stupid questions.  I'm just wondering how to use r8brain in the best possible way.  Thanks very much... :)


madshi: (1) For 6 channel audio data I'm calling r8b_executeMem2 with 48000 samples of channel 1, then with 48000 samples of channel 2, then with 48000 samples of channel 3 etc.  When I've fed 48000 samples of channel 6, I'm again beginning with channel 1.  Now I'm wondering: r8brain can't know which channel I'm feeding.  Doesn't that hurt resampling or dithering quality?  Because r8brain can't really store any ''history'' data?

You can process that way if you process all data at once.  But this won't work if you are think about block processing.  Such approach will create discontinuities.

madshi: (2) Let's say I want to resample from ''48000'' to ''50500.5''.  Now I'm feeding r8brain 48000 samples.  Obviously r8brain cannot really output 50500.5 samples.  So it has to either output 50500.0 or 50501.0 samples.  Now if I do this in a loop I'm missing 0.5 samples each second (or I have 0.5 samples too many each second).  What is the best way to handle this?  Do I need to feed 96000 samples so that I can receive 101001 samples?  That's no big problem for 48000 -> 50500.5.  But how can I solve this when I have really weird output rates, e.g.  48000.00123456789?  Is there an easy general way to solve this?

Sample rate conversion never deals with individual samples.  It's a continous process which CAN produce partial sample delays.

madshi: (3) If I feed 48000 samples at a time, r8brain cannot ''mix''/interpolate the sample number 47999 of frame 1 with sample 0 of frame 2.  Doesn't that hurt audio quality?  Of course the problem is only there once every second if I feed 48000 samples, but still?

I've answered this in Q1 - r8b_executeMem2 is not meant to be used for block processing, and will produce clicks if you'll try to do so.

Here's an API for streamed processing:

procedure r8b_executeStream (var InFormat: TR8BInputFormat; OutRate: Double;

OutBitDepth, OutQuality: LongInt; var CancelFlag: LongInt;

Callback: TR8BCallback; p: Pointer; var err: TR8BError;

ReadCallback: TR8BReadCallback; WriteCallback: TR8BWriteCallback); cdecl;

TR8BReadCallback = function (var IObuffer: Pointer;

byteoffset, iobytes: LongInt): LongInt; cdecl;

TR8BWriteCallback = function (var IObuffer: Pointer;

iobytes: LongInt): LongInt; cdecl;

Callbacks return 0 if no error.  In read callback IObuffer should receive pointer to data (DLL does not provide its own read buffer).


Thanks much for the speedy reply!

Is r8b_executeStream thread safe?  I'd like to create one thread per channel so that I can process all channels at the same time.


Unfortunately, I can't say exactly if it is.  It does create an individual structure without dependence on global variables, but I do not know if memory allocations inside of it are thread-safe.

I've just tested this.  The dll is definitely not thread safe.  However, if I make sure that I carefully let only one thread run at the same time (while the other threads are waiting in ReadCallback) things are working fine - up to the point where I abort streaming (by returning 1 in ReadCallback).  In that very moment crazy things happen: Suddenly the thread I'm trying to stop takes over the identity (stack etc) of another thread!!

Is it possible that you're using Get/SetThreadContext in your dll somehow somewhere?  That's about the only thing I can think of that would explain the thread's "identity theft" during shutdown...

Thanks for your help!


No, Get/SetThreadContext should not be used.  The reason I'm unable to answer your question about thread-safety is because I've programmed this DLL a long time ago, and it used semi-professional tools (freepascal to be exact).  So, I can't be sure run-time library this DLL uses was programmed professionally.

But I guess you can process audio in several passes, two channels (stereo) per pass.

I understand that this DLL needs a serious re-programming especially considering I now use C++ only, but I do not have much free time at the moment, to devote it to such tool.


P.S: Got around the problem by loading one (renamed) separate copy of the r8b.dll for each channel.  Everything works fine now.

Ooops, funny, our posts crossed... :)

Of course a thread-safe dll would be nice to have, but I got everything working now with some ugly tricks.  So for my needs I don't really need a new version of the dll.

Sad to see you go C++.  I like Pascal/Delphi so much more... :P

This topic was last updated 180 days ago, and thus it was archived.  Replying is disabled for this topic.