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

Released v1.5 with minor precision enhancements
Image

Post

Thanks. :)

Post

Aleksey Vaneev wrote:No, that's not overkill, I myself use linear-phase oversampling in Voxengo plug-ins that is close to that latency number and quality. You can reduce latency by using a lower ReqAtten and higher ReqTransBand values, it's flexible.
I have been trying to implement r8brain in an oversampling scenario and I have a question. Using r8brain to downsample would be the obvious choice; however, what would be the recommended method for upsampling? Would zero-stuffing with some other filtering work more efficiently when upsampling? Or, would it be better to use r8brain for this as well?

Thanks for the great library.

Post

random_id wrote:
Aleksey Vaneev wrote:No, that's not overkill, I myself use linear-phase oversampling in Voxengo plug-ins that is close to that latency number and quality. You can reduce latency by using a lower ReqAtten and higher ReqTransBand values, it's flexible.
I have been trying to implement r8brain in an oversampling scenario and I have a question. Using r8brain to downsample would be the obvious choice; however, what would be the recommended method for upsampling? Would zero-stuffing with some other filtering work more efficiently when upsampling? Or, would it be better to use r8brain for this as well?

Thanks for the great library.
I would use r8brain for both the upsampling and downsampling.

Post

random_id wrote: I have been trying to implement r8brain in an oversampling scenario and I have a question. Using r8brain to downsample would be the obvious choice; however, what would be the recommended method for upsampling? Would zero-stuffing with some other filtering work more efficiently when upsampling? Or, would it be better to use r8brain for this as well?
r8brain-free-src can be used for both tasks. Besides, I think it would be hard to find a faster implementation of linear-phase resampling than what r8brain-free-src offers.

If you just need to do 2x,4x,8x,etc upsampling/downsampling you may use objects of the CDSPBlockConvolver class directly. But you'll need to study the CDSPFIRFilterCache::getLPFilter() function to be fluent with filter parameters. For efficient multi-step resampling the transition bands of intermediate resampling steps must be set to larger values.
Image

Post

After a bit of thought, I think I'll add an additional "resampler" class which will do the "power of 2" resampling exclusively. It will be different to the CDSPResampler class in that it will report the full latency amount without consuming it automatically.

Right now I think CDSPResampler class cannot be used for oversampling inside plug-in's signal path, because CDSPResampler is not working synchronously.
Image

Post

Aleksey Vaneev wrote:After a bit of thought, I think I'll add an additional "resampler" class which will do the "power of 2" resampling exclusively. It will be different to the CDSPResampler class in that it will report the full latency amount without consuming it automatically.
That would be a nice addition. :cool:
Aleksey Vaneev wrote:Right now I think CDSPResampler class cannot be used for oversampling inside plug-in's signal path, because CDSPResampler is not working synchronously.
Well, I have experimented with this only briefly, but it does seem to work already. However, I couldn't find a way to read out the latency programmatically, so I just measured it manually.

Post

Tale wrote:Well, I have experimented with this only briefly, but it does seem to work already. However, I couldn't find a way to read out the latency programmatically, so I just measured it manually.
Yes, but that's a work-around. Besides, for the overall latency to remain a whole number, downsampling step may require insertion of several samples. So, in general case things are quite complicated if one wants to have consistent results at any setting.
Image

Post

Aleksey Vaneev wrote:Yes, but that's a work-around. Besides, for the overall latency to remain a whole number, downsampling step may require insertion of several samples. So, in general case things are quite complicated if one wants to have consistent results at any setting.
This was for 2x up, 2x down, and measuring the latency each time you change something was a pain, although it did seemed to be consistent.

Still, like I already expressed, I would very much welcome the addition of a better solution. :)

Post

this is great! i am currently working on a c# wrapper.
but there is one thing i don't understand. the process function has double* as input and output type for the buffers. so does the process function only work with double[] types and i have to provide the samples always as double? and how does this work together with the resolution of the resampler type that i create?

i ask this because in my engine am using only 32-bit float buffers and it would need an additional step to convert the input/output buffers which would be painful for the performance. also the input to the resampler is often PCM 16 or 24 bit integer data directly from a wave file that i would need in 32-bit float buffer representation after.

so the setup is most of the time:

wavafile not in engine sample rate -> resampler -> 32-bit float buffer in engine sample rate

whats your suggestion for an optimal signal flow?

here is my first take on it:
https://github.com/tebjan/VVVV.Audio/bl ... nverter.cs

Post

and i have another question, in which cases does the op0 output buffer point to the input buffer? can you generalize this? only when downsampling?

this is an important question since the c# wrapper has to know whether it has to allocate unmanaged memory. in cases when the op0 output buffer does not point to the input buffer it can just pin the input array for the time of the call and no copy is needed.

Post

i am not sure what i am doing wrong... the process method seems to work, but i get very high output values, like 3.15490588487157E+287. have you ever seen this? might be an obvious problem... my input values are double samples in the range [-1..1], this is correct, or not?

Post

Aleksey Vaneev wrote:After a bit of thought, I think I'll add an additional "resampler" class which will do the "power of 2" resampling exclusively. It will be different to the CDSPResampler class in that it will report the full latency amount without consuming it automatically.
That would be useful. :)

Post

tonfilm wrote:this is great! i am currently working on a c# wrapper.
but there is one thing i don't understand. the process function has double* as input and output type for the buffers. so does the process function only work with double[] types and i have to provide the samples always as double? and how does this work together with the resolution of the resampler type that i create?
Yes, you have to provide "double" samples, always.
tonfilm wrote:i ask this because in my engine am using only 32-bit float buffers and it would need an additional step to convert the input/output buffers which would be painful for the performance. also the input to the resampler is often PCM 16 or 24 bit integer data directly from a wave file that i would need in 32-bit float buffer representation after.
Such conversion is not "pain", it takes no more than 0.1% of conversion time.

Moreover, today it's much more practical to work with "double" buffers exclusively, it's an outdated approach, to use 32-bit float. From my tests, "doubles" work visibly faster than "floats", at least Intel C++ Compiler creates a faster code when "double" type is used.
tonfilm wrote:and i have another question, in which cases does the op0 output buffer point to the input buffer? can you generalize this? only when downsampling?

this is an important question since the c# wrapper has to know whether it has to allocate unmanaged memory. in cases when the op0 output buffer does not point to the input buffer it can just pin the input array for the time of the call and no copy is needed.
I would not rely on any pointer comparisons. You have to write your code in a way so that a new block of input data is not processed until you consume all output data.
tonfilm wrote:i am not sure what i am doing wrong... the process method seems to work, but i get very high output values, like 3.15490588487157E+287. have you ever seen this? might be an obvious problem... my input values are double samples in the range [-1..1], this is correct, or not?
You have bug somewhere definitely.
Image

Post

Aleksey Vaneev wrote: I would not rely on any pointer comparisons. You have to write your code in a way so that a new block of input data is not processed until you consume all output data.
tonfilm wrote:i am not sure what i am doing wrong... the process method seems to work, but i get very high output values, like 3.15490588487157E+287. have you ever seen this? might be an obvious problem... my input values are double samples in the range [-1..1], this is correct, or not?
You have bug somewhere definitely.
Yes, that was the case, i was just to overworked to see it. i handed over the wrong pointer to the input array, there are subtle details in .NET interop. it works now like a charm.

do you think i should host a project on github for the .NET wrapper? maybe others are interested too. current code is here:
https://github.com/tebjan/VVVV.Audio/bl ... nverter.cs
Aleksey Vaneev wrote:
Moreover, today it's much more practical to work with "double" buffers exclusively, it's an outdated approach, to use 32-bit float. From my tests, "doubles" work visibly faster than "floats", at least Intel C++ Compiler creates a faster code when "double" type is used.
this is very interesting... as i am in an early stage of the engine, i can still switch to double precision as the overall buffer format. from what you write, it sounds like the thing to do... and hello, we live in 2014 soon, 64-bit machines are here to stay. but i fear that 90% of all VST plugins do not support double precision and modular vst routing is one of the core features of the engine. what do you think? maybe i should open a separate discussion thread for that... :)

Post Reply

Return to “DSP and Plugin Development”