intfiction.org

The Interactive Fiction Community Forum
It is currently Sat May 18, 2013 8:00 am

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Thu Feb 02, 2012 3:05 pm 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
As promised, I've made some progress on the websound extension for Web UI. Right now it supports most of the attributes of the HTML TADS sound tags: src, layer, repeat, volume, sequence, interrupt, and cancel.

Layers are only supported to a limited extent: there are four of them and they all work the same way. This should be mostly right, except for ambient; I need to ask a few clarifying questions of the experts to understand what that one is supposed to do.

Fades are not supported at all. This may be sheer ineptitude on my part but I can't seem to get an mp3 hosted online to start playing instantly, much less perform incremental volume changes on the audio with sub-second precision. Local Web UI play is a different matter and probably could support fades.

The most significant restriction at the moment is that large mp3s don't work well in the browser, when served out of the .t3 file. The session becomes unresponsive until the sound is loaded. This looks like an interpreter or server bottleneck rather than a problem with the sound code. The workaround is to put the mp3s online as separate files, and link to those files directly rather than to internal game resources.

For example:
Code:
#ifdef TADS_INCLUDE_NET
"<sound src=\"http://example.com/mp3/test.mp3\" layer=\"foreground\"/>";
#else
"<sound src=\"res/ogg/test.ogg\" layer=\"foreground\"/>";
#endif


Given all that, if it's still of interest, you can get the latest websound snapshot. Unpack the files into your project folder and add the websound library to your Makefile at the end of the sources list.

Quote:
## sources
-source tadsnet
-lib system
-lib webui
-lib adv3/adv3web
...
-source myfile
-lib websound


This new module follows the webui conventions and is much less of a hacky abomination than the last version.


Top
 Profile Send private message  
 
PostPosted: Thu Feb 02, 2012 3:39 pm 
Offline
User avatar

Joined: Tue Apr 20, 2010 2:48 pm
Posts: 680
bcressey wrote:
Layers are only supported to a limited extent: there are four of them and they all work the same way. This should be mostly right, except for ambient; I need to ask a few clarifying questions of the experts to understand what that one is supposed to do.

Basically it's for deciding what not to play on implementations that can't play all layers at once. In case you were not aware of this piece of documentation:

http://tads.org/t3doc/doc/htmltads/sound.htm

(Scroll down to the "Sound Architecture" section.)


Top
 Profile Send private message  
 
PostPosted: Thu Feb 02, 2012 3:45 pm 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
From the random attribute description on that page:

Quote:
The RANDOM attribute lets you specify the probability of playing a sound in the ambient layer. Usually, you will want a sound in the ambient layer to be played randomly from time to time; this attribute specifies the probability that the sound will be played at any given time. This attribute takes a value from 1 to 100. A low value makes the sound play infrequently; a value of 100 causes the sound to play at every opportunity (i.e., whenever another sound in the same layer isn't playing).


The "from time to time" part is what I find ambiguous. Does the ambient layer try to find something to play every second? Every minute?

Put another way, if a sound has a random attribute of 1, that should mean it has a 1% chance to play in some interval of time. What interval do you use in QTads?


Top
 Profile Send private message  
 
PostPosted: Thu Feb 02, 2012 4:05 pm 
Offline
User avatar

Joined: Tue Apr 20, 2010 2:48 pm
Posts: 680
The interval is handled by the HTML subsystem (QTads only provides the timer interrupt API implementation so that the subsystem can use them.) Reading htmlsnd.cpp, CHtmlSoundQueue::on_timer(), suggests an interval of one second. CHtmlSoundQueue::maybe_start_sound() contains the code that makes the decision when to play the next sound.

So a 1% probability would play the sound every 100 seconds on average, and a 100% probably would play it every second. Note the "on average". It doesn't count how many seconds have passed. It calculates the probability every time and uses that to decide whether to play it or not. It has no memory of previous random probability outcomes.


Top
 Profile Send private message  
 
PostPosted: Thu Feb 02, 2012 4:07 pm 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
Perfect, that's what I needed to know. Thanks!


Top
 Profile Send private message  
 
PostPosted: Thu Feb 02, 2012 4:32 pm 
Offline
User avatar

Joined: Tue Apr 20, 2010 2:48 pm
Posts: 680
Btw, the code suggests (well, tells actually) that every sound in the sequence gets its own probability if the previous one didn't score a high enough outcome. So that means that if the sequence contains 100 sounds, and the requested probability of each one is 1%, one of the sounds will almost always play. Each sound in the sequence can have a different probability though. So you might get one sound with a RANDOM value of 10 and another one with 30. If the first sound fails the 10% outcome, then a 30% outcome is tried for the next sound. And so on until a sound passes the check, or all sounds have been tried.

The actual code:

Code:
/*
 *   Check this sound for randomness.  If it has a random start
 *   probability, randomly decide whether to start it; if it fails,
 *   move on to the next sound.
 */
orig_nxt = nxt;
for (;;)
{
    /* if this one isn't random, start it immediately */
    if (nxt->get_random_start() == 0)
        break;

    /*.
     *   choose a random number from 0 to 100 - if it's less than the
     *   start probability, start the sound, otherwise skip it for now.
     */
    if ((rand() % 100) <= nxt->get_random_start())
        break;

    /*.
     *   move on to the next sound, wrapping to the start of the queue
     *   if we reach the end.
     */
    nxt = nxt->next_;
    if (nxt == 0)
        nxt = first_entry_;
       
    /* if we've looped, we don't want to start anything now */
    if (nxt == orig_nxt)
        return;
}


Top
 Profile Send private message  
 
PostPosted: Thu Feb 02, 2012 7:58 pm 
Offline

Joined: Tue Apr 27, 2010 1:02 pm
Posts: 797
Great, that was helpful. I've added support for the random attribute and the ambient layer works properly now.

Now I just have to figure out what's going on with the bundled MP3s.


Top
 Profile Send private message  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group