5

I am having a problem finding resources on playing an attack (start of sound) / sustain (looping sound) / decay (ending of sound) sequence with no transition breaks. Are there any good libraries for handling this, or should I roll my own with AVAudioPlayer? Is AudioQueue a better place to look? I used to use SoundEngine.cpp, but that's been long gone for a while. Is CAF still the best format to use for it?

Thanks!

umop
  • 2,122
  • 2
  • 18
  • 22

2 Answers2

3

From your description, it sounds as if you're trying to write a software synthesizer. The only way that you could use AVAudioPlayer for something like this would be to compose the entire duration of a note as a single WAV file and then play the whole thing with AVAudioPlayer.

To create a note sound of arbitrary duration, one that begins playing in response to a user action (like tapping a button) and then continues playing until a second user action (like tapping a "stop" button or lifting the finger off the first button) begins the process of ramping the looped region's volume down to zero (the "release" part), you will need to use AudioQueue (AVAudioPlayer can be used to play audio constructed entirely in memory, but the entire playback has to be constructed before play begins, meaning that you cannot change what is being played in response to user actions [other than to stop playback]).

Here's another question/answer that shows simply how to use AudioQueue. AudioQueue calls a callback method whenever it needs to load up more data to play - you would have to implement all the code that loops and envelope-wraps the original WAV file data.

Community
  • 1
  • 1
MusiGenesis
  • 74,184
  • 40
  • 190
  • 334
  • I don't know about the op, but in my case it's for the background music of a game. I need the attack becouse the music has an intro, then after the intro it should keep looping the sustain. To avoid bigger memory footprint I want to use AVAudioPlayer to stream the music (which would take like 10 MB, and my game already needs too much memory). My current problem is that when I play a sound with AVAudioPlayer it has a huge delay (like 200 ms), even if I already called prepareToPlay before, this leave an undesired gap between the attack and sustain. – fbafelipe Nov 01 '11 at 01:28
  • 1
    @fbafelipe: `AudioQueue` is almost certainly the way you want to go. It's more complicated to use than AVAudioPlayer (not least because the main tutorial includes C++) but also much more powerful and flexible. I've been meaning to get around to learning AQ properly, since it's the iOS version of the waveOut... win32 API that I'm very familiar with. Once you learn how to create audio in memory and play it with a low-level API like AudioQueue, it opens up a world of programming possibilities. It also tends to expose how little the higher-level APIs actually do under the hood. – MusiGenesis Nov 01 '11 at 03:22
  • But can AudioQueue stream the audio? I am currently using OpenAL for the sound effects and the background music, I want to keep OpenAL for the effects but stream the music to save memory. – fbafelipe Nov 01 '11 at 03:40
  • AQ can stream audio, but I think OpenAL can too. I think you can do what you need with OpenAL, but I'm not sure - I'm not very familiar with it. – MusiGenesis Nov 01 '11 at 03:50
  • I can do stream with OpenAL, but I would need to read the buffers and feed OpenAL by my own. With AVAudioPlayer I just open the file and it stream for me. Well, I guess I'll have to implement the streaming with OpenAL. Thanks for the help. – fbafelipe Nov 01 '11 at 03:56
1

creating your own envelope generator is very simple. the tough part will be updating your program to use lower level audio services in order to alter the signal directly.

to do this, you will need:

  • the audio file's samples
  • set up an AudioQueue (that's one approach, but i am going with it because it was mentioned in the OP, and it is relatively high level API for a user provided sample buffer)
  • provide a signal to the queue
  • determine if your program is best in realtime or pre-rendered

Realtime

  • Allows live variations
  • manage your loop points
  • manage your render position
  • be able to determine the amplitude to apply based on the sample position range you are reading

or

Prerendered

  • May require more memory
  • Requires less CPU
  • apply the envelope to your copy of the sample buffer
  • manage your render position

I also assume that you need only slow/simple transitions. If you want some crazy/fast LFO, without aliasing, you will have a lot more work to do. This approach should not produce audible aliasing unless your changes are too abrupt:

Writing a simple envelope generator (EG) is easy; check out Apple's SinSynth for a very basic EG if you need a push in that direction.

justin
  • 104,054
  • 14
  • 179
  • 226