Playing sounds one after another

Is there a way to play sounds one after another? With something like this,

Instead of listening: Play the sound of Sound-1; Play the sound of Sound-2.

you end up hearing only one of the sounds. I also tried the Multiple Sounds extension, but as far as I can tell, it doesn’t address this.

Hi bg.

If you mean to play them consecutively - Ie when the first one ends, the next one begins - there is some sound notification code in Glulx that was meant to allow for this (it should alert you when a sound ends, which you could use to then start the next one) but in practice it doesn’t work because of the way Glulx polls for certain kinds of events happening. I experimented with it extensively, and other people better at the advanced Inform coding (Erik Temple plus some other onlookers) confirmed my findings.

I’m an assistant author of Multiple Sounds, and I’d have added this functionality if it had worked.

The workaround is doable, but tedious to program.

There is a timer in Glulx. You can start it running and it counts how much real time is passing. And Glulx is good at reacting when the timer hits a target you’ve set.

So the way I do this kind of thing is: First, you have to take note of how long each of your sounds is in milliseconds. Let’s say sound 1 is 1.5 seconds long. So that’s 1500 ms.

Then, in your game, when you play sound 1, you start the glulx timer and ask it to get back to you after 1500 milliseconds. When it reports back, you stop the timer, start playing sound 2, and ask the timer to get back to you after (the length of sound 2), etc.

This is the programming approach. I don’t think the situation has changed in terms of the arrival of the new Inform, or the implementation of the most recent version of Glulx’s sound code in interpreters, to get around this yet. Someone else can chime in if this is incorrect.

I thought I’d just tell you about the overall situation before ploughing into any specific code, to see if you’re game to do this.

-Wade

I was just having a look at a topic about the game ‘Transparent’ from IFComp

viewtopic.php?f=32&t=17101

and I see the author mention a new Music extension he used. And I see this extension is something that builds on Multiple Sounds a bit:

github.com/i7/extensions/blob/m … /Music.i7x

I’m guessing this extension is for the new Inform? I know next to nothing about it thus far except that it exists. Looking at it, it supports crossfades, and seems to support some of the newer sound calls, like automatic fading. Though with those, I don’t think they’re very commonly supported in interpreters yet.

So it looks pretty cool. But it doesn’t do sound notifications (I’m guessing they still don’t work right), thus I doubt it helps with the problem posed in this topic. I just wanted to mention it here.

-Wade

I’m not aware of any fundamental problems in Inform or Glulx that stop this working - using sound notifications and some Inform 6 code is how I’d do it. There is a bug in Gargoyle that causes problems with sound notifications (https://code.google.com/p/garglk/issues/detail?id=204) - is that what you mean? If so there’s nothing Inform can do about this, it’s simply a Gargoyle bug.

As far as I know, sound notifications work in all other interpreters that support them. If you’ve an example that demonstrates anything different, I’d be interested.

Yes, consecutively is what I mean–one sound ends before the next one begins.

From what you both are saying, it sounds like either the timer or the sound notifications (except in Gargoyle) might work. I’m game to try whichever method is easier, so long as it’s possible to do it by imitating an example, since I don’t know Inform 6.

I’d like to be able to code something like “Play the first sound (one of various options) and then play the second one (one of various options),” rather than assuming that the first sound will be always be, say, “frogs” and the second sound will always be “crickets,” or whatever.

I tried compiling the source for David Kinder’s “Sound Notifications” example (substituting another sound file) and when I ran it in Inform, I got an error message:

I’m not sure whether this is related, but I’m also having trouble with the example “Input Handling” that accompanies Glulx Entry Points, version 10. I’ve pasted the example below:


Include version 10 of Glulx Entry Points by Emily Short.

Use direct event handling.

Glk Testing is a room.

Glulx input handling rule for an independent of the player g-event:
say "[bracket]Non-input event detected: [current glk event][close bracket][line break]".

Glulx input handling rule for a dependent on the player g-event:
     say "[bracket]Player input detected: [current glk event][close bracket][line break]".

Glulx input handling rule for a line-event:
     now the Glulx replacement command is "jump".

When I compile and run it, the “Non-input event detected” line never seems to print anything, even if I add a sound, and successfully play it.

Does the sound you played have the notification request on? A sound doesn’t trigger an event unless notification was requested. The easiest way to test the example is to resize your interpreter window. One or more events should be logged.

In the Input Handling example? I didn’t do anything special to the sound, so I guess not. I’m not sure how to turn on the notification request. For David Kinder’s example, I used the code exactly as it was, changing only the line that identified the sound file.

Ok, I tried the “Input Handling” example, resized the window, and got this error message: “>Fatal Error: Printing text to a window that is waiting for line or character input is not allowed.”

Thanks David, and it looks like you’re right. In fact, following your link, I see you answered this for me the first time around. It’s just this stuff is so complex and it’s so long between drinks, I often can’t remember the innermost details of what I’ve learned, even when I was the person who explicitly began the research.

The real problem is, then, there is only one interpreter for Macs with sound: Gargoyle. So no sound notifications in Gargoyle currently = no properly functioning sound notifications for any Mac players, period. In the IF world, I just wouldn’t do that at the moment. If your game relied on it heavily, you’ve lost that feature for all the Mac players.

-Wade

I’ll have a look at this and try to come up with a working example soon.

Hmm. Can using the timer be done without getting into I6? You mentioned the timer solution was tedious, but I’m less concerned about tedium than about the likelihood of me breaking something and not being able to fix it.

Thank you. I hadn’t realized that Mac users would be without any means of getting sound notifications, though, so now I’m wondering if I ought to try the timer route instead. If so, I may not need an example for this after all.

I had a quick look. The problem with the “Fatal Error” message seems related to changes to Glulx Entry Points, which may have introduced a bug. However, that’s not really relevant, since that is related to issues with printing out text while waiting for input, and the code only printed out text in order to allow us to test that the notification worked. I will have a look at that, but that’s not the main point here.

The following code will play two sounds, one after the other. It won’t work properly on Gargoyle, though. Personally, I would not try to hack this with timer events: I would just note that Gargoyle has a bug that needs fixing. Timer events are going to be a lot less reliable in use than sound notifications, as timer events aren’t guaranteed to give you accurate timings: they just give you the chance to run something at roughly some point in the future. Trying to write games that work around interpreter bugs is usually a futile exercise - if the interpreters aren’t being updated then eventually they will be useless.

This only uses one little bit of Inform 6, needed to play the sound file with the appropriate flags to trigger a notification event. If you wanted more elaborate patterns of sounds playing then the Glk input handling rule would need to be more complicated, and possibly use the values in the notification event, but that’s not what was asked for :slight_smile: If needed I can produce a more elaborate example.

[code]“Sound Experiment” by David Kinder

Include Glulx Entry Points by Emily Short.

Use direct event handling.

The Sound Stage is a room. “Enter ‘chime’ to play two chimes.”

Sound of Chiming One is the file “Chime1.aiff”.
Sound of Chiming Two is the file “Chime2.aiff”.

Playing chimes is an action applying to nothing. Carry out playing chimes:
play Sound of Chiming One with notification;
say “The chimes have started playing.”

Understand “chime” as playing chimes.

Glulx input handling rule for an independent of the player g-event:
if the current glk event is a sound-notify-event:
play Sound of Chiming Two.

To play (SFX - sound name) with notification:
(- glk_schannel_play_ext(gg_foregroundchan,ResourceIDsOfSounds–>{SFX},1,1); -).
[/code]

I’ve worked out what was wrong with the original sound notification example: changes to how Inform 7 handles whether to print trailing paragraph and line breaks meant that an extra return was being printed after the code that printed out that a notification had been received. For reference, if you want to print out text from a notification rule, you’ll need something like

[code]
[When handling the event…]
cancel line input in the main window;
say “Got a Glk event[line break]>[run paragraph on]”;
restart line input in the main window.

To restart line input in the/-- main window:
(- glk_request_line_event(gg_mainwin,buffer+WORDSIZE,INPUT_BUFFER_LEN-WORDSIZE,0); -)
[/code]However, none of that’s needed if you just want to trigger a further sound to play - it’s only needed for printing out text in this case.

There were several places I wished I could have done consecutive sounds, or somehow queued a series of sounds. That extension gives three channels of sound and an INTRODUCE [SOUNDNAME] command that will automatically fade up and repeat a clip on either foreground or background alternatingly so it crossfades. I mostly ended up using foreground/background for continuous sounds like the ambient drone or the telephone ringing and repeating, then mid ground for one-off sounds like the camera shutter or door slams. I know there were times I wished I could have made sure a sound got through, and it required some juggling channels when I wanted simultaneous things to happen and not get buried. Compromises were made, but as I said in the postmortem, I love that extension and sound was one of the best-behaving elements of that game.

If I didn’t have limitations of file-size (like with Final Girl, where the sounds were hosted from a dropbox) I would have recorded different variations of each sound with the specific unusual cues mixed in exactly where I wanted them. In the post comp release I really wanted to play a sound just at utter random to the player, but since that’s impossible, I ended up hooking it to a “look” action with a random chance to occur. If I’d had unlimited resource, I would have recorded variable background drones each with a different unusual element and switched them around to make the differences seem to happen randomly.

I agree in theory. But the practice on the Mac, one of the major platforms for both authors and users, is - we’ve only got 2 interepreters that can run a new game.

One, Zoom, has no sound and has enough other bugs that it’s close to being regarded as broken (or simply is), though it still runs a lot of games fine.

The other, Gargoyle, has sound, but it also has a sound bug in the most fundamental area of advanced sound.

So both interpreters are sliding or have slid. If I’m writing on a Mac, to even test my own game, I have to write around these things. It’s either that or wait X years for the kind souls who have the ability to fix or write these interpreters do so.

-Wade

Thanks! That’s working fine, except, as you said, in Gargoyle. And thanks for the code to address the error.

I’d be interested to try it this way also, and see how it works. Are there any updated extensions for timers, or can anyone point me to an example of how to use a timer?

This bothers me, believe me.

Anyone want to sponsor some Glk development work?

If someone was to start maintaining Gargoyle again I think there would be many people who’d be willing to sponsor them, me included!

I would totally sponsor some stuff!

bg, just popped in to read messages and going offline now, but I’ll get back to you tonight if you do want to try the ‘timey’ way of sound queueing. It is, as has been pointed out, not pretty, but basically works.

EDIT:

Generally I use Erik Temple’s Real Time Delays. I don’t think this has been updated for Inform 2014, but it’s not listed as broken:
inform7.com/extensions/Erik%20Te … ource.html

Probably a more explicit example of how to set a timer and then react when it’s done is in Basic Real Time. This has been updated for the 2014 Inform:
github.com/i7/extensions/tree/m … 20Morayati

-Wade

Below is a very simple modification of the previous example: when “chime” is entered a timer is started for two seconds, after which a sound is played. As ever this is all pretty minimal - real code should check if timer events (and sound, for that matter) are supported by the interpreter.

[code]“Sound Experiment” by David Kinder

Include Glulx Entry Points by Emily Short.

Use direct event handling.

The Sound Stage is a room. “Enter ‘chime’ to play a chime.”

Sound of Chiming is the file “Chime1.aiff”.

Playing chimes is an action applying to nothing. Carry out playing chimes:
request timer events;
say “The chimes will start playing soon.”

Understand “chime” as playing chimes.

Glulx input handling rule for an independent of the player g-event:
if the current glk event is a timer-event:
cancel timer events;
play Sound of Chiming.

To request timer events:
(- glk_request_timer_events(2000); -)

To cancel timer events:
(- glk_request_timer_events(0); -)
[/code]

Thanks, that’s helpful!

Thanks! Is it enough to check for timer and sound support at the start of play, or does it need to be checked before each event, in case the player is restoring the game on another interpreter, or something? Or is it generally safest to use an extension with all the features built in? I noticed the Basic Real Time extension above has something special to handle restoring the game.

In the example code, would you do something like this to set the timer for different lengths of time?

[code]To request three-second timer event:
(- glk_request_timer_events(3000); -)

To request four-second timer event:
(- glk_request_timer_events(4000); -)[/code]