Skip to content
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

User stories/usecases/experiences (please add!) #626

Open
dvdsk opened this issue Oct 3, 2024 · 11 comments
Open

User stories/usecases/experiences (please add!) #626

dvdsk opened this issue Oct 3, 2024 · 11 comments

Comments

@dvdsk
Copy link
Collaborator

dvdsk commented Oct 3, 2024

A collection of user stories/usecases & experiences to be used to inform (breaking) api changes.

Please add your own!

@dvdsk dvdsk pinned this issue Oct 3, 2024
@dvdsk dvdsk changed the title User stories User stories (please add!) Oct 3, 2024
@dvdsk dvdsk changed the title User stories (please add!) User stories/applications (please add!) Oct 4, 2024
@dvdsk dvdsk changed the title User stories/applications (please add!) User stories/usecases/experiences (please add!) Oct 4, 2024
@ugochukwu-850
Copy link
Contributor

@dvdsk , should we add it here .

@dvdsk
Copy link
Collaborator Author

dvdsk commented Oct 4, 2024

please do, we can always move it to its own issue if we have questions. And thank you very much!

@dvdsk
Copy link
Collaborator Author

dvdsk commented Oct 19, 2024

Something that seems very hard/impossible with rodio now:

A user adds two songs to a queue some time after eachother. Then they enable cross-fade while the first song is almost at the end but just before adding the second song. Crossfade then works and the two songs fade into each-other.

The music plays without any stuttering while crossfade is toggled on and off.

I am trying to write an example on how to do this using the current API, maybe I am wrong and it is relatively doable. In that case an example would help out.

@bluenote10
Copy link

I'm simply adding a few use cases I had in the past -- without re-checking if they would currently be possible already.

Sample perfect scheduling

Think of a metronome app that needs to schedule its click sound dynamically (the user can control bpm e.g. via a slider), but with utmost temporal precision (you don't want any fluctuation in a metronome). This requires a to have sample/frame perfect scheduling, i.e., one would need to express start playing this sound at sample index i=xxx.

Sample perfect looping

Sometimes I had to loop sounds also without any gap in the audio output (note that waiting for the sound to finish, and re-schedule it again introduces a gap). This would require to set up a loop information that specifies same (loop_sample_index_from, loop_sample_index_upto) so that the playback can implicitly wrapped-around once the "upto" sample is reached. Ideally the playback interface would expose e.g. a loop_counter to allow users to query once a loop-wrap occurred. The most obvious use case for that are "infinite" background sounds that are constructed in a way that they loop around seamlessly, and simply setting the loop specification to (0, last_sample) would repeat the entire sound indefinitely.

Low-latency scheduling

I was once trying to implement a kind of drum synthesizer in rodio, where certain key-presses triggered certain sounds. However I noticed that the input latency was way too large for musical purposes. I would assume that mainly comes down to the large default buffer size, and #512 should improve that.

@dvdsk
Copy link
Collaborator Author

dvdsk commented Oct 21, 2024

I'm simply adding a few use cases I had in the past

Very helpful thank you!

@nednoodlehead
Copy link

My primary use case:

Rust-based music player (iced gui).

I got pretty much everything I need out of rodio, without too much hassle either. (All inside of this function).

The only thing that I am waiting on (or perhaps, I do not know how to implement. And frankly, haven't tried too much) is crossfade between songs. I do see the fade in / fade out stuff. But that applies more to a setup where you take source A, and source B, then add them into the sink or whatever, then apply it. I add my sources more 'dynamically'. Where once the playing song ends a new one is appended. So there is no point where I can apply it.

I had an idea for a potential workaround, but I have literally 0 clue how this library works under the hood (and not too much experience with this type of programming, so I don't think I could help too much). But be able to somehow change when sink.is_empty() returns true, and for example, if you choose to have a crossfade of 5 seconds, the sink would return true 5 seconds before it actually ends (and it is fading out during this time). Idk if this would create bugs or not, or if this is possible, but it is my first thought for making my idea work with my use case.

Also, weird bug, when music is playing, and I drag my scrubbing bar, the timer got reset to 0 nano seconds for a split second my comment here. Dunno if it is related at all.

@dvdsk
Copy link
Collaborator Author

dvdsk commented Oct 21, 2024

Thanks for all the feedback!

I add my sources more 'dynamically'. Where once the playing song ends a new one is appended. So there is no point where I can apply it.

This is an issue I ran into myself too, good to hear others have trouble with it too. We should make this easy/doable and add a full example.

@tramhao
Copy link

tramhao commented Nov 8, 2024

I used rodio for music playback in my project termusic: https://github.com/tramhao/termusic .
Later on, when more features needed, but rodio is not merging the PRs. I have to use the code from Rodio and merge the necessary code myself.

@dvdsk
Copy link
Collaborator Author

dvdsk commented Nov 8, 2024

I used rodio for music playback in my project termusic: https://github.com/tramhao/termusic . Later on, when more features needed, but rodio is not merging the PRs. I have to use the code from Rodio and merge the necessary code myself.

Could you specify which features you specifically need for your app?

@dvdsk
Copy link
Collaborator Author

dvdsk commented Nov 11, 2024

From #636 by callum-jones19

Hi there!

I just had a brief issue dealing with the following situation:

You create a new sink.
You open two sources from files.
Both sources are appended to the sink
During playback of source 1, you decide that you want to remove source 2, and append a new source in its place.

However, I want to do this without interrupting the flow of playback. This is for a music player, so the possibility of the next upcoming song changing (say, because of a queue change) without interrupting the current playback (stutters, moment of silence, etc) is quite important. I would also like to keep the gapless playback functionality.

Right now, the only solution I could think of is having a secondary sink which is switched out, but this seems a bit cumbersome and likely to cause one of the issues I mentioned above. The way my player works right now is there is a Vec of song file paths (my 'lightweight' queue). When you add a song to this file path queue, it checks to see if the sink contains < 4 song sources in it. If it does, then it opens the file path into an actual source, and adds it to the sink. An EmptyCallback that sits after this then runs whenever the song source ends, and opens the next song path in the file path vec into a Decoder, which is then appended to the sink.

I do this so that I can have a very large queue that is easy to control (plus has song struct info in it) with minimal open file pointers, etc, but then the sink is constantly kept at 2 songs ready to go (unless there is only 1 left to play) so gapless playback works. This works well, but like I said, if I want to change the next song in the queue during playback of the first source, I am not sure how to remove the second source from the sink and append a new one in its place.

Thanks for all the hard work on Rodio - it's been incredibly helpful, and I've learnt a lot working with the library. Hopefully when I understand it a bit more fully I can contribute back to it too :)

@IRSMsoso
Copy link

IRSMsoso commented Nov 12, 2024

Some of these are pretty specific and my fall outside the scope of this project/may be implemented I just haven't found them yet, buuut...

I would love easier ways to manage channels. Including:

  • Ways of taking certain channels of a source (for example, taking the first channel of a wave file and making it mono)
  • Customizing the way that channels from a source are mixed up and down to different numbers of channels (for example a stereo wave file mixing up to any number of device channels).
  • Ways for sources to be aware of the channel situation of the output (or maybe the next channel configuration in the chain?) (for example, a source that always has the same number of channels as the device output.
    • This is useful if, for example, you wanted to implement a source that does the sound design trick of delaying each channel of a mono non-transient audio recording and pumping that out to each and every speaker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants