How many sounds can glulx play at once?

Hi guys. I can’t find any documentation about the max # of audio channels a glulx/glk game can handle that gels with my hands-on experience.

The most up to date info I have is from one 8 year old source which says a game can handle two audio channels at max, and advises not mixing types:

‘Sound Channels - {Objects} Sounds are played in channels, one sound per channel. Technically two sounds could play in two channels at once, creating a mixing effect (a sound effect heard over background music). However, this can get tricky and is not guaranteed to work in all instances. MOD files demand more of each player’s computer resources and players’ computers differ. So L. Ross Raszewski recommends when “mixing”, combine one AIFF with one MOD, or combine two AIFFs. While David Kinder states that one MOD file will take all Windows Glulxe’s resources, so if playing two sound files simultaneously they should both be AIFF ’

(iffydoemain.org/glkdunces/gl … htm#format)

These days, glulx can handle ogg files. Massimo Stella’s ‘Multiple Sounds’ extension comes equipped to play two sound channels at a time. I cribbed a line of code from it to add a 3rd channel to my game, and the resulting gblorb file ran fine in Gargoyle - IE it was indeed capable of playing 3 ogg sounds at once.

My question to anyone who may know is – does anyone know the real limit? Is there one? Is a game with more than 2 sound channels going to make some interpreters crash or stress the system?

It’s not that I’m barraging the player with quadrophonic sound with my 4 channels, but you need extra channels to prevent music, atmos and spot fx cutting each other off.

Argh, wait!.. not that I don’t want an answer to this question(s) but I have to doublecheck I didn’t just trick myself into thinking I had 3 sounds going at once :wink:

Edit - Yeah, I cannot reproduce my 3 channels, ergo I figure I must have tricked myself. This suggests the limit is 2 channels, but I’d appreciate any further info.

That’s a very old quote from me that’s not been correct for a long time!

The basic answer to your question is ‘it depends on what the interpreter’s Glk library can do’. These days Windows Glk uses Windows’ DirectSound interface under the hood, which is very powerful, so with a Windows Glk-based interpreter (i.e. Windows Glulxe or Windows Git) there is no limit on how many different sound channels you can create, and they can all play any different sounds without problems. Gargoyle I know relies on the SDL library for sound support, which has a few limitations, such as not liking playing multiple sounds simultaneously that have different sampling rates.

Partly this is a reflection of the fact that few games use sound, so Glk library authors have tended to not worry about this too much. (Does Zoom even support sound? It didn’t a while back.)

Anyway, I would certainly expect three simultaneous channels to work on a Windows Glk based interpreter. Personally I would assume that such a thing should work and complain to the appropriate interpreter authors if it does not :slight_smile:

Additional thought: your code could print out the result of the Glk sound calls, which will give information on what the Glk library itself thinks is going on. Sound channels are created by calling glk_schannel_create(): if this returns 0, the Glk library couldn’t create any more channels. Similarly, sounds are played by calling glk_schannel_play() or glk_schannel_play_ext(): these return 0 if the Glk library hit a problem when starting to play.

Depends. This is usually a limitation when you choose to go the quick route and use an under-performing, buggy and very out of date helper library (SDL_mixer). Which is what most people end up doing, since you can implement sound support in your application with it in about 15 minutes (and this isn’t an exaggeration.) But then of course you pay the price when authors use non-uniform sample rates or slightly non-standard-conforming sound formats.

Anyway, the point is that SDL itself has no limitations in this regard, since all it does is play one single audio stream. It’s up to you to mix your sources together into that single stream :mrgreen:

Thanks a lot guys.

Okay, my problem is I don’t know how to implement the glk calls.

I’m usually pretty good at looking at a sample chunk of code (from some language/environment I don’t know) and deriving what I need from it, but for instance, I haven’t been able to add 3rd and 4th channels (called, say, third, and fourth) by cutting and pasting bits of Massimo’s extension. I’ll paste the whole extension below, as it’s not very long. If you could tell me the actual code needed to add 3rd and 4th channels, I’ll be super happy.

What I tried, btw, was to add this to my game (with the extension already in place):

To play (SND - a sound name) in midground: (- SoundReproduce(ResourceIDsOfSounds-->{SND},gg_thirdchan,1); -)

Then I tried to ‘play sound of blah in midground’ during my game. But this wouldn’t compile - it suggested I6 errors as the culprit.

The extension: (which sets up two channels called foreground and background)

[code]Version 2 of Multiple Sounds by Massimo Stella begins here.

“Provides facilities for the basic reproduction of multiple-channel audio with loops under Glulx.”

Use authorial modesty.

[The idea for this extension was born from some code written by Eliak Blauk on rec.arts.int-fiction in 2008. Thanks to Sarganar for his bug report.]

Section - IF6 Code

Include (-
[ SoundReproduce sound chan loop;
if (glk_gestalt(gestalt_Sound,0) && glk_gestalt(gestalt_SoundMusic,0)) {
glk_schannel_play_ext(chan,sound,loop,0);
}
else {
“Your interpreter doesn’t support sound reproduction.”;
}
];

[ VolumeControl chan val;
if (glk_gestalt(gestalt_SoundVolume,0)) {
if ((val <= 5) && (val >=0)) {
glk_schannel_set_volume(chan, val * 16384);
}
else {
“Invalid Volume Level: please insert a value between 0 and 5.”;
}
}
else {
“Your interpreter doesn’t support volume control.”;
}
];

[ SoundStop chan;
if (glk_gestalt(gestalt_Sound,0) && glk_gestalt(gestalt_SoundMusic,0)) {
glk_schannel_stop(chan);
}
else {
“Your interpreter doesn’t support sound stopping.”;
}
]; -).

Section - Declaring Commands

To play (SND - a sound name) in foreground:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_foregroundchan,1); -)

To play (SND - a sound name) in background:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_backgroundchan,1); -)

To play (SND - a sound name) in foreground with loop:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_foregroundchan,-1); -)

To play (SND - a sound name) in background with loop:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_backgroundchan,-1); -)

To play (SND - a sound name) in foreground for (loop - a number) times:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_foregroundchan,{loop}); -)

To play (SND - a sound name) in background for (loop - a number) times:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_backgroundchan,{loop}); -)

To set the foreground volume to (VOL - a number):
(- VolumeControl(gg_foregroundchan,{VOL}); -)

To set the background volume to (VOL - a number):
(- VolumeControl(gg_backgroundchan,{VOL}); -)

To stop the foreground sound:
(- SoundStop(gg_foregroundchan); -)

To stop the background sound:
(- SoundStop(gg_backgroundchan); -)

Multiple Sounds ends here.

---- DOCUMENTATION ----

This extention allows the reproduction of two audio layers at once under the Glulx envinronment. It implements only a few features regarding the audio files management (such as loops, double channel reproduction, volume control and sound stops) and it will become obsolete when Damusix by Eliuk Blau will eventually be released for Inform 7.

After having declared the name of an audio file, like indicated in the IF7 main documentation:

Sound of frogs is the file "Frogs.ogg". 

We can choose how to reproduce it, on the background channel or on the foreground one:

play the sound of frogs in background;
play the sound of frogs in foreground;

Sometimes a continuous loop might be useful:

play the sound of frogs in background with loop;
play the sound of frogs in foreground with loop;

Also the repetition of a specific audio file for N times is supported:

play the sound of frogs in background for 5 times;
play the sound of sea in foreground for 10 times;

Glulx allows to play multiple sounds at the same time, provided they are reproduced on different channels:

play the sound of frogs in background;
play the sound of birds in foreground;

To stop an audio file:

stop the foreground sound;
stop the background sound;

To modify volume from a minimum level of 0 (silence) to a maximum level of 5 (full volume):

set the foreground volume to 2;
set the background volume to 1;

Example: * Rainforest - Shows how to use multiple sounds effects to mimic a natural environment.

*:	"Rainforest"

Include Multiple Sounds by Massimo Stella.

The Swamp is a room. The description is "A beautiful mirror of water is in front of your eyes while behind you there are the tallest trees you've ever seen. You can hear the sound of some frogs in the distance."

Sound of frogs is the file "Frogs.ogg". 
Sound of water is the file "Water.ogg".

When play begins:
	set the background volume to 2;
	play the sound of frogs in background;
	set the foreground volume to 3;
	play the sound of water in foreground with loop.
[/code]

Did you set up the midground channel first? You would need to create that channel (I think that the foreground and background channels used by the extension are created by the I7 library). You could try searching the Inform template files for gg_foregroundchan to see how to do this. This reference might also be useful for you:

iffydoemain.org/glkdunces/summary.txt

You might also be interested in the Damusix I6 extension, which has been ported to I7, but sadly never released…

caad.es/eliukblau/damusix.html

–Erik

I figured that might be where I was coming undone, as I couldn’t see anything in the extension I just used actually establishing a foreground and background channel. Thanks for the pointers. They ought to help me extrapolate what I need.

I found the sound channel init routines in the Glulx.i6t file contained in the I6 template on this page:

inform7.com/sources/webs/

… but after much copying, pasting, poking, extrapolating and struggling, I have to accept initialising another one is beyond my capabilities. I don’t know i6 and each change I make increases the number of i6 compile errors I’m getting. It may even be I’m typing the correct lines (it looked like it may only take about 5 or 6 lines of code) but simply have the formatting or placement wrong.

This operation also looks to be difficult in terms of … there are comments in the glulx.i6t file about closing the channel down and making various glk calls at initialisation and restart times, so I wondered if there’s more programming involved than just turning the channel on.

In any case, I humbly extend a request for help to anyone who does understand glk and i6 programming as to how to initialise a 3rd and maybe 4th sound channel.

In the meantime, I’ll go back to doing the programming I know how to do :slight_smile:

(the next day…)

Okay, it was bloody frustrating to work out, but I got my 3rd channel, and now could add as many as I want.

For the millions champing at the bit for this spunky bit of code, here it is.

[code]Section - IF6 Code

Include (-

Global gg_midgroundchan=0;
Constant GG_MIDGROUNDCHAN_ROCK 412;

[ MidCreate;
if (glk_gestalt(gestalt_Sound, 0)) {
if (gg_midgroundchan == 0)
gg_midgroundchan = glk_schannel_create(GG_MIDGROUNDCHAN_ROCK);
}
];

Section - Declaring Commands

To create the midground channel:
(- MidCreate(GG_MIDGROUNDCHAN_ROCK); -)

To play (SND - a sound name) in midground:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_midgroundchan,1); -)
[/code]

IIRC some of the complexity of Damusix came from the edge cases: what happens to a looping sound when you restore from a saved game, or undo/redo a command that triggers a sound?

If you’re waiting on notification to tell you when playback finishes, in those cases you could see the event arrive before the sound is even played (in game terms).

I assume that the I7 library handles the bookkeeping for the normal sound channels, but it’s something to keep in mind if you start chaining effects together or intend to use the new channels for background music.

I should be okay. ‘Multiple Sounds’ has some easy to use calls in it that let you manually look after things at the moment of restart or restoring.

'Undo’ing while music is playing already cuts off the music in interpreters I’ve tried, which is fine by me. (I’m not using looping, well, at least in-game, or Yet.)

Basically I just wanted one more channel so that in the rare moment when 3 different kinds of sounds play at once, no one kind will be cancelled. And I’m putting only one shots fx on the new channel. Longer music will stay on one of the official channels.

Yes. :mrgreen:

Damusix not dead. I am currently working on the fourth version of the audio engine.

Recent changes in I7’s resource management I have had to reconsider some features of Damusix, besides the well-known delay was due to translation of the documentation (and a new place of work where I am now).

Damusix worked correctly until it ceased to work two or three I7 releases ago. However, as I said, the delay of the Damusix release was due to the translation of documentation, which is very detailed.

Because of this, Damusix 4 for I7 will be released with a “preliminary” version of the documentation, and henceforth this will be completed. (The documentation in Spanish for Inform6 already exists and is complete, but now we have to adapt to I7 and translate it into English.)

Hopefully it is, finally!, for this year. :slight_smile: Thank you all for your patient waiting.

Saludos! :mrgreen:

P.S: this message is google translated, sorry.

The idea for this extension was born from some code written by Eliak Blauk on rec.arts.int-fiction in 2008

Is Eliuk Blau. :laughing:

Haha, hey, there’s at least one of us. I’m having the same problem as you were - wanting the option to have more than two sounds going at once - but your solution isn’t working for me.

I think there was a missing " -) " just before the Section - Declaring Commands, but when I fix that, I get an I6 error.

Error: Variable must be defined before use: “gg_midgroundchan”

It’s been a while since I used I6, and I never got a good grasp the first time around. I don’t really get the error, because you defined it with “Global gg_midgroundchan = 0;”

Any tips?

Jason

It sounds like maybe the positioning of the included I6 block was left out, along with the -). Try something like:

Include (- ... -) after "Definitions.i6t".

–Erik

Hey Jason,

In my moment of triumph, I don’t think I quoted the whole enchilada, just the bit that I had to nut out to make the 3rd channel work - and that was already on a base of the MultipleSounds extension. I believe the compiling problem you’re having is that the ‘SoundReproduce’ line from my quoted code only works on top of the extension.

What I’ll do is past the whole modified extension below (which gives 3 channels, foreground, background and midground.) Note also I haven’t added looping or on-demand stopping for the midground yet, but that’s as easy as duplicating the one-line foreground looping and stopping lines in the extension, and dropping the word ‘midground’ in in place of foreground.

I put comments in the code for myself explaining how to add any more channels if you want them. They’re not super explicit so let me know if you need elaboration. Beyond the I6 code, something to remember is that the foreground and background channels are created by Inform by default at game init. For all further sound channels the author adds, he must issue a ‘create’ instruction for them when his game starts (or at least before they are used in the game). So you’ll see the ‘create midground channel’ command is the first thing defined in the ‘Section - Declaring Commands’.

[spoiler][code]
Version 2 of MultipleSoundsForSix by Massimo Stella begins here.

[This is NOT the raw version of MultipleSounds. This is Wade Clarke’s edit, adding a midground channel. For the original extension, go to the Inform 7 Website extensions page]

“Provides facilities for the basic reproduction of multiple-channel audio with loops under Glulx.”

Use authorial modesty.

[The idea for this extension was born from some code written by Eliak Blauk on rec.arts.int-fiction in 2008. Thanks to Sarganar for his bug report.]

Section - IF6 Code

Include (-
[ SoundReproduce sound chan loop;
if (glk_gestalt(gestalt_Sound,0) && glk_gestalt(gestalt_SoundMusic,0)) {
glk_schannel_play_ext(chan,sound,loop,0);
}
else {
“Your interpreter doesn’t support sound reproduction.”;
}
];

[ VolumeControl chan val;
if (glk_gestalt(gestalt_SoundVolume,0)) {
if ((val <= 5) && (val >=0)) {
glk_schannel_set_volume(chan, val * 16384);
}
else {
“Invalid Volume Level: please insert a value between 0 and 5.”;
}
}
else {
“Your interpreter doesn’t support volume control.”;
}
];

[ SoundStop chan;
if (glk_gestalt(gestalt_Sound,0) && glk_gestalt(gestalt_SoundMusic,0)) {
glk_schannel_stop(chan);
}
else {
“Your interpreter doesn’t support sound stopping.”;
}
];

! Between here and ‘Section - Declaring…’ is my new stuff needed to add a new sound channel. I called it ‘midground’.
! To add further channels, give each one a new name, a global and constant (as per midground), increase the ROCK number by 1 each time (midground is 412, so the channel after should be 413, the one after that 414, etc).
! Add a ‘create’ instruction for each new channel and call all ‘create’ instructions when your game starts.
! Cobble together appropriate 'play a sound in (whatever)ground instructions, etc. Voila!

Global gg_midgroundchan=0;
Constant GG_MIDGROUNDCHAN_ROCK 412;

[ MidCreate;
if (glk_gestalt(gestalt_Sound, 0)) {
if (gg_midgroundchan == 0)
gg_midgroundchan = glk_schannel_create(GG_MIDGROUNDCHAN_ROCK);
}
]; -).

Section - Declaring Commands

To create the midground channel:
(- MidCreate(GG_MIDGROUNDCHAN_ROCK); -)

To play (SND - a sound name) in foreground:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_foregroundchan,1); -)

To play (SND - a sound name) in midground:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_midgroundchan,1); -)

To play (SND - a sound name) in background:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_backgroundchan,1); -)

To play (SND - a sound name) in foreground with loop:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_foregroundchan,-1); -)

To play (SND - a sound name) in background with loop:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_backgroundchan,-1); -)

To play (SND - a sound name) in foreground for (loop - a number) times:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_foregroundchan,{loop}); -)

To play (SND - a sound name) in background for (loop - a number) times:
(- SoundReproduce(ResourceIDsOfSounds–>{SND},gg_backgroundchan,{loop}); -)

To set the foreground volume to (VOL - a number):
(- VolumeControl(gg_foregroundchan,{VOL}); -)

To set the midground volume to (VOL - a number):
(- VolumeControl(gg_midgroundchan,{VOL}); -)

To set the background volume to (VOL - a number):
(- VolumeControl(gg_backgroundchan,{VOL}); -)

To stop the foreground sound:
(- SoundStop(gg_foregroundchan); -)

To stop the background sound:
(- SoundStop(gg_backgroundchan); -)

MultipleSoundsForSix ends here.

---- DOCUMENTATION ----

This extention allows the reproduction of two audio layers at once under the Glulx envinronment. It implements only a few features regarding the audio files management (such as loops, double channel reproduction, volume control and sound stops) and it will become obsolete when Damusix by Eliuk Blau will eventually be released for Inform 7.

After having declared the name of an audio file, like indicated in the IF7 main documentation:

Sound of frogs is the file "Frogs.ogg". 

We can choose how to reproduce it, on the background channel or on the foreground one:

play the sound of frogs in background;
play the sound of frogs in foreground;

Sometimes a continuous loop might be useful:

play the sound of frogs in background with loop;
play the sound of frogs in foreground with loop;

Also the repetition of a specific audio file for N times is supported:

play the sound of frogs in background for 5 times;
play the sound of sea in foreground for 10 times;

Glulx allows to play multiple sounds at the same time, provided they are reproduced on different channels:

play the sound of frogs in background;
play the sound of birds in foreground;

To stop an audio file:

stop the foreground sound;
stop the background sound;

To modify volume from a minimum level of 0 (silence) to a maximum level of 5 (full volume):

set the foreground volume to 2;
set the background volume to 1;

Example: * Rainforest - Shows how to use multiple sounds effects to mimic a natural environment.

*:	"Rainforest"

Include Multiple Sounds by Massimo Stella.

The Swamp is a room. The description is "A beautiful mirror of water is in front of your eyes while behind you there are the tallest trees you've ever seen. You can hear the sound of some frogs in the distance."

Sound of frogs is the file "Frogs.ogg". 
Sound of water is the file "Water.ogg".

When play begins:
	set the background volume to 2;
	play the sound of frogs in background;
	set the foreground volume to 3;
	play the sound of water in foreground with loop.

[/code][/spoiler]

Hi!

My name is Massimo Stella and I’m the author of the above mentioned extension Multiple Sounds!

Firstly, I would like to deeply apologize for the mystype of Mr. Blau’s name, I’ll upgrade the extension as soon as possible!

Secondly, it would be great if I could use Mr. Clarke’s code for a newer version of Multiple Sounds, obviously with the proper credits.

In the meanwhile…we all are waiting for the IF7 version of Damusix so keep up the good work with it!

Hi Massimo,

Thanks a lot for your extension. I’ll try to send you what I’ve done soon. I’ve got it all working very well now.

I have a question about Multiple Sounds. Internally you use a volume level between 0 and 81920. Where did the 81920 come from? I understand that it’s 5 x 16384, but I’ve found that there’s no audible difference between 65536 (volume level 4) and 81920 (volume level 5, or maximum) - both seem to be equally maximum. I tested this on all Mac interpreters and on the PC ones as well, and found the same thing. So in my game I’ve changed the volume range to 0 to 65536 for this reason. But I have never seen any documentation about what the level means anyway. Nearly all my audio code is based on or developed from what other people have done in their extensions.

  • Wade

The volume level is defined in the Glk spec: 0 is silence, 65536 is full volume.