If you have an updated GEP, then it would be in the Glk Definitions extension (by me). It will be built in to the next version of Inform 10.
My extension checks the “gestalt” for gestalt_sound2. Every interpreter has a list of gestalts, which are just yes/no flags that say what they support. Gestalt_sound2 is the gestalt that is supposed to be checked by all extensions, but I also had to check gestalt_sound before the game would actually try making sound.
The “do we have sound” phrase just translates into Inform 6 as checking the gestalt.
So my short answer is, yes. However, my interpreter is lying, as I don’t support setting volume and having multiple channels and creating and destroying sound channels. The code for those things would be non trivial but not too bad. I just don’t plan on it unless someone wants native glk volume setting support.
Right, thanks.
Yeah, I had an idea to try this for my most elementary sound game, Ghosterington Night. No multiple channels, no volume, it just plays theme music once. For anything more, I continue to wait for the day when the basic online interpreters support sound…
-Wade
It sounds like you have more complex sound games. Maybe you can answer a question I had; I saw that glk supports things like adding “rocks” to channels (rocks are made-up numbers for designating windows). Do you have any idea why it would be useful to assign channels to windows? And what does a complex sound game look like from your end? Like Six? What features do they use? I’ve been being careful to only use sounds and hyperlinks in a way that’s compatible with offline interpreters, so knowing how you did it is useful.
Rocks are used for all Glk objects, not just windows. Schannel rocks have nothing to do with window rocks. (It’s probably safe to use the same rock number for different Glk object types.)
That makes sense. The first time I saw it in the documentation it said:
Every window has a rock. This is a value you provide when the window is created; you can use it however you want. See section 1.6.1, “Rocks”.
I glanced over the rock section, but I didn’t process it. How is a rock different than an ID number, then?
Rocks are mostly used for save/restore. The ID number is assigned by the interpreter and is not predictable. When you restore a save file all the IDs are probably going to be different. To update the ID references so that the storyfile can refer to the objects it expects, it goes through all the objects and matches them by rock number.
Thank you, that is very clear!
Six uses the old Multiple Sounds extension (which I cowrote). The extension gives a foreground channel and a background channel out of the box. Then Six creates four more sound channels (midground, horizon, bird, wind). They all get their own rock.
The game tracks two user-supplied 0-5 volume settings - one for music, one for FX. It then applies these to the relevant channels when those sounds play. Music’s on the foreground, everything else gets the FX level.
The main things the game has to do are:
(a) check if the interpreter can even play sound. If not, it shuts down all the sound code.
(b) Remember user-specified sound levels across games. E.G. So after a restore, it changes volume levels to the persistent values, overwriting whatever might have been in the saved game
(c) Handle rocks correctly on restore. At the time, I had to get help to add code to the restore function to do this. Before that, Six would crash on restore if a sound had been playing at the moment you saved that game, because the rock/glulx objects would no longer match. I don’t know if such things are handled automatically now… this is 13 years ago.
Any fading audio in the game is done manually by stepping the raw volume value (0-65k-whatever) in a curve like fashion. So any fancier audio options in the spec that only existed later (automated fading) aren’t used.
PS - The source is on IFDB, so you can see the sound tests and methods in there if you want.
-Wade
Thanks, that’s good to know. Those things are advanced, but I have an idea of how they might be tracked, and looking at your extension would be helpful. It might take a long time, and I’m not going to focus on it as a priority, but it helps me ‘get the picture’ and is motivating.
Due to an error one user reported involving text going off the page, I checked and realized that my Bisquixe interpreter was based on Quixe 2.1.1, not the latest version of 2.2.2.
So I had to go and cut and paste all my code over, and I had trouble finding it. The new version (Bisquixe Version 4) now has comments /Bisquixe Start/ and /Bisquixe End/ surrounding all changes to help ensure this doesn’t happen agin.
This version is backwards compatible, and all my current code examples still run off of it. Let me know if anything bad comes up!
I’ve released version 5 of both Bisquixe and the extensions for Inform 7 and Inform 10.
This version adds a new way to include graphics in Quixe (detailed in the documentation here) using Inform instead of editing html. Quixe already has full graphics functionality; this addition only skips a somewhat tedious preparation step.
This is fully compatible with other graphics extensions. In both Inform 7 and Inform 10, I was able to use Emily Short’s Location Images right out of the box:
I think I might use this later on to do a re-release of Swigian, as I like the way this looks better than my old custom hack.
Pertinent Swigian code
Release along with a "Bisquixe" interpreter.
Include Simple Multimedia Effects for v10 by Mathbrush.
Include Simple Graphical Window by Emily Short.
Include Location Images by Emily Short.
Use scoring. Maximum score is 15.
Figure of 1_lake is the file "1_lake.jpg".
When play begins:
css-set-fast ".coverimage; display; none";
css-set-fast ".links; display; none";
css-set-fast "#gameport; left; 20%";
css-set-fast "#gameport; right; 20%";
let temp be the glulx resource id of the figure of 1_lake;
add-image "1_lake.jpg" with alttext "Lake" with id temp with width 1000 with height 336;
Part I - Rooms
Chapter 1 - Foresty region
Section 1- Lake
Lake is a room. "You are by a lake. The lake is still."
The room-illustration of Lake is figure of 1_lake.
This is backwards compatible, so any code you may have been working on should still work just great!
Top stuff! Really good to see a general way to add artworks.
Okay, I’ve released Version 6 of Bisquixe and its two extensions, available at the link at the top of the page. This completes all of the things I intended to add.
New features:
-Internal links. You can now add links to internal pages (i.e. pages in the same folder structure as you), with the option to open in the same tab or a new tab. Details in the documentation post at the top (post 2).
-Full sound capability. This means that once you add audio with the add-audio command, you can run any Inform sound extensions, such as Music by Daniel Stelzer.
One caveat for the music extension in particular is that that extension uses a ‘fade step’ function that sets the volume down a notch every millisecond (most likely to work around interpreter struggles); that doesn’t work well with bisquixe, but fortunately Inform already has a default command for fading stuff in and out called set_volume_ext that lets you specify how long you want something to fade in or fade out and even lets you set a notification when it’s done. In my new release of my Audiovisual test, I demonstrate how you can use that notification to play a song, fade out the volume, and ring a bell once that volume is completed.
Full code for it here (there’s a lot of silly stuff in this one, like a pikachu face, so don’t expect a lot):
Code
"Audiovisual" by Mathbrush
[Significant chunks of code were first written by Petter Sjölund.]
The release number is 4.
Release along with a "Bisquixe" interpreter.
Release along with an interpreter.
Include Simple Multimedia Effects by Mathbrush.
Include Music by Daniel Stelzer.
Figure of pikachu is the file "pikachu.jpg".
Figure of Rembrandt is the file "Rembrandt.jpg".
Sandbox is a room. "Hello! To try various features, try clicking links, typing Z to see text alignment, typing JUMP to see various colors used in the same paragraph, or typing I to hear a sound. J plays some music, K stops it, while P and M fade the music in and out when it's playing.
Here's a link to the homepage: [homelink].
Here's a link to the homepage, but opening in a new tab: [homelink2].
From here, you can go [boldnorth]."
To say homelink:
hyperlink "link" as "zzxvm home";
To say homelink2:
hyperlink "link" as "zzxvm home2";
Jumphoming is an action applying to nothing. Understand "zzxvm home" as jumphoming.
Carry out jumphoming:
link-page "/index.html" with TabOption 0;
Jump2homing is an action applying to nothing. Understand "zzxvm home2" as jump2homing.
Carry out jump2homing:
link-page "/index.html" with TabOption 1;
Coolroom is a room.
To say right:
set-any-class "right_just";
To say left:
set-any-class "left_just";
To say center:
set-any-class "center_just";
Sound of bells is the file "Bells1.ogg".
Sound of weird is the file "Weirds.ogg".
Instead of thinking:
display the figure of pikachu;
display the figure of Rembrandt;
When play begins:
let temp be the glulx resource id of the figure of pikachu;
add-image "pikachu.jpg" with alttext "surprised pikachu face" with id temp with width 320 with height 320;
let temp be the glulx resource id of the figure of Rembrandt;
add-image "Rembrandt.jpg" with alttext "Rembrandt" with id temp with width 342 with height 423;
css-set-fast ".Buffer_right_just;text-align;right";
css-set-fast ".Buffer_left_just;text-align;left";
css-set-fast ".Buffer_center_just;text-align;center";
import-google-fonts "Kalnia&family=Rubik+Bubbles";
css-set-fast ".BufferLine;font-family;Kalnia";
upload-audio "Bells1" with internal name sound of bells;
upload-audio "Weirds" with internal name sound of weird;
Instead of taking inventory:
do cool noise;
[play sound of bells on foreground;]
To do cool noise:
(- glk_schannel_play_ext(gg_foregroundchan, ResourceIDsOfSounds-->(+ sound of bells +), 1, 1); -)
Understand "j" as waving hands.
Instead of waving hands:
play sound of Weird on background;
Understand "k" as saying sorry.
Instead of saying sorry:
stop sound of Weird;
Understand "m" as sleeping.
Instead of sleeping:
do a cool mute;
To do a cool mute:
(- glk_schannel_set_volume_ext(gg_backgroundchan, 0, 3000, 1); -)
P-ing is an action applying to nothing. Understand "p" as p-ing.
Carry out p-ing:
do a cool crescendo;
To do a cool crescendo:
(- glk_schannel_set_volume_ext(gg_backgroundchan, 65535, 3000, 1); -)
Vsetting is an action applying to one number. Understand "v [a number]" as vsetting.
Carry out vsetting:
set volume of background to the number understood;
To say boldnorth:
hyperlink "north" as "north";
WeirdRoom is north from Sandbox.
The dog is in weirdroom.
Rule for printing the name of the dog:
hyperlink "dog" as "x dog";
Instead of jumping:
repeat with current running from 3 to 50:
let bigcurrent be current * 3;
let bigtemp be 255 - bigcurrent;
let temp be ".Style_user[current];color;rgb([bigtemp],[bigcurrent],[bigcurrent])";
css-set-fast temp;
let tempclass be "user[current]";
set-any-class tempclass;
say "M";
Instead of waiting:
say "[right]I am on the right!
[center]I am on the middle!
[left]I am on the left!";
Glulx input handling rule for a sound-notify-event:
play sound of weird on background;
Glulx input handling rule for a volume-notify-event:
play sound of bells on foreground;
A g-event is a kind of value. The g-events are timer-event, char-event, line-event, mouse-event, arrange-event, redraw-event, sound-notify-event, hyperlink-event, volume-notify-event.
To decide which g-event is null-event: (- 0 -)
Edit: Note that the volume-notify-event line has to be added because Glulx Entry Points doesn’t include it as the ninth type of g-event but Quixe does.
Also, like usual, this is backwards-compatible, so anything you may have been working on should still work.
I don’t actually remember why Music had to do it that way; it was written quite a while ago. But if it’s no longer necessary, a version of the extension that uses set_volume_ext
should be added to my agenda. That would be a whole lot cleaner!
The Music extension was probably written to work on interpreters without support for set_volume_ext()
. Glk originally had a more bare-bones sound API, without a fading mechanism. set_volume_ext()
was introduced in Glk 0.7.3 in 2011, but some popular interpreters did not support it. Gargoyle added support for this in 2019.
https://eblong.com/zarf/glk/Glk-Spec-Changes.txt
- version 0.7.3 (October 10, 2011)
Added some new sound-playing functions, along with gestalt_Sound2.
New features:
- can pause and unpause a sound channel.
- can change a sound channel’s volume gradually over an interval, and
get an event notification when the volume change is complete.
There’s a gestalt specifically for volume notifications, you could check for that and use your old code on interpreters that don’t have it and the new call on interpreters that do!
Aha, that would be it! I was trying to remember what interpreters didn’t support it, and Gargoyle would have been enough reason for me to avoid it.