Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Playing a sample with a volume envelope  (Read 4565 times)

0 Members and 1 Guest are viewing this topic.

HornetMaX

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Playing a sample with a volume envelope
« 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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Playing a sample with a volume envelope
« Reply #1 on: February 16, 2015, 11:08:50 pm »
Nop.

I'm curious: what do you need this for?
Laurent Gomila - SFML developer

HornetMaX

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Playing a sample with a volume envelope
« Reply #2 on: February 16, 2015, 11:58:37 pm »
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.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Playing a sample with a volume envelope
« Reply #3 on: February 17, 2015, 12:17:27 am »
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..

HornetMaX

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Playing a sample with a volume envelope
« Reply #4 on: February 17, 2015, 01:30:33 am »
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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Playing a sample with a volume envelope
« Reply #5 on: February 17, 2015, 07:59:15 am »
Have you tried the naive approach, i.e. adjusting the volume with setVolume while the sound is playing?
Laurent Gomila - SFML developer

HornetMaX

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Playing a sample with a volume envelope
« Reply #6 on: February 17, 2015, 09:13:08 am »
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) 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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Playing a sample with a volume envelope
« Reply #7 on: February 17, 2015, 10:23:49 am »
Quote
How d I do I know exactly where in the wav file we currently are ?
sound.getPlayingPosition()

Quote
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 ;)
Laurent Gomila - SFML developer

HornetMaX

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Playing a sample with a volume envelope
« Reply #8 on: February 17, 2015, 10:53:09 am »
Quote
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 ?

Quote
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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Playing a sample with a volume envelope
« Reply #9 on: February 17, 2015, 12:01:22 pm »
Quote
I have a sound.getPlayingOffset() but it returns a Time.
Yes, sorry, I meant this function.

Quote
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?

Quote
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.
Laurent Gomila - SFML developer

HornetMaX

  • Newbie
  • *
  • Posts: 12
    • View Profile
    • Email
Re: Playing a sample with a volume envelope
« Reply #10 on: February 17, 2015, 12:47:01 pm »
Quote
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.