-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a buffered
signal to AudioEffectCapture
#2650
Comments
buffered
signal to AudioEffectCapture
Hi, (In regards to your comment about multiple consumers, note that it is not recommended to have multiple consumers from a single AudioEffectCapture. It is not be designed for this, so it could lead to reading corrupt data. RingBuffer implements a single-consumer, single-producer lock-free ring buffer. This is a widely used standard data structure but it comes with this limitation.) Regarding your questions about sharing buffers, no they are not shared: buffers can be assumed to be allocated on each use and deallocated when you return from the function or remove your reference to them. Internally, buffers are pooled and reused as needed, so this is quite efficient and not something you should be concerning yourself with or trying to optimize. Let's ignore your buffer concerns for the rest of this response as they are not relevant. So as far as the premise of your question, I think you have identified a problem with the way AudioEffectCapture is often used, polling from the main thread, and you are hinting at a solution which mimics modern audio APIs insofar as a callback occurs at the instant data is generated or requested. So at first glance, it seems good. There are three main issues here:
Does posting a Semaphore count as a system call and/or locking? I don't actually know! is it Operating System specific? Some OS Scheduler algorithms may halt execution of the current thread and transfer it to the thread that was awoken by the system call (e.g. if you post() a semaphore, the CPU will context switch to the user thread and wake it up at the wait() call, leaving the audio server asleep until the CPU has available time. This would be a problem. I think it might be safe to do the above semaphore operation once the audio server has finished its work for a given tick and is about to go to sleep. So here's my counter-proposal (whether this is possible depends on the locking mechanics of semaphores):
We should also implement the same API for use in AudioStreamGenerator. |
Wow. What a wonderful counter-suggestion, and a really great read all-in-all. The Semaphore idea sounds like a good hybrid solution. |
I probably won't get to working on this for a long time - if you're interested in real-time audio and want to prototype something with threading and a Semaphore, that would help to validate this approach. |
Would it work if I did the prototype in GDScript? I am not familiar with C++ in Godot (though want to get there eventually.) |
My personal opinion is it's good to prototype in GDScript and use C++ only for the critical optimizations. However... there is one small C++ change that would be needed: part of the proposal involves modifying the AudioServer to post a semaphore. That small part would need to be done in pure C++ because GDScript cannot run on the audio bus thread. (especially due to the requirement of not locking) |
For users here who are curious and interested to know how that is done => read this. |
Was suggested on Discord that I contact @lyuma (by @Calinou)
Describe the project you are working on
Markdown To Story Script Creation with Script Line Recording
Describe the problem or limitation you are having in your project
Not a "problem" per se, but an inefficiency...
Why do I poll the AudioEffectCapture?
If there are multiple consumers, should they each be polling?
The documentation is a bit unclear on ring buffer management...
Am I consuming buffers when I call get_buffer?
Do I share this with others, or hoard it all to myself?
Why do I have to do all this?!?!?
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Add a signal buffered(buffer) # where buffer is PoolVector2Array
Then everyone who wishes to consume the next buffer will be signaled, whether for recording to a wav file or broadcasting over the network or transcoding into an image or...whatever.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
as compared to
If this enhancement will not be used often, can it be worked around with a few lines of script?
Sure. Everyone can poll all the time...whee!
And create multiple AudioEffectCapture effects if you want multiple users/consumers...
Is there a reason why this should be core and not an add-on in the asset library?
Convenience, efficiency, removal of redundancy.
But sure, I can make an addon that becomes a Singleton that does this...totally doable.
The text was updated successfully, but these errors were encountered: