-
-
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
Adding a new AudioStream variant to play audio from an actual stream (continously adding data) #11782
Comments
I think you might want to look into AudioStreamGenerator, you can add samples to the buffer continuously from the TCP connection |
Do you have any documentation or pointers on how I could convert raw MP3 data to a suitable frame for the |
No. I assume you'll have to decompress it yourself, or use an external library? I had just assumed you were transmitting the raw uncompressed samples or something easier to decode |
I think there is a miscommunication here, what I receive is raw MP3, I am not the one sending the data, it's from an internet radio (could be any radio). |
From what I've understood of this conversation, I think it'd make more sense to add or expose methods for loading raw MP3 data and converting it into a format that AudioStreamGenerator can use. This keeps the simplicity of a single AudioStreamGenerator class/resource type, instead of making multiple for different data types. The delay you described with the |
First, I see what you mean about extending the functionalities of the AudioStreamGenerator, I did not realize that my proposition was this close to what it does. I'll start looking into that. Secondly, I feel like you missread the minimal working example I provided: downloading the next chunk of MP3 data is done in advance of waiting for # waiting for enough data to be ready
stream_peer.poll()
var available := stream_peer.get_available_bytes()
if available < 16000:
await get_tree().process_frame
continue
# downloading the data
var data: PackedByteArray = stream_peer.get_data(available)[1]
# waiting for the current chunk to finish playing
if playing: await finished
# replace stream data and play new data
stream.set_data(data)
play() I tried to place the I can also confirm that the |
Describe the project you are working on
An internet radio player receiving audio data through a StreamPeerTCP.
Describe the problem or limitation you are having in your project
I tried to play continous audio in multiple ways with all the options Godot's
AudioStream
types offer but I always end up with an issue: there is always a delay between the instant the stream in theAudioStreamPlayer
ends and the instant when thefinished
signal is emitted, creating very grating stutters between chunks of streamed audio data, especially when the game's window is not focused. I suspect this is due to how the engine's event loop works, so I wouldn't be surprised if this did not happen for people with very good PC specs.For completeness, I tried to use an
AudioStreamPlaylist
but the same issue emerges because itsset_list_stream
stops the audio for some reason, so callingplay
is still required and causes stuttering. Also I'm pretty sure it isn't a good idea to infinitely add streams to a playlist.Some of the methods I tried with limited success are listed in this reddit post, I can reproduce minimal working examples for each case if necessary.
Here is a minimal working example I put together of the simplest way to see this happening:
(the radio link used in this example is the one I'm trying to connect to, please excuse the choice)
I know that the stuttering does not come from the data because concatenating multiple chunks of data from
stream_peer.get_data(available)[1]
and then playing the resultingPackedByteArray
does not create any stutter. Also, other radio players (firefox, Gnome's Rythmbox) are able to play the radio with no issue.I'd also like to add that this feature would be required to play .m3u files (Audio Playlist) because they can contain links to internet audio streams.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Since it is not possible to play a continous stream with the existing
AudioStream
types, I propose the introduction of a new type: proposed name isAudioStreamMP3Stream
. This new type would have aqueue_data
method to add a chunk of MP3 data to be played, and it would internally chain the data together, eventually discarding chunks that have finished playing.Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I am making this proposal before starting the implementation because it was advised to do so in the Godot documentation, I have some ideas about how to build what I am proposing, but I did not look into the source code yet, so it is based on my C++ knowledge, not on the Godot codebase.
The
AudioStreamMP3Stream
class I am planning to create has these methods:queue_data(data: PackedByteArray) -> void
adds a chunk of data to an internal queue to be played.get_elapsed_time() -> float
returns the total length of audio played since play() was called in milliseconds.As well as the following signal:
data_discarded(data: PackedByteArray)
emited when the internal data chunk just finished playing and is discarded (freed) to play the next one in the queue.From what I understand, it will also require some other internal features to handle all the methods of an
AudioStreamPlayer
likeplay
,stop
andstream_paused
.As mentioned earlier, I did not look into how an
AudioStreamMP3
works internally yet, but I am confident that it is possible to continously play raw MP3 data by using a queue structure.If this enhancement will not be used often, can it be worked around with a few lines of script?
Not to my knowledge. If it can, I would be glad to make an addon with the workaround instead of a new class.
Is there a reason why this should be core and not an add-on in the asset library?
From my understanding, what's in the asset library is built with what exists in Godot, but what I am proposing is not possible with what is already available. Feel free to correct me if this is wrong.
The text was updated successfully, but these errors were encountered: