Allegro.cc - Online Community

Allegro.cc Forums » Off-Topic Ordeals » [RetroHack] Start of competition

This thread is locked; no one can reply to it. rss feed Print
[RetroHack] Start of competition
Thomas Harte
Member #33
April 2000
avatar

Quote:

Has anyone see that under linux/OSX? If not, its deff a bug in the windows driver.

I wasn't very clear, but the same code as on that other thread returns no buffers for a very long time, then two at once, then none for ages, then two at once, etc on my OS X machine.

The attitude of the developers on that thread also seems to be "this is the way we think Allegro should work, we'll fix the docs". So I'm not sure it's worth trying to organise fixes.

Thomas Fjellstrom
Member #476
June 2000
avatar

As a part time allegro developer, I think its wrong. And I'm not sure the others fully saw what the problem was.

AFAIK, it really should return one of the buffer's the ms its ready. not when more than one are.

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

Eric Love
Member #846
December 2000

Looks like everyone knows where they're going music-wise. Looking at the sound code I think a MIDI driver would've been a bit hard (on my limited time), although the one from Tomb Robber would've been a good starting point.

I wish I'd noticed RetroHack was on earlier. Although I hardly do any game dev any more, it would have been fun to contribute something to this hack. If I'm not busy at the end of the week, I might be up for some testing, if not I look forward to playing the games.

Elias
Member #358
May 2000

Quote:

As a part time allegro developer, I think its wrong. And I'm not sure the others fully saw what the problem was.

AFAIK, it really should return one of the buffer's the ms its ready. not when more than one are.

To me it seems, the problem is not at all Allegro's API, but the implementation - in this case likely the OSX sound driver (or OSX mixer if it doesn't use the software mixer - I wouldn't know).

With the Alsa driver it works like this: Creating the audio stream allocate one Allegro SAMPLE, and plays it as a looping sample. The sample is cut into two halves. Now when you request an audio buffer, it will look which half is currently being played, and return the other half. If you now immediately request a buffer again, it will return NULL. Only when the last returned half starts being played, the now un-used other half is returned to the next request. So basically, you never can get a buffer returned two times consecutively. For this to work, it needs to be known which sample data Alsa is currently processing.. not sure right now if this is done by directly asking Alsa or just calculating the sample position from current time. Or maybe it even is advanced by a whole half-buffer.. should still work correctly even then.

Anyway, I believe now the distortion I was getting here is just this multiple-AY-channels-mixed issue, and has nothing to do with Allegro. exstream works perfectly at least.

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

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

With the Alsa driver it works like this: Creating the audio stream allocate one Allegro SAMPLE, and plays it as a looping sample. The sample is cut into two halves. Now when you request an audio buffer, it will look which half is currently being played, and return the other half. If you now immediately request a buffer again, it will return NULL. Only when the last returned half starts being played, the now un-used other half is returned to the next request. So basically, you never can get a buffer returned two times consecutively. For this to work, it needs to be known which sample data Alsa is currently processing.. not sure right now if this is done by directly asking Alsa or just calculating the sample position from current time. Or maybe it even is advanced by a whole half-buffer.. should still work correctly even then.

Has that changed since I coded it? I recall having it not be in half. it was split up based on the buffer size requested in the config, and then using the alsa config for the buffer sizes... So you could easily have 16 buffers of 1/16th a second, or 1/32 a second or whatever.

--
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:

To me it seems, the problem is not at all Allegro's API, but the implementation - in this case likely the OSX sound driver (or OSX mixer if it doesn't use the software mixer - I wouldn't know).

It'll be more the Windows driver, not the OS X driver - my test program on OS X returns buffers in groups of two, but on Windows it returns them in groups of six. Irrespective of this, I think I'll take the opportunity now to register my opinion that the API should be changed for the new Allegro API. Having a callback function, ala SDL, just makes a lot more sense to me, even if it means you really need to implement some sort of mutex/whatever support. Or at least add a framework by which you can say "create me an AUDIOSTREAM then just tell me what buffer size works for you".

Quote:

Anyway, I believe now the distortion I was getting here is just this multiple-AY-channels-mixed issue, and has nothing to do with Allegro. exstream works perfectly at least.

I still wouldn't rule out the RetroHack code. I'm going to keep looking at it.

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

Irrespective of this, I think I'll take the opportunity now to register my opinion that the API should be changed for the new Allegro API.

The audio bits of allegro 5 haven't even really been planned out yet. Now would be a great time to start ;)

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

Elias
Member #358
May 2000

Hm, yes, there can be more than two buffers apparently - not really sure why. But Allegro always expects you to fill a buffer of the given buffer size, so this should not be of concern to the end user.. should still be perfectly fine not immediately filling all the future buffers as long as no overrun occurs.

For 44100 Hz sound frequency and 50 Hz get_audio_stream_buffer call frequency, the minimum buffer size would be 44100/50=882 samples. So 1024 should work fine - I'll try investigate why 2048 seemed the minimum to work properly for exstream.

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

Thomas Fjellstrom
Member #476
June 2000
avatar

alsa and oss have the idea of "fragments", and you can specify the size and number of them that you want, so you can configure the amount of latency and whatnot that your app can stand. Which should technically be separate from the AUDIOSTREAM handling if AUDIOSTREAM really is just a SAMPLE... needs some looking into.

--
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:

Hm, yes, there can be more than two buffers apparently - not really sure why. But Allegro always expects you to fill a buffer of the given buffer size, so this should not be of concern to the end user.. should still be perfectly fine not immediately filling all the future buffers as long as no overrun occurs.

While that's true, a result of the Allegro API is that there's no way to (a) find out how many free buffers are available; or, more vitally, (b) find out how long it'll be until the buffer you've just received will be played.

Imagine you start and you know you haven't filled any audio yet. A buffer is available so you fill it. Another is available, but you know you don't have to fill it now because you just filled one. How do you know when you need to fill it by? The answer is that you don't. So logically you can't avoid the sort of latency problems we're discussing here.

Conversely, if a buffer was only freed when the one immediately before it was being played then you'd know something - that it needed to be filled in less time than it takes to play the buffer. So you can be pretty good with latency if you're using small buffers.

P.s. how about this for a radical Allegro 5.x suggestion: no sound code. Just build it on OpenAL.

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

P.s. how about this for a radical Allegro 5.x suggestion: no sound code. Just build it on OpenAL.

Thats been suggested. But OpenAL is incomplete at best itself.

One of the original ideas was to have a kick ass api supporting true surround, and positioning. OpenAL doesn't seem to do surround, just positioning.

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

Elias
Member #358
May 2000

Yes, I'm seeing the problem now. So, from just the API view, I'd say it's simple: Always fill only the buffer which is returned. As long as it is big enough (e.g. 44100 / 50 samples plus some space for jitter, if you know you will roughly update 50 times a second), just filling one buffer a time never can cause problems - it will take at least that long to play, and so you are certain to fill the next buffer before it runs out.

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

Thomas Harte
Member #33
April 2000
avatar

Quote:

I'd say it's simple: Always fill only the buffer which is returned.

So then you need to be doing explicit timing of your own to second guess things that are well known within Allegro's audio subsystem and just not exposed? That strikes me as a very poor solution given the well-known unreliable and parlous nature of Allegro's timing mechanisms.

Being "reasonably close" in your guesses will never be good enough. Imagine if I ask for a buffer size that is 1024 bytes, but I'm curious as to whether I need to fill a new one every 1023 bytes of sample time. I fill one, I wait, I see if I can fill another. I can so I do. Now I'm 1 sample ahead. On Windows, on my machine, I continue getting ahead until I am at least 6 buffers ahead because that's the first time that Allegro will actually refuse to give me a new buffer. And the only information I can get from Allegro is it either offering me a new buffer or refusing to offer me a new buffer.

EDIT:

Quote:

(e.g. 44100 / 50 samples plus some space for jitter, if you know you will roughly update 50 times a second),

Amongst other things, the manual says "The length should normally be (but doesn't have to be) a power of 2", now you're suggesting that what the manual recommends is actually not recommended?

Elias
Member #358
May 2000

Quote:

So then you need to be doing explicit timing of your own to second guess things that are well known within Allegro's audio subsystem and just not exposed? That strikes me as a very poor solution given the well-known unreliable and parlous nature of Allegro's timing mechanisms.

The actual play position should be available in the voices code, but I never looked into that much. Basically, audio streams just are a wrapper on top of SAMPLE and VOICE.

Quote:

Being "reasonably close" in your guesses will never be good enough. Imagine if I ask for a buffer size that is 1024 bytes, but I'm curious as to whether I need to fill a new one every 1023 bytes of sample time. I fill one, I wait, I see if I can fill another. I can so I do. Now I'm 1 sample ahead. On Windows, on my machine, I continue getting ahead until I am at least 6 buffers ahead because that's the first time that Allegro will actually refuse to give me a new buffer. And the only information I can get from Allegro is it either offering me a new buffer or refusing to offer me a new buffer.

The solution to this would be to have Allegro choose a buffer size for you, but I think that would be difficult, as it depends on a lot of things. When you know you are not doing any disk operations or whatever might cause the kernel to schedule out your code for too long, a tight buffer size could work. If you're just concerned about sound quality but not delay, a bigger buffer size works. Hence Allegro simply lets you specify the size.. anything obvious I'm overlooking?

[EDIT:] Ah, of course, I was.. if you fill only one buffer each time, you get more and more ahead if there's more than 2. So as I think I already said, not sure why there ever are more than 2 buffers. But with only two buffers, it should be ok, right?

[EDIT2:] I.e. my interpretion is something like this.. you call the buffer function roughly with 50 Hz, so every 20 ms. Your buffer is some power of two. At point 0, you fill buffer A, and the sound starts playing.. then if you fill one buffer each time, all that happens is that sometimes there will be no buffer returned. Also if you call it more often. Just if you call not often enough, there will of course be overruns.

         0     20    40    60    80    100   120   140
call:    |A    |B    |A    |B    |A    |-    |B    |A    
buffers: [ A    ][ B    ][ A    ][ B    ][ A    ][ B    ]

        0      20    40    60    80    100   120   140
call:    |A |B |- |A |- |- |B |- |A |- |- |B |- |- |A |    
buffers: [ A    ][ B    ][ A    ][ B    ][ A    ][ B    ]

Quote:

Amongst other things, the manual says "The length should normally be (but doesn't have to be) a power of 2", now you're suggesting that what the manual recommends is actually not recommended?

Well, use the next higher power of two? So 1024. But here, with 1024, I still get occasional overruns, so 2048 is the best (which means 46 ms of delay before the last data in the buffer reach the underlying system, in my case Alsa).

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

Thomas Harte
Member #33
April 2000
avatar

Quote:

Well, use the next higher power of two? So 1024. But here, with 1024, I still get occasional overruns, so 2048 is the best (which means 46 ms of delay before the last data in the buffer reach the underlying system, in my case Alsa).

I was referring to your suggestion that if I'm already synchronising myself to a 50 Hz beat then I can usurp Allegro's opaque internal sample timing by starting an audio stream with a 44100 / 50 (or whatever) sample length buffer and only requesting a new buffer when I know I'm time synchronised from some other clock. Obviously I can either follow that earlier suggestion, to try and guess close to my play position, or follow this new one and have Allegro be less likely to do whatever the manual is warning may happen.

EDIT: obviously there would never be a problem (other than the usual gross inefficiencies associated with polling for real time events) if the audio stream code kept exactly two buffers internally.

Thomas Fjellstrom
Member #476
June 2000
avatar

You could just skip AUDIOSTREAM and handle it yourself.

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

Elias
Member #358
May 2000

Hm, in fact, it does not look to me like it can use more than two buffers:

http://alleg.svn.sourceforge.net/viewvc/alleg/allegro/branches/4.3.10plus/src/stream.c?revision=8101&view=markup

http://alleg.svn.sourceforge.net/viewvc/alleg/allegro/branches/4.3.10plus/include/allegro/stream.h?revision=8101&view=markup

It seems a SAMPLE can consist of multiple buffers, which is what this code handles and is somewhat confusing.. but the user only ever gets returned one half or the other - at least after another quick glance now.

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

Thomas Harte
Member #33
April 2000
avatar

Quote:

You could just skip AUDIOSTREAM and handle it yourself.

I intend to look into exactly that when I next get a chance. I hadn't registered the existence of voice_get_position. Seems a bit perverse when this is what AUDIOSTREAMS are for.

EDIT:

Quote:

Hm, in fact, it does not look to me like it can use more than two buffers:

Then explain the results of the small sample code in this thread.

Elias
Member #358
May 2000

Quote:

Then explain the results of the small sample code in this thread.

Yes, I agree now, the 6 seems wrong. Even 2 should only happen at the very start. But likely I'm mis-interpreting stream.c somehow - since I don't see what good it would be splitting the sample into multiple buffers in any case, whether with more than 2 user buffers or not, just never seems to be an advantage. To quote #allegro from a bit earlier:

Quote:

<elias> hm, i don't get allegro's audiostreams code
<elias> wonder what Shawn was thinking when he made all those buffers.. :P
<Sevalecan> "hic"

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

Paul Pridham
Member #250
April 2000
avatar

PortAudio seems to be a good portable streaming audio library: http://www.portaudio.com/

I've seen it used in a project or two, and the results were quite acceptable. Perhaps we can either see how they are doing it, or adapt it for Allegro 5. The license is pretty liberal.

Thomas Harte
Member #33
April 2000
avatar

Further to the question of low latency audio with the RetroHack simulation library, does anybody care to try the new test version attached to this post? It's main claim to fame is that it dumps AUDIOSTREAMS in favour of doing its own stuff in the SAMPLE structure with an allocated voice.

EDIT: okay, I'm aware of an integer that overflows after about 3 minutes of play. I'll fix that. But I could still do with some feedback on latency and quality of sound for the first three minutes!

EDIT2: that bug is fixed. New version is attached (get V12Test.zip rather than Archive.zip). Feedback is still sought.

Jakub Wasilewski
Member #3,653
June 2003
avatar

Quote:

okay, I'm aware of an integer that overflows after about 3 minutes of play. I'll fix that. But I could still do with some feedback on latency and quality of sound for the first three minutes!

So that's what's causing it! And here I was looking for the overflowing counter on my side ;). Should have posted about it I guess - but it didn't seem to do me any good when I posted about the #include <allegro.h> and C++ issue :P. (Just kidding, it was easy to overlook in a rather longish post).

Anyway, I'm not having any time at all lately, so I might not be able to finish with all the others - but I will surely wrap up the game in the following week and post it anyways. It's just too much fun coding for a constrained machine (one can really flex his/hers programming muscles), and thanks to those bugs we have added realism (computers often had their own bugs, but those were rather hard to fix on the spot) :-).

---------------------------
[ ChristmasHack! | My games ] :::: One CSS to style them all, One Javascript to script them, / One HTML to bring them all and in the browser bind them / In the Land of Fantasy where Standards mean something.

Thomas Harte
Member #33
April 2000
avatar

Quote:

Should have posted about it I guess - but it didn't seem to do me any good when I posted about the #include <allegro.h> and C++ issue

That wasn't ignored - check out the placing of #include <allegro.h> in both of the test versions of the 1.2 library, attached to my most recent previous post.

If nobody else comments then I'll assume 1.2 is good to go (subject to one additional latency decrease I've thought of while at work) and release it as soon as possible. I think pushing fixes out now is more time dependant than it was earlier in the competition.

Paul Pridham
Member #250
April 2000
avatar

Thomas, I'd love to test out your change, but won't be able to get to it 'til tonight sometime. I appreciate your efforts.

Elias
Member #358
May 2000

I just tested here, and now I get a perfect square wave in my earlier example - so that distortion also was fixed by your change. Also in the game I can't here distortion any longer, and still no overruns or audible delay - so very nice :)

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



Go to: