SFML community forums
Help => Audio => Topic started by: HornetMaX on February 16, 2015, 09:05:50 pm
-
Hi all,
I'm new to SFML hence my question could be a bit noobish.
I'd like to play a given sound (raw .wav) with a specified "volume envelope", meaning that each individual sample in the .wav must be played with a specified volume.
Is thee a way to achieve this with SFML ?
MaX.
-
Nop.
I'm curious: what do you need this for?
-
I'm curious: what do you need this for?
It's a very specific need. I have a .wav file I show graphically on a graph and I'd like to allow the user to select a part of it and loop-play the selected part only, in a particular manner.
First, a volume envelope is applied to the selection, typically as (numbers are just to give an idea):
- between 0% and 25% of the selection, the volume goes linearly form 0 to 1
- between 25% and 75% of the selection, the volume stays at 1
- between 75% and 100% of the selection, the volume goes linearly form 1 to 0
Also, when on the "fade out" section (volume going from 1 to 0), I'll be "mixing" that with the "fade in" section (volume going from 0 to 1).
Essentially what this is trying to achieve is to allow the user to select a section of the .wav and loop it smoothly.
I guess that one way to do that would be to handle myself the "slicing" and "volume envelope" and then use loadFromSamples.
MaX.
-
I'd like to play a given sound (raw .wav) with a specified "volume envelope", meaning that each individual sample in the .wav must be played with a specified volume.
Couldn't you simply pre-process the file to ensure this - make sure it's within the envelope? Why would you need SFML's help to do this at runtime?
Or maybe I'm just not understanding your question..
-
Couldn't you simply pre-process the file to ensure this - make sure it's within the envelope? Why would you need SFML's help to do this at runtime?
Or maybe I'm just not understanding your question..
Yeah, pre-processing is what I said above (handle myself the "slicing" and "volume envelope" and then use loadFromSamples).
I need SFML to play the samples and to change the pitch on the fly.
MaX.
-
Have you tried the naive approach, i.e. adjusting the volume with setVolume while the sound is playing?
-
Have you tried the naive approach, i.e. adjusting the volume with setVolume while the sound is playing?
That wouldn't work I think. How d I do I know exactly where in the wav file we currently are ?
But looking more carefully at the tutorial for SoundStream (http://www.sfml-dev.org/tutorials/2.2/audio-streams.php (http://www.sfml-dev.org/tutorials/2.2/audio-streams.php)) I just realized that I can create a SoundBuffer an do a getSamples() to get a const pointer to the samples. Then I can probably cast away the const and apply my volume envelope to the samples. Dirty, but should work, right ?
To avoid the ugly cast, I could even create a custom SoundStream that takes its samples from a SoundBuffer, apply the volume envelope and return chunks of size equal to the whole .wav size. A bit involved (to simply avoid the cast) but should work too.
MaX.
-
How d I do I know exactly where in the wav file we currently are ?
sound.getPlayingPosition()
Then I can probably cast away the const and apply my volume envelope to the samples. Dirty, but should work, right ?
Nop. The returned samples are just a copy of what's into the internal OpenAL buffer. Changing them will not update the OpenAL buffer. You must copy the samples, do your modifications, and put them back into a sound buffer with the loadFromSamples function. But this is pre-processing, and we have already discussed this option. Also, I have no idea what this has to do with sound streams ;)
-
How d I do I know exactly where in the wav file we currently are ?
sound.getPlayingPosition()
Is it documented (in 2.2) ? I don't find it in the doc. I have a sound.getPlayingOffset() but it returns a Time.
Anyway, I would need to have my function (that sets the volume according to the envelope and the current position) called each time a sample is played. How can I do that ?
Then I can probably cast away the const and apply my volume envelope to the samples. Dirty, but should work, right ?
Nop. The returned samples are just a copy of what's into the internal OpenAL buffer. Changing them will not update the OpenAL buffer. You must copy the samples, do your modifications, and put them back into a sound buffer with the loadFromSamples function. But this is pre-processing, and we have already discussed this option. Also, I have no idea what this has to do with sound streams ;)
Bummer for the copy thing :)
The soundStream could allow me to have my volume envelope applied in a more dynamic fashion, "on the fly": if I pre-process (without sound stream), when the volume envelope changes I have to pre-process again (not sure but depending on the wav size, this may take too long).
On the other hand, a SoundStream could take the raw samples (no envelope) and apply the envelope each time a chunck is requested. If the chunk is small enough, the user will be able to change the envelope while playing.
I'll give it a try (as soon as possible) and let you know.
Thanks a lot for your replies and congrats for SFML: I'm really liking it ! (I use its sound and joystick stuff in some Qt apps).
MaX.
-
I have a sound.getPlayingOffset() but it returns a Time.
Yes, sorry, I meant this function.
Anyway, I would need to have my function (that sets the volume according to the envelope and the current position) called each time a sample is played. How can I do that ?
Do you really need to set it per sample? Who's going to hear the difference, compared to doing it like 60 times per second?
On the other hand, a SoundStream could take the raw samples (no envelope) and apply the envelope each time a chunck is requested. If the chunk is small enough, the user will be able to change the envelope while playing.
Ah, yes, that's indeed a good idea.
-
Anyway, I would need to have my function (that sets the volume according to the envelope and the current position) called each time a sample is played. How can I do that ?
Do you really need to set it per sample? Who's going to hear the difference, compared to doing it like 60 times per second?
I don't know yet if per-sample is needed or if something coarser could work too. Most likely, per-sample is overshoot. However, doing it per "bunch-of-samples" (e.g at 60Hz) will limit how small a grain could be, there's a trade-off to be done somewhere.
Anyway, even if I do it per "bunch-of-samples", I still need to use the SoundStream + chunk approach, but that should be OK.
MaX.