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

docs: How to play same short sound multiple time (concurrent) with different pitch? #155

Open
1 task
dvmatyun opened this issue Nov 18, 2024 · 7 comments
Open
1 task
Labels
documentation Improvements or additions to documentation

Comments

@dvmatyun
Copy link

Description

In gamedev some short sound effects (hit sound for example) need to be played in parallel with different pitch (to not sound exactly the same). What is correct approach to do this in Flutter Soloud?

Requirements

  • Make code example that shows how to play mutiple sounds in parallel with different pitch
@dvmatyun dvmatyun added the documentation Improvements or additions to documentation label Nov 18, 2024
@alnitak
Copy link
Owner

alnitak commented Dec 2, 2024

Hi @dvmatyun, sorry for the late reply!

A filter can be applied only once to a sound, so the best way I can see is to duplicate the audio file and load them into separate AudioSources, apply the filter after loading them, and then play. This is because is not possible to to have multiple AudioSources pointing to the same audio file.

You can do something like this:

/// Load all the sounds
sound1 = await soLoud.loadAsset('assets/audio/tic-1.wav');
sound2 = await soLoud.loadAsset('assets/audio/tic-2.wav');
sound1!.filters.pitchShiftFilter.activate();
sound2!.filters.pitchShiftFilter.activate();

then call a method like this and pass the AudioSource and the shift value:

Future<void> playWithPitchShift(AudioSource source, double value) async {
  source.filters.pitchShiftFilter.shift(soundHandle: handle).value = value;
  final handle = await soLoud.play(source);
}

@dvmatyun
Copy link
Author

dvmatyun commented Dec 3, 2024

@alnitak thanks you for the reply. I guess I can load file into memory (by reading it from assets) and create 2 Soloud instances with same in-memory file (list of bytes I guess?) ? Or that is not possible / won't work?
Anyway, thank you for great example!

@alnitak
Copy link
Owner

alnitak commented Dec 3, 2024

Nope, you can't create more instances of SoLoud. It is a singleton class because of the nature of the audio hardware.

My best solution is to duplicate the audio files to apply different filters to them. I know this could be a problem if the files are taking up much memory, but for now it is the only solution I think.

I'd leave this open, maybe in the near future I will think of a solution! Maybe in something like force to load an already loaded sound into a new AudioSource parameter somewhere.

@dvmatyun
Copy link
Author

dvmatyun commented Dec 3, 2024

@alnitak to be honest this is not what I was meaning. So I was suggesting following:

  1. use one Soloud instance. I didn't mean to create another one
  2. Read file into memory. Make a copy of that file in-memory (so copy bytes)
  3. Pass to soloud the orginal file and the copy of the file (I believe soloud can take bytes instead of file path?)

Not sure if this will work, that is just the first thought that came to me.

PS I just know that in "Unreal Engine" for example you are using single file and can apply different pitch to it each call - to make "attack" sound for example to sound a little bit different.

@alnitak
Copy link
Owner

alnitak commented Dec 3, 2024

Got it! Yes it is possible to use loadMem for this purpose:

/// Load a file into a `Uint8List`
Uint8List bytes = /* use `File` or `rootBundle` to acquire bytes */;

AudioSource sound1 = await soloud.loadMem(
  'sound1',  // this must be a unique string of your own that identifies this new sound
  bytes,
);

AudioSource sound2 = await soloud.loadMem(
  'sound2',
  bytes,
);
// and so on

Doing so you will have the same sound in both sound1 and sound2 and you will be able to apply a different pitch shift.

I'll leave this open because I think there could be a better way to manage this kind of thing, but if you have more thoughts please let me know.

@dvmatyun
Copy link
Author

dvmatyun commented Dec 3, 2024

@alnitak Nope, just want to say it would be cool (if it's possible) to apply pitch to sound without any kind of manipulations, something like:

final mySound = await soloud.load('path-to-file.wav'); // load file
mySound.play(filters: PitchFilter(pitch: 0.1)).ignore(); // play same sound simultaniously with different pitches
mySound.play(filters: PitchFilter(pitch: 0.2)).ignore();

But I guess there might be some platform limitations for that. Anyway, this is by far the best library to play sounds in flutter I have found. Others just either throw errors, or play sound with huge delay or have other kind of problems. This issue is not a big problem for me, so thank you for your help!

@alnitak
Copy link
Owner

alnitak commented Dec 3, 2024

Thanks for your kind words, appreciate it!

But I guess there might be some platform limitations for that.

You are correct, this plugin is heavily based on the SoLoud c++ lib, but can be improved with the help of people like you!

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

No branches or pull requests

2 participants