AudioTK library
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
Anyone using the AudioTK library (https://github.com/mbrucher/AudioTK)?
---
I think it needs C++ tutorials since I can't figure out how to do a processing "loop" in C++ that takes audio in from some stream and return to some other stream, so that one could use it in a typical ProcessReplacing() function in a plug-in. The Python examples don't seem to help.
Also can/could you get parameters out of some of the classes so you could use them to modulate other parameters? Or does e.g. the AttackReleaseFilter generate as output the envelope so one could then plug that into something?
---
I think it needs C++ tutorials since I can't figure out how to do a processing "loop" in C++ that takes audio in from some stream and return to some other stream, so that one could use it in a typical ProcessReplacing() function in a plug-in. The Python examples don't seem to help.
Also can/could you get parameters out of some of the classes so you could use them to modulate other parameters? Or does e.g. the AttackReleaseFilter generate as output the envelope so one could then plug that into something?
Last edited by soundmodel on Tue Jul 28, 2015 3:21 pm, edited 1 time in total.
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
I am :p
I haven't finished writing the tutorials, it's a work in progress. My main examples are in Python because it's easy to draw curves, input data...
There are not that many stream sources and sinks available (as it's a pipeline library, all inputs and outputs can be seen as streams). The main ones you want to use are InPointerFilter and OutPointerFilter. Each time you initialize the pointer (with the maximum available size), it resets its internal state, and when you call process() on the pipeline sink, it will increment the internal counters.
The best examples of the library are the plugins themselves : https://github.com/mbrucher/ATK-plugins
Not all the parameters can be changed on the fly with another stream, only specific filters can have this. For EQs, there is the TimeVaryingIIRFilter to change the central/cut frequency, and for delays, the UniversalVariableDelayLineFilter can also have its delay from an input stream.
I haven't finished writing the tutorials, it's a work in progress. My main examples are in Python because it's easy to draw curves, input data...
There are not that many stream sources and sinks available (as it's a pipeline library, all inputs and outputs can be seen as streams). The main ones you want to use are InPointerFilter and OutPointerFilter. Each time you initialize the pointer (with the maximum available size), it resets its internal state, and when you call process() on the pipeline sink, it will increment the internal counters.
The best examples of the library are the plugins themselves : https://github.com/mbrucher/ATK-plugins
Not all the parameters can be changed on the fly with another stream, only specific filters can have this. For EQs, there is the TimeVaryingIIRFilter to change the central/cut frequency, and for delays, the UniversalVariableDelayLineFilter can also have its delay from an input stream.
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
If they do nFrames sized processing in the ProcessReplacing(), like e.g.:
inFilter.set_pointer(inputs[0], nFrames);
outFilter.set_pointer(outputs[0], nFrames);
outFilter.process(nFrames);
Then does it mean that they process "continuously"?
If one specified a buffersize in the constructor, then would one need to "reset" the buffers somehow, everytime they get full?
inFilter.set_pointer(inputs[0], nFrames);
outFilter.set_pointer(outputs[0], nFrames);
outFilter.process(nFrames);
Then does it mean that they process "continuously"?
If one specified a buffersize in the constructor, then would one need to "reset" the buffers somehow, everytime they get full?
Last edited by soundmodel on Thu Jul 30, 2015 8:42 pm, edited 1 time in total.
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
They process nFrames as you asked it in output.process(), in one batch.
The buffersize set in the constructor is the same as in set_pointer, it's in case you are doing things differently than a plugin. In my plugins, the constructor is set to nullptr, 0.
Of course you need to reset the buffer each time they are full, otherwise there would be a memory error, just call set_pointer on the new buffer you have. This is what I do for plugins, it doesn't cost much to do so.
The buffersize set in the constructor is the same as in set_pointer, it's in case you are doing things differently than a plugin. In my plugins, the constructor is set to nullptr, 0.
Of course you need to reset the buffer each time they are full, otherwise there would be a memory error, just call set_pointer on the new buffer you have. This is what I do for plugins, it doesn't cost much to do so.
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
But e.g. in the compressor example, as the attack and release times may be longer than nFrames, then are the samples buffered somehow (inside the "Filters"), so that the attack and release are applied over a longer period of samples (acquired over several calls to ProcessReplacing())?Miles1981 wrote:They process nFrames as you asked it in output.process(), in one batch.
The buffersize set in the constructor is the same as in set_pointer, it's in case you are doing things differently than a plugin. In my plugins, the constructor is set to nullptr, 0.
Of course you need to reset the buffer each time they are full, otherwise there would be a memory error, just call set_pointer on the new buffer you have. This is what I do for plugins, it doesn't cost much to do so.
It's something that I don't need to care about?
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
You don't have to care about it, the library takes care of buffering internally if required. Then for attack/release you specify a memory factor, so you only need the last sample (internally, ATK handles it, as I've said). It's an IIR filter (order 1) in some way, it doesn't recompute the RMS value, it's kind of a geometric sum over all the samples with memory_factor^n with increasing n as you go back in time.
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
How do you get the coefficients for a "timevarying" allpass filter?
Or how do you declare the entire timevarying allpass filter?
Or how do you declare the entire timevarying allpass filter?
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
Why does the compressor example do these lines:
applyGainFilter.set_input_port(0, &attackReleaseFilter, 0);
applyGainFilter.set_input_port(1, &inFilter, 0);
https://github.com/mbrucher/ATK-plugins ... or.cpp#L91
What construct could be used to extract the gain reduction envelope that the compressor does?
applyGainFilter.set_input_port(0, &attackReleaseFilter, 0);
applyGainFilter.set_input_port(1, &inFilter, 0);
https://github.com/mbrucher/ATK-plugins ... or.cpp#L91
What construct could be used to extract the gain reduction envelope that the compressor does?
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
I only have one example of a time varying filter in Python: https://github.com/mbrucher/AudioTK/blo ... ryingEQ.pyFluky wrote:How do you get the coefficients for a "timevarying" allpass filter?
Or how do you declare the entire timevarying allpass filter?
The second port is the one in charge of setting the frequency.
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
The gain envelope is given by the attack release filter (it is set after the gain transform because the gain transform is discrete as it is using a LUT).Fluky wrote:Why does the compressor example do these lines:
applyGainFilter.set_input_port(0, &attackReleaseFilter, 0);
applyGainFilter.set_input_port(1, &inFilter, 0);
https://github.com/mbrucher/ATK-plugins ... or.cpp#L91
What construct could be used to extract the gain reduction envelope that the compressor does?
applyGainFilter is only multiplying the two streams together.
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
So can I use the attack release filter as such?
input pointer filter -> attack release filter -> output pointer filter ?
input pointer filter -> attack release filter -> output pointer filter ?
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
Yes, of course. The AR filter will give you the envelope of your signal from the abs or RMS.
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
How can one create a envelope using an array of mere 1.0s, so that one can use it for scaling a parameter?
What kind of pointer do I need to pass to the input of the attack release filter "chain"? Of course it should be a pointer that contains 1.0s.
Should it be a dynamic array? So I can create n-sized blocks inside the "ProcessReplacing" function?
Could it be a std::vector?
Before I was just passing the input of a continuous stream of audio, but now that I need to create the array. Then how to do it?
What kind of pointer do I need to pass to the input of the attack release filter "chain"? Of course it should be a pointer that contains 1.0s.
Should it be a dynamic array? So I can create n-sized blocks inside the "ProcessReplacing" function?
Could it be a std::vector?
Before I was just passing the input of a continuous stream of audio, but now that I need to create the array. Then how to do it?
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
If you just want to scale a stream by a constant, why don't you use the VolumeFilter instead? https://github.com/mbrucher/AudioTK/blo ... meFilter.h
-
- KVRian
- Topic Starter
- 1091 posts since 28 May, 2010 from Finland
No I mean that I want to create an envelope out of an array of 1.0s. That way I can control the value range that I'm getting out.