Snack Time - Adding sounds to your program


Just for fun, lets teach the computer to talk.

At least, a little.

The Tcl/Tk program you downloaded from ActiveState comes with a bunch of extra software to add more features to the Tcl/Tk language. In Tcl, we call these packages. In other languages, they might be called libraries or DLLs.

The snack package lets us add sounds to a Tcl/Tk program. It was developed at the Kungliga Technical University in Sweden, and like so many computer things, it's available for free. It is always provided with ActiveTcl.

Computer programming commands are created in different ways. Commands like for and set are part of the Tcl language. The snack commands are added later and aren't always available to your program. We call this an extension to the Tcl/Tk language, since we've extended the available commands.

Because the snack command isn't part of the basic language, we need to tell the wish interpreter that we want to load this package.

The command to do this is the package command. The first argument to the package command is another command that tells the package command what we need it to do.

The package command can do several different commands, but the only important one for now is package require. That tells Tcl/Tk (and the wish interpreter) that we require a package, and we want the interpreter to find it and make it available to our program.

It looks like this:

package require snack

Once we've told the wish interpreter to find the snack package it will look on our hard drive until it finds the package, load it up, and then we can use the snack commands.

The snack command we need to use is snack::sound.

The snack::sound command is different from other commands we've used so far. It doesn't just do something, like the set or if commands. It creates a brand new command that can do stuff.

The snack::sound command creates a new Tcl command that can load and play a sound.

To create a new sound command with the snack package we use a command like this:

snack::sound mySoundCommand

Notice that the snack::sound command is all one word, and that there are two colons (:) in the center. The two colons are important. We'll discuss them in depth in later lessons. For now, just think of them as part of the command name, just like the other letters.

The second word (mySoundCommand) is the name of the new command we created.

The new sound command we just created can read a file that describes a sound. This file can contain .wav or .mp3 data (or even other less common sound data). The sound can be as short as a single word, or as long as the complete Beatles' collection.

We read a sound file with a the read argument to our new sound command like this:

mySoundCommand read mySoundFile.wav

Finally, our new sound command can play the sound it read with the play argument. That would look like this.

mySoundCommand play

You can record your own sounds if you want, but for now, just use these three files to tell the user that they guessed too high, too low, or that they've won.

You can download 3 .wav files with those words in them here:

Download the three wav files and put them in the folder where you keep the programs you've written so far.

Here's the commands that tell the wish interpreter to

# Find the snack package and load it
package require snack

# Create a new command named toHigh
snack::sound toHigh

# Read the too_high wave file
tooHigh read too_high.wav

# play the toHigh words
tooHigh play

Try typing those commands into Komodo Edit, save and run them. If your computer has a sound card and speakers, you should hear it say something. If you don't, check that you've got the speakers turned on, that the volume control isn't set to mute, or something like that.

You can use the snack::sound to create as many new sound commands as you need. But, like the buttons and labels, each sound command needs a unique name.

Try modifying the previous commands to read the too_low.wav and the youwin.wav files and see how they sound.

Here's the definitions for the snack::sound command and the arguments for the new command it creates:

Syntax: snack::sound soundName
Create a new snack sound Object.
soundName A name to identify the new sound

Here's the details about the read argument you can give the new command:

Syntax: $soundName read fileName ?-key option?
Read data into a sound object.
fileName The name of the file containing sound data
-fileformat Format of the sound file (mp3, wav, etc) (Default is wav)

And finally, the definition of the play argument:

Syntax: $soundName play
Play a sound.

We can add a few lines to the beginning of the game we wrote in the previous lesson to create 3 new sound commands and read the sound files. Then, instead of having the pop-up messages for Too High and Too Low, the computer will say the words.

The new version of the program looks like this:

# Find and load the snack package
package require snack

# Create the tooHigh command
snack::sound tooHigh 

# read the too_high.wav into the tooHigh command
tooHigh read too_high.wav

# Create the tooLow command
snack::sound tooLow

# read the too_low.wav into the tooLow command
tooLow read too_low.wav

# create the youWin command and read the .wav file
snack::sound youWin
youWin read youwin.wav

label .info -text "I've got a secret number. Can you guess it?"

# Grid this label so that it goes across 10 columns
#   one for each of the 10 buttons.
grid .info -row 1 -columnspan 10

# Calculate a secret number between 1 and 10
set secret [expr 1 + int(rand() * 10)]

# Build 10 buttons and grid them.

# Go through this loop 10 times.

for {set counter 1} {$counter <= 10} {set counter [expr $counter + 1]} {
  # Each pass through the loop, one of these if tests will be true
  #   and the proper command will be put in the cmd variable

  if {$counter < $secret} {
    set cmd {tooLow play}

  if {$counter > $secret} {
    set cmd {tooHigh play}

  if {$counter == $secret} {
    set cmd {youWin play}
  button .b$counter -text "$counter" -command $cmd

  # Grid the button we just created.
  #   Notice that we are using counter to see if the button matches
  #   the secret, as the text in the button, and as the column to
  #   grid this button on.
  grid .b$counter -row 2 -column $counter

Here's some other things you can try.

You can record your own messages if you've got a microphone (or a laptop with a built-in microphone).

On Windows, you can use the Sound Recorder. This program is under the Start/Programs/Accessories/Entertainment menu.

On Linux, you can use the krecord or audacity programs to record a sound.

Try recording some messages like "Much too high", and "Much too low",and modify your 1 - 100 number game to give hints like "Much Too High" if the player guesses more than 20 higher than the secret and "Much Too Low" if they guess more than 20 lower.

Try adding some background music to your game. All you need to do is create a new sound command, read in a music file, and start it playing.

There is a lot of free music available on the net. But be careful to only use music that's really free. As a rule, if the song is modern, it's not free.

One site that has only very old music that is out of copyright and completely free is Project Gutenberg.

Before you use music as the background in a game, you'll need to reduce the volume (so you can hear the game messages over the music.

Here's a link to a free music file that I've made quieter so you can use it as background music in a game. It's part of the William Tell overture, originally recorded in the early 1900s for a cylindrical Edison record.

Game Background Music

The important thing we learned in this lesson is that your program can create new commands while it's running. You can write a computer program that writes parts of itself.

The other points in this lesson are:

The snack package can do many things with sounds. If you want to do more with sounds, you can look at this snack page, or you can go on to the next game lessons.

Snack Page



Copyright 2007 Clif Flynt