Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] Repeating audio samples

This thread is locked; no one can reply to it. rss feed Print
[A5] Repeating audio samples
Neil Roy
Member #2,229
April 2002
avatar

I finally got around to understanding Allegro's audio system at least a little bit. I can get audio to play alright at least with this.

The problem now is that, in my pacman like game, you can eat a lot of pills rapidly, and each time you do, it plays a sample. Not a problem normally, but if you speed along too fast, it will skip some sounds. My understanding is that an instance of that sound is already playing so it doesn't play it again until that one is finished.

I am thinking that I am still doing something wrong here, even though it works to a limited degree. I was up until almost 6am this morning working on this and I really would like to understand how this works, if for nothing else than so I can get a good understanding for future projects. This current one, while not the best game in history, is basically my test bed for learning about Allegro 5 as I go. And it's been nice so far, been really loving Allegro 5.

Anyhow, here's my code I use for my sound (all in C, I use the C 2011 standard, not that I have anything specific to that in my code, but just so you know)..

dp2_sound.h

#SelectExpand
1#ifndef _dp2_sound_h_ 2#define _dp2_sound_h_ 3 4#include <stdio.h> 5#include <allegro5/allegro.h> 6#include <allegro5/allegro_audio.h> 7 8typedef struct SFX { 9 ALLEGRO_SAMPLE *samp; 10 ALLEGRO_SAMPLE_INSTANCE *inst; 11} SFX; 12 13bool init_sound(int samples); 14bool load_sound(SFX *sfx, char const *file); 15void play_sound(SFX *sfx, float volume, float pan, float speed, ALLEGRO_PLAYMODE playmode); 16void destroy_sound(SFX *sfx); 17void shutdown_sound(void); 18 19#endif

dp2_sound.c

#SelectExpand
1#include "dp2_sound.h" 2 3 4ALLEGRO_VOICE *voice = NULL; 5ALLEGRO_MIXER *mixer = NULL; 6 7bool init_sound(int samples) 8{ 9 if(!al_install_audio()) { 10 printf("al_install_audio() failed.\n"); 11 return false; 12 } 13 14 voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2); 15 if(voice == NULL) { 16 printf("Error creating voice\n"); 17 return false; 18 } 19 20 mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2); 21 if(mixer == NULL) { 22 printf("Error creating mixer.\n"); 23 return false; 24 } 25 26 if(!al_attach_mixer_to_voice(mixer, voice)){ 27 printf("Error attaching mixer to voice.\n"); 28 return false; 29 } 30 31 if(!al_reserve_samples(samples)) { 32 printf("Error reserving samples.\n"); 33 return false; 34 } 35 36 return true; 37} 38 39 40bool load_sound(SFX *sfx, char const *file) 41{ 42 sfx->samp = al_load_sample(file); 43 if(!sfx->samp) return false; 44 45 sfx->inst = al_create_sample_instance(sfx->samp); 46 if(!sfx->inst) return false; 47 48 if(!al_attach_sample_instance_to_mixer(sfx->inst, mixer)) return false; 49 50 return true; 51} 52 53 54void play_sound(SFX *sfx, float volume, float pan, float speed, ALLEGRO_PLAYMODE playmode) 55{ 56 al_set_sample_instance_gain(sfx->inst, volume); 57 al_set_sample_instance_pan(sfx->inst, pan); 58 al_set_sample_instance_speed(sfx->inst, speed); 59 al_set_sample_instance_playmode(sfx->inst, playmode); 60 al_play_sample_instance(sfx->inst); 61} 62 63 64void destroy_sound(SFX *sfx) 65{ 66 if(sfx->inst) al_detach_sample_instance(sfx->inst); 67 68 if(sfx->inst) { 69 al_destroy_sample_instance(sfx->inst); 70 sfx->inst = NULL; 71 } 72 73 if(sfx->samp) { 74 al_destroy_sample(sfx->samp); 75 sfx->samp = NULL; 76 } 77} 78 79void shutdown_sound(void) { 80 if(mixer) al_destroy_mixer(mixer); 81 if(voice) al_destroy_voice(voice); 82 if(al_is_audio_installed()) al_uninstall_audio(); 83}

The functions are fairly self explanatory. I use init_sound() to initialize everything, load_sound() to load in sound samples and set them up, play_sound() plays the sounds with similar perimeters as the al_play_sample() (except the last one). destroy_sound() frees up allocated memory for each sound sample and finally shutdown_sound() is called before the game exits.

I also have a problem when I go to use al_set_sample_instance_speed() on a sample that is currently playing, the speed of the sample isn't changed at all, which was part of the reason why I set up all this in the first place.

Any help would be appreciated. Sorry if these questions seem stupid, but I did spend a LOT of time last night and today and I am missing something, just what I don't know. :-/

Matthew Leverton
Supreme Loser
January 1999
avatar

There are two levels of sample playing functions. You can mix and match them, but it's important to understand the differences.

  1. Higher Level: al_reserve_samples(int n) is paired with al_play_sample(). n how many times you can simultaneously call that latter function, regardless if it's the same underlying raw data or not.

    It creates its own voice/mixer combination if you don't tell it about a default one via al_set_default_mixer(). So in your example, you should set the default mixer before calling the reserve sample function.


  2. Lower Level: create voice / create mixer / attach x to y / al_create_sample_instance() / al_play_sample_instance() If you want to play the same sample N simultaneous times, then you need to create 1 ALLEGRO_SAMPLE and n ALLEGRO_SAMPLE_INSTANCE variables.

The two structures:

So in your case, you may want to move toward this (with the lower level API):

typedef struct SFX {
   ALLEGRO_SAMPLE *samp;
   ALLEGRO_SAMPLE_INSTANCE **inst;
   int max_simultaneous_count;
} SFX;

When loading the sample, set max_simultaneous_count and create an array of that many ALLEGRO_SAMPLE_INSTANCE. Then when playing your SFX, loop through that array and play the sample instance if it is not currently playing.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Neil Roy
Member #2,229
April 2002
avatar

Okay, that clarifies things. I still can't adjust the sound's speed while it is playing.

Anyhow, I removed this code from my game for now and went back to using al_play_sample() (thank God for backups). All this headache just isn't worth it for one small sound effect.

I'll have to figure t his out another day, I may take a peek at the al_play_sample() code sometime and see what it does if I can understand it, but if I spend much more time trying to figure this out I will never get this game done, and I just want to finish this thing sometime this century. ;)

It does look like, if I ever plan to use this that I will have to write lots of code to track multiple instances in some sort of array, and I somehow track when they're done playing yada yada yada... I am starting to miss Allegro 4, at least for audio anyhow.

I love Allegro 5, but not the audio system, seems overly complicated compared to Allegro 4.

Edit: Thanks for the additional ideas. I will still work on this on the side, in a separate project so I can continue to try and get something working that I can use in all my future projects. It's just this particular project has dragged on too long now and I tire of working on it (but refuse to stop until it is done! ;) ).

Edit2:

When loading the sample, set max_simultaneous_count and create an array of that many ALLEGRO_SAMPLE_INSTANCE. Then when playing your SFX, loop through that array and play the sample instance if it is not currently playing.

Good idea, but I am wondering. Do you have to check if that instance of a sample is still playing? When it ends playing, do you destroy that instance? I'm just uncertain about the management of all of this.

Go to: