Thanks to the hard work done a number of people, its never been so easy to add decent sound to your programs as now. If you have a Qx0 or QPC2 you can use the SMSQ/E Sample Sound System (SSSS - shortened here to SSS, to encompass Qdos Classic) to play sound samples and even real music. This can make a big difference to the fun and usability of your programs.
Here I present a few simple routines that you can merge into your own programs directly, or just take a look at, to get an idea of how easy it can be to produce your own. These routines take into account that you may want your programs also to be able to run on platforms that dont have the supporting hardware, in which case they fall back on the familiar BEEP.
All you need in addition to the platforms mentioned (QPC2 must be V3.20 or later) are Wolfgang Lenerz'es Soundfile toolkit, which you can download from the Internet (contact details below) and some sound samples.
For distributable programs I prefer the Soundfile toolkit as it can be compiled in with the code, whether you use Turbo or Qlib. Simon Goodwin's sound device is more versatile, but needs to be loaded residentially at boot time or at least before starting your program.
Sound samples are a different matter. Until someone creates an online sound sample library, you will have to filch them from other programs (for example from the game D-Miner, available off my website) or record and/or convert your own. (How? Download Jonathan Hudson's Qdos port of SOX to convert standard .wav files to the ub format, or search for and download a Windoze compatible version of SOX on the Internet and use that.)
Ok, so lets get our hands dirty. My comments normally describe the code block immediately above, unless otherwise stated:
1 REMark $$asmb=win1_snd_sound_bin,0,10 2 :
If you want to compile the program with Qlib and include the soundfile toolkit with the code, you need this line. The corresponding Turbo directive is:
1 REMark %%win1_snd_sound_bin,0,10 2 :
You dont need to compile a separate version for non-SSS platforms as, provided you dont call any of the procedures in the toolkit, it wont error. The routines shown here take care of that for you.
3 REMark Test for presence of Sampled Sound System 4 TstSSS 5 :
One of the first things to do is to determine whether the SSS is present and set a switch accordingly. I use two global program switches relating to sound:
1) ssspresent can be true of false depending on whether the SSS was detected or not. This switch is set inside the TstSSS procedure.
2) sound is used by the sound subroutines to determine whether the user wants sound or not.
6 sx$ = '_ub' : REMark Sound file extension 7 sd$ = 'ram1_snd_': REMark Sound file folder 8 :
Initialise some variables used in the sound routines. Better have them up front where they can be easily seen and altered, rather than buried somewhere deep inside your program.
9 game = 0: win = 1: REMark Some dummy game variables 10 RANDOMISE DATE 11 :
Ive devised a very silly "game" to help illustrate usage.
12 REMark User input or config file determines sound on/off 13 snd = YesNo('Do you want sound') 14 SetSound snd: REMark Switch sound on/off 15 PRINT 'Ready to rock' 16 Ping 'ok': PAUSE 50: REMark Allow time to display sound and text 17 :
Its always a good idea to give the user the choice of having sound or not. SetSound sets the global program sound switch to on or off. If sound is wanted, it also sets the switch to the best available sound. Finally Ping gives a confirming noise if sound is on (see below)
18 REMark Your program goes here. Eg.. 19 : 20 CLS 21 REPeat main 22 PlayGame 23 IF game = win THEN 24 PRINT 'You win :o)' 25 Ping 'win' 26 ELSE 27 PRINT 'You loose :-(' 28 Burp 'loose' 29 END IF 30 IF NOT YesNo("Another game"): EXIT main 31 END REPeat main 32 Ping 'bye' 33 :
The main program loop simulates a game. If you "win" it plays the "win_ub" sound sample, otherwise it plays the "loose_ub" sound sample. Thats really all there is to it! The rest is just detail!
Ping and Burp take a filename parameter which means you can re-use them to play different sound samples, but they fall back on only two kinds of beep: 'Nice beep' and 'Bad beep'. But this is a simplification for the purposes of this demonstration. If you know how to be creative with BEEP, you could do things differently and very much better. The point is that you can follow any action with a sound, as shown. Every click on a button could produce a different sample sound and fall back on a different beep if you wish.
Note: When storing sound samples in a library it is a good idea to group them and give them evocative names such as 'quack' or 'gunshot1'. However, when you use them in a program it is better to rename copies of them according to their function in the program. This makes the program logic clearer and also allows the user to replace the default sounds with his own selection.
34 DEFine PROCedure PlayGame 35 REMark Dummy game routine 36 game = RND(0 TO 1) 37 END DEFine PlayGame 38 :
Well, that was your free game ;o)
39 DEFine FuNction YesNo(txt$) 40 PRINT txt$; ' <Y/n>? '; 41 IF INKEY$(-1) INSTR 'y' & CHR$(10): PRINT 'Y': RETurn 1 42 PRINT 'N': RETurn 0 43 END DEFine YesNo 44 :
Here follow the sound routines:
45 REMark Sound routines 46 : 47 DEFine PROCedure SetSound(s) 48 IF s THEN 49 IF ssspresent: sound = 2: ELSE : sound = 1 50 ELSE 51 sound = 0 52 END IF 53 END DEFine SetSound 54 :
SetSound 0 turns the program sound off, while SetSound 1 turns sound on. It also determines the level of sound available to the program; either BEEP or SSS. All it is is a logical switch in a wrapper for convenience, as the option of changing the sound status should be available to the user at any time.
55 DEFine PROCedure Ping(nm$) 56 REMark Nice sound 57 IF sound = 2 THEN 58 IF FTEST(sd$ & nm$ & sx$) = 0 THEN 59 KILLSOUND: SOUNDFILE sd$ & nm$ & sx$ 60 ELSE 61 BEEP 999, 2 62 END IF 63 ELSE 64 IF sound: BEEP 999, 2 65 END IF 66 END DEFine Ping 67 : 68 DEFine PROCedure Burp(nm$) 69 REMark Bad sound 70 IF sound = 2 THEN 71 IF FTEST(sd$ & nm$ & sx$) = 0 THEN 72 KILLSOUND: SOUNDFILE sd$ & nm$ & sx$ 73 ELSE 74 BEEP 999, 255 75 END IF 76 ELSE 77 IF sound: BEEP 999, 255 78 END IF 79 END DEFine Burp 80 :
The logic of Ping and Burp is:
If sound is off: do nothing
If sound is on then
If SSS available then
If the file exists: play sample sound
In all other cases just beep
81 DEFine PROCedure TstSSS 82 LOCal adr 83 REMark GLOBal ssspresent 84 REMark Test for presence of Sampled Sound System 85 REMark V0.01 pjwitte 2oo5 86 : 87 adr = ALCHP(26) 88 POKE_L adr + 0, HEX("43fa0016"): REMark lea.l result,a1 89 POKE_L adr + 4, HEX("26780070"): REMark move.l exv_i4,a3 90 POKE_L adr + 8, HEX("0cab5353"): REMark cmp.l #sss.flag,-8(a3) 91 POKE_L adr + 12, HEX("5353fff8") 92 POKE_L adr + 16, HEX("57e90001"): REMark seq 1(a1) 93 POKE_W adr + 20, HEX("7000") : REMark moveq#0,d0 94 POKE_W adr + 22, HEX("4e75") : REMark rts 95 POKE_W adr + 24, 0 : REMark ds.w 1 96 CALL adr 97 ssspresent = PEEK_W(adr + 24) 98 RECHP adr 99 END DEFine TstSSS 100 :
TstSSS is the only little awkwardness that remains, and hopefully it will one day be redundant: There is no easy and documented way offered by the OS of determining whether the Sampled Sound System is available or not, so we have to resort to a bit of jiggery-pokery. All this routine does is check whether it can find the SSS flag at the documented location just above the interrupt server, and set the ssspresent switch accordingly.
The program and associated sound samples can be downloaded here.
Have fun!
©pjwitte November 8th 2005
D-Miner can be found here
The soundfile toolkit can be found at Dilwyn's QL repository
The Qdos version of Sox and Simon Goodwin's sound device and a collection of sound tools - including samples - can also be found there.