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... :)
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.
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.
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.