Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » AUDIOSTREAMs not functioning as documented

This thread is locked; no one can reply to it. rss feed Print
AUDIOSTREAMs not functioning as documented
Thomas Harte
Member #33
April 2000
avatar

Per the docs (emphasis added):

Quote:

You must call this function at regular intervals while an audio stream is playing, to provide the next buffer of sample data (the smaller the stream buffer size, the more often it must be called).

...

If it returns NULL, the stream is still playing the previous lot of data, so you don't need to do anything. If it returns a value, that is the location of the next buffer to be played

The documentation clearly implies a system where one section of sound is being played, and one more is queued. It does this by explicitly using the singular — talking about the next buffer — and claiming that the pointer returned points to the next buffer to be played.

So this code:

1#include "allegro.h"
2 
3int main(int argc, char **argv)
4{
5 AUDIOSTREAM *a;
6 
7 allegro_init();
8 install_keyboard();
9 set_gfx_mode(GFX_AUTODETECT, 320, 240, 0, 0);
10 install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL);
11 a = play_audio_stream(1024, 16, FALSE, 44100, 128, 128);
12 while(!key[KEY_ESC])
13 {
14 void *buf;
15 int c = 0;
16 
17 if(buf = get_audio_stream_buffer(a))
18 {
19 do
20 {
21 c++;
22 free_audio_stream_buffer(a);
23 }
24 while(buf = get_audio_stream_buffer(a));
25 clear(screen);
26 textprintf(screen, font, 0, 0, makecol(255, 255, 255), "%d", c);
27 }
28 }
29 return 0;
30}
31END_OF_MAIN()

Should only ever display the number '1'. Otherwise multiple buffers are suddenly available at once, and all but the first one you fill are definitely not, as the documentation promises the next buffer to be played.

However, under Windows it displays '6' and under OS X it displays '2'. See the bottom of this post for full details of my machine/OS/etc.

Therefore, either the documentation is broken or Allegro is. I would suggest that Allegro is, on the basis that setting things up this way substantially breaks the ability for Allegro programs to maintain a small latency between themselves and the audio output, and where latency can't be avoided the remedy should be to require a larger audio stream buffer rather than to have Allegro lie to the programmer and in so doing not follow the documented behaviour.

Comments? Opinions? Am I perhaps wrong?

Boring stuff:
Machine is a 2.16 Ghz Core Duo running OS X v10.4.10. For Windows I use a virtualised copy of Windows 2000 via Parallels 3.x. In both cases I used Allegro 4.2.2 which I understand to be the latest available version.

EDIT: I should add that I've seen the source code of at least one project that assumes that buffers are provided one at a time, an equal amount of time apart, as I believe the documentation implies the will be. I therefore also assume that this is how Allegro used to work and any changes to that will therefore unjustifiably break backwards compatibility if it is agreed that the documentation states that this is their intended method of operation.

Thomas Fjellstrom
Member #476
June 2000
avatar

Depending on the config, you get two or more buffers with a SOUNDSTREAM. You have to tweak the size of the buffer you pass, and the allegro.cfg vars for the driver you're using (the alsa config on unix varies greatly between systems, audio hardware, and if theres a pink elephant near by)

But yes, the buffers should be ready as soon as allegro is done with them.. so you have to get to filling as soon as allegro is done with them. Its tricky. The api isn't too well done, but its all we have for now.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Thomas Harte
Member #33
April 2000
avatar

Quote:

The api isn't too well done, but its all we have for now.

And how do you feel about the API not fitting the documentation, especially that the manual claims "If [get_audio_stream_buffer] returns a value, that is the location of the next buffer to be played" but if you don't happen to guess exactly half of the internal Allegro sound buffer size then that usually simply isn't true?

Thomas Fjellstrom
Member #476
June 2000
avatar

Well, it is the next buffer, and it wont be half. Depending on the size you ask for and the driver is told to use internally, it could be in 16 pieces or more.

What its supposed to do is just return the absolute next buffer thats not been returned yet. Once its returned one, it gets the next if theres one ready (ie: more than two chunks).

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Thomas Harte
Member #33
April 2000
avatar

Quote:

Well, it is the next buffer

In that case, on Windows with the settings I arbitrarily picked there are apparently 6 buffers that are all equally "next to be played".

Quote:

What its supposed to do is just return the absolute next buffer thats not been returned yet. Once its returned one, it gets the next if theres one ready (ie: more than two chunks).

Then you agree that the documentation is incorrect?

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

In that case, on Windows with the settings I arbitrarily picked there are apparently 6 buffers that are all equally "next to be played".

They should all be consecutive, so once you fill one, the next one will be ready immediatly if its not been filled yet, or you took too much time getting to it.

Quote:

Then you agree that the documentation is incorrect?

Not sure to be honest.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Peter Wang
Member #23
April 2000

Quote:

Should only ever display the number '1'. Otherwise multiple buffers are suddenly available at once, and all but the first one you fill are definitely not, as the documentation promises the next buffer to be played.

If you understand you correctly, you expect get_audio_stream_buffer() to return the buffer directly after the one being played right at the moment you make the call, and only that buffer? Well, I guess that is a documentation bug. What it should say is that there is a queue (ring?) of buffers and get_audio_stream_buffer() returns the next buffer in the queue, and the queue length may be greater than one.

Quote:

I therefore also assume that this is how Allegro used to work and any changes to that will therefore unjustifiably break backwards compatibility if it is agreed that the documentation states that this is their intended method of operation.

I got lost in that sentence somewhere. I will just note that audiostreams have operated in their present state since at least 2000 when the code was entered into version control.

Thomas Harte
Member #33
April 2000
avatar

Quote:

I got lost in that sentence somewhere.

Not surprising. It's possibly the most horrid sentence that ever stood.

Quote:

If you understand you correctly, you expect get_audio_stream_buffer() to return the buffer directly after the one being played right at the moment you make the call

How else would you interpret "If it returns a value, that is the location of the next buffer to be played" (emphasis added)?

Anyway, I'm glad this is a documentation issue rather than a genuine implementation flaw.

Kitty Cat
Member #2,815
October 2002
avatar

Quote:

How else would you interpret "If it returns a value, that is the location of the next buffer to be played"?

The next pending buffer to be played that hasn't been filled. If you have a buffer queue of three, fill the first and start playing it, you have:
<filled> <pending> <pending>
Then if you fill the next one
<<filled> <filled> <pending>
the next buffer to be played after that is the third, which is what you get.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

Thomas Harte
Member #33
April 2000
avatar

Quote:

The next pending buffer to be played that hasn't been filled

Right. You've adopted quite different wording to the documentation, so I suggest your post be taken as a vote that the documentation is incorrect.

Elias
Member #358
May 2000

Ok, so would the documentation be any clearer if we append the following to the end?

Quote:

Note that some drivers use more than two buffers internally, and depending on CPU load, multiple buffers may be ready to be filled at once. Therefore, to minimize the chance of overruns, it is best practice to call get_audio_stream_buffer/free_audio_stream_buffer in a loop until get_audio_stream_buffer returns NULL.

--
"Either help out or stop whining" - Evert

Thomas Harte
Member #33
April 2000
avatar

I think it might need more fundamental changes than that. The intro says:

Quote:

You can think of an AUDIOSTREAM structure as a wrapper around two audio buffers. The first thing you do is fill both buffers with sound data and let Allegro play them. Once the first buffer has been played, the second starts, and Allegro lets you know you have to fill the other one (i.e. graphics double buffering applied to sounds too big to fit into memory).

Which isn't true, indeed the change you're suggesting explicitly suggests that you can't "think of an AUDIOSTREAM structure as a wrapper around two audio buffers" if you want to minimise the risk of overruns.

In addition to fixing that and adding your note, I'd also suggest that the get_audio_stream_buffer documentation is altered, at leas to (changes bolded):

Quote:

If it returns NULL, the stream is still playing data you've previously provided, so you don't need to do anything. If it returns a value, that is the location of the next buffer that needs to be filled

It's not perfect, but I could sit here and obsess over the exact wording all day.

Go to: