Control multiple versions of the same sound


I am building an audiogame based on Allegro, but I encounter some problems during the process. As I've said before, I'm an absolute beginner, so excuse me for asking this stupid things. :)

I'd like to have multiple versions of the same sound playing, which I can control seperately. The last is possible with Voice Control, but I need to specify a voice so I can adjust it.
Now I'm trying to make a function like this:
place_objet(x_position, y_position, ID);
The ID will name the voice where the sound is playing, but these are automatically asigned. Thus I can't do things like:
asigned. Thus I can't do things like:
place_objet(20, 30, 1); // Object #1
place_objet(50, 90, 2); // Object #2

So, I have to obtain the voice where the sound is playing with allocate_voice, but at the same time I already need this voicenumber, because it should be my ID.

I know this is not very common, but does someone get my point and maybe can provide some help?

Tobias Dammers

First allocate, then adjust. Store the ID in a member var of your object.
The hard part is not this, but dealing with "too many" objects (that is, when you can't allocate enough voices for all your objects).


I just don't know how to do this in another way.

My problem is that I want to make multiple objects at the same time. And if Allegro gives me a voicenumber, and I store that, and then build up a new object (from the same function) it'll override the original one, isn't it?

Tobias Dammers

You keep the same object, and initialize its voice to "undefined" (0 or -1, don't remember, please read the manual). As soon as you allocate a voice, store its index in the object, and after that, use the stored id to access the sound. When you free the sound, set the stored id back to undefined.


So, I have to obtain the voice where the sound is playing with allocate_voice

Or just use the value returned by play_sample().


So you think it's possible to place objets (stones, cars, whatever) with just one function which will manage all the objects simultaniously?

Dustin Dettmer

Better to allow only 1 instance of a sound to play at once.

The more sounds you play the lower the sound quality. If you get too many playing at once it will sound awful and you lose the point of playing sounds in the first place.

Also remember the old saying KISS, Keep It Simple, Stupid.


Alright, but this is going to be an audiogame... :)

Tomorrow I'll try classes and arrays (good practice!).


You don't select the voices number yourself... If you have any sound program running (Winamp), you could have ANY voices busy and unavailable to Allegro - and it probably won't be as simple as voices 0 and 1.
You'll have to uniquely identify your objects, without relying on the voices numbers.
Something like:

1typedef struct
3 int x_position;
4 int y_position;
5 int voice; // allegro voice
8// SOUND_OBJECT allocator and "constructor"
9SOUND_OBJECT *place_object(int _x, int _y, const SAMPLE *spl)
12 ob = malloc(sizeof(SOUND_OBJECT));
14 ob->x_position = _x;
15 ob->y_position = _y;
16 // allegro gives the voice number
17 ob->voice = allocate_voice(spl);
18 // should check for -1 here (no more voices available)
20 return ob;
23(...main program...)
25engine_noise = load_sample("engine.wav");
27SOUND_OBJECT * sounds[8]; // games uses 8 voices, for example
29sounds[0] = place_object(10, 30, engine_noise);
30// etc.

edit: argh, I just saw the word "classes" in your post.. I should have made it C++ instead of C++-like.


I have made a class where a function runs that places objects. Now I'm able to do this:

object ob1;
ob1.x_position = 30;
ob1.y_position = 20;; // Do it!

I can play one object, and I think I can also make it adjust the sample. And this afternoon I'll try to make it working for multiple objects (won't be too hard using classes I hope).

Richard Phipps

There is a design flaw (IMHO) in Allegro's sound handling which makes it difficult to play a sample using a specific voice. You have to let Allegro find a voice and then manipulate that voice channel.

Tobias Dammers

This is not a design flaw, it's how the api works. It is similar to when you allocate a pointer or a handle: you will get whatever free space the memory allocation algorithm finds for you. You can't say, for example:

int* p = new int at 0x00AA1234;

Allegro's voices work exactly the same, only that the address space is "a little" smaller.


By the way, am I right that adjust_sample(*spl); adjusts the first one that it finds. So, if you make two samples, the first one is always adjusted, even if you call adjust_sample() multiple times?

Thomas Fjellstrom

Allegro's voices work exactly the same, only that the address space is "a little" smaller.

If you want to keep a voice number, you can use reallocate_voice. Just make sure it isn't set to deallocate automatically. Then you also have to worry about running out of voices.


the first one is always adjusted, even if you call adjust_sample() multiple times?

It seems it might only modify the last one you played. Which seems to jive with the api, play_sample makes a voice that auto deallocates when finished, so you can't rely on the voice id existing and being usefull at all for any length of time.

For more complex sound using games, you MUST use the voice functions and ignore the play_sample function all together. play_sample is a fire and forget type interface.

edit: Actually play_sample returns the voice number for the voice it allocated, so you can use the voice functions with that if you wish. But its all the same really.


If I play one sound with my own created class all is fine, but when I try to play two sounds, they're played at the far left side of the stereofield.
And now I wonder why that's happening. I thought that it maybe had something to do with the play_sample-function. But after reading this I guess that it is a problem in my class or something.

Thomas Fjellstrom

Maybe you're passing the pan value in wrong?


The pan variable is currently declared in the function itself (which is declared in the class), but that seems to trouble.

I know that this stuff isn't really common, although I hope to find a good solution quite soon. :)

Thomas Fjellstrom

Post the play_sample code you have. as well as some of the code arround it, so we can see how you're using it.


I don't know if someone is able to understand it, but here we go...

The class:

class rock {
       int rock_x;
       int rock_y;
       void adjust_rock(void);

1rock::rock() {
2 play_sample(rocky, 255, 128, 1000, TRUE);
4rock::~rock() {
5 stop_sample(rocky);
7void rock::adjust_rock(void) {
9 /* Declare local variables */
10 int left = rock_x - 128;
11 int right = rock_x + 128;
12 int back = rock_y - 128;
13 int front = rock_y + 128;
14 int pan;
15 int vol;
17 /* Calculate variables */
18 pan = 128 - (x - rock_x);
20 /* Adjust the sound */
21 adjust_sample(rocky, 255, pan, 1000, TRUE);
24And in the main-function:
25 rock rock1;
26 rock1.rock_x = 750;
27 rock1.rock_y = 0;
28while (!key[KEY_ESC]) {
29 rock1.adjust_rock();

  • The variables that are not declared in this piece of code are declared globally.

  • I duplicate the code from the main-function to obtain a new sound (all in one loop).

Thomas Fjellstrom

Please use the

<code>code here</code>

tags :)

The only thing I can think at this point is the pan variable is getting to large or too small. try printf'ing or cout'ing the value of it when you modify it.


One last question: Is it true that Allegro adjusts the volume when you pan a sound, and if so, can I prevent Allegro from doing that?


Do you really realize what pan mean ?


I meant: are there differences between the way adjust_sample and voice_set_pan works?

Some programs/mixers/whatever boost the volume of the left channel when you pan to the left. But others just cut down the volume of the right side (which is better in my opinion).

Edit: I found it! I needed set_volume_per_voice().

Thread #590131. Printed from