docs: How to play same short sound multiple time (concurrent) with different pitch?
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
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);
}
@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!
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.
@alnitak to be honest this is not what I was meaning. So I was suggesting following:
- use one Soloud instance. I didn't mean to create another one
- Read file into memory. Make a copy of that file in-memory (so copy bytes)
- 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.
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.
@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!
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!