Closed dhng22 closed 1 month ago
Hi, I would like to integrate this library as well in a realtime processing context like dhng22, but the API really confuse me. In particular it seam to me that the library have to take control on the transport/read position while usually the time-stretching libraries only do the processing on a block of audio that it's provided to it. There's any reason why the library need to have the control on the read position?
There's any way to use it in a chain of processors? Like in the example code showed by dhng22, usually in a processors chain a time-stretching library provide a "maximum input frames needed" to allocate an input buffer and some way to calculate how many input frames are needed to have a specific amount of output frames. Based on that information we usually feed some chunks of input data, call the processing and check if enough output data are available to fill an output buffer, reading the output into circular buffers to compensate for input/output discrepancy.
I've tried to understand how to do that with the current API but I'm missing a way to specify in the Request how many frames I need the library to process or any way to do some calculations on how many input samples are needed or how many output samples will be produced. Also the position parameters in the request confuse me, because I don't have a big audio buffer with all the audio to be stretched, but small chunks.
So I would like to join the request done by dhng22 of a clarification or an example on how to use the library in those scenarios.
Thanks again for your work!
Hello both,
Thank you for your interest in Bungee.
Because Bungee's input can move forwards, backwards, pause, seek and scrub through the input audio, the API does need to be a bit different to traditional modules that have an input and an output stream of audio. The native API works something like this, per grain:
Caller: I want the next grain to be centred at sample position 10,000 Bungee: sure, please show me audio frames from 7,952 to 12,047. Caller: here's a pointer to the input audio range that you asked for Bungee: ok, grain done, here are the next 512 frames of audio output. These correspond to input audio from 7,952 to 8,463 Caller: ok based up current playback speed and pitch, where should the next grain be centred? Bungee: the next grain should have position 10,512.
This API is based upon how Bungee works and it allows users to achieve the lowest possible latency, minimising data copies. It can work for any speed including zero and negative ones. Any mode of operation can be built upon this by adding input and/or output buffering.
Have you both seen the "push" API in Push.h? It is additional wrapper input buffering code that we created for cases where apps are driven by calls delivering input audio. Sample usage is here: https://github.com/kupix/bungee/blob/0083f748ab2f30ed5969a67602ee66582bd828ae/cmd/main.cpp#L32 please study the loop that follows this code and let me know whether you can drop that onto your code.
Please do share any further questions or suggestions.
@kupix Hi, thanks for the quick explaination. Can you explain what's the pushFrameCount at this line and how can I get it in my context? Thanks
I've managed to get the pushFrameCount, but there's more problem:
I already have the audio data in the readPtr, but there isn't a constructor to directly pass the data in, instead I have to make a double loop to assign it. And there's also a lot of variables marked red that I don't know where to acquire as in the image above. Also all functions in Push::InputBuffer are not documented. So I don't really know what they do. That being said, I still can not produce a corresponding function to Rubberband
Here is my best attempt to make the API work:
There's still the processor.write() to make the loop break but I'm not using cmd Processor
I also find it confusing when trying to integrate the library with my code. There's a lot of functions to just process an audio buffer from local source: preroll, specifyGrain, analyseGrain, synthesisGrain, next. After all of these I also couldn't get it to work
any update?
@kupix Hi, is there any snippet for this issue? I'm impressed by your library and would love to integrate it with my current project! Thanks
The API is designed around the dataflow that the stretcher needs to achieve fully flexible time warping with minimum latency, supporting zero and negative speeds. It's also designed to avoid the need for a callback to get the necessary input data for each grain.
So some usecases will require additional buffering, and that's fine. Push.h provides input buffering. Output buffering should be straightforward to add, if needed.
I suggest looking at the sample main() function first: get that working in a debugger, understand the inputs and outputs then adapt to the dataflow of your own app.
@kupix Kindly asking if you could answer my question? It'd be great if you could have a quick look at the screenshot i posted above
If no progress can be made, this issue should be closed
@dhng22 sorry, I can't help with debugging your code. General point: Processor.write is user code that does two things, it outputs the chunk produced by bungee and it decides when processing is finished. You should replace it with code appropriate to your processing loop.
If no progress can be made, this issue should be closed
Agreed since there doesn't seem to be any problem with the bungee library itself perhaps we should close this. I am wondering whether we could use GitHub discussions for user/community support. If new samples, wrappers or documentation are required, let's get that clearly defined in a new issue.
@kupix I apologize for reopening this. Again, I've been trying to make it work in the past few weeks, yet I couldn't get it to work.
sorry, I can't help with debugging your code
I mean, come on, I'm not asking for detailed debugging or advanced things. I'm just a community member trying to utilize your library at the entry point and the doc itself isn't clear enough for me. I am grateful for your work, and it would be great if I could use it. If it works, I'd love to license my app with a commercial license too.
Again, I'm still trying to perform audio stretch, but the output is still the same:
It'd be great if you @kupix or anyone could help me out. Thanks a lot
@dhng22 So the output audio remains unchanged? Have you check the stretcherRequest speed and pitch parameters? or any abnormal execution inside the synthesiseGrain() loops?
@toaster217 Thanks for your response. I've set the stretcherRequest speed and pitch before the above code happens. And I did notice that the code inside the loops
inputBuffer.inputFrameCountRequired() <= 0
only run like 4-5 times and then there are no more log comming from that part anymore. Wondering if I'm missing something
@dhng22 The code seems fine to me. I suggest opening a new issue and seeing if @kupix could help you out, since pretty much no one here can
Hi, thanks for the awesome library. I'm a little bit struggling to make it work in code. I've looked at cmd/main.cpp but still pretty hard for me to understand. I'm currently using Rubberband to perform pitch-shift on audio buffer, and this is how i make it work in code:
It's pretty simple and straightfoward. Can you provide more detail comments on the functions from Stretcher? It would be nice if you could also provide a simple code corresponding to the working example of Rubberband I've posted above. Thank you