Tik-76.115 Individual Project: Guinea Pig
$Id: gpSoundPlayer.html,v 1.7 1996/04/22 05:56:35 hynde Exp $

Sound Player's python interface

This document describes the python end of the Sound Player. The python end hides the underlying player and the player's interface protocol from the user and provides easy access to the player using objects and methods organized into a python module. The principal user of this module is the Test Logic module.

Contents


1 · Classes and objects

The sound player interface for python is implemented in the module gpSoundPlayer. In python it is loaded like this:
   import gpSoundPlayer
The module defines the classes and functions that provide an easy interface to the sound player. The module also defines some utility functions.

1.1 · SoundPlayer class

The sound player is represented by an instance of the SoundPlayer class that handles the communication with the sound player program. A new player object is created this way:
   p = gpSoundPlayer.SoundPlayer()
A connection to the player program is established with the connect() method of the player ohject (using default values):
   p.connect()
The player program is expected to be running at this time and waiting for a connection. Connect() may be given two arguments, a hostname and port number telling where to connect instead of the defaults, for example:
   p.connect('bekesy.hut.fi', 10000)
Alternatively, the launch() method can be used to automatically start the player program and connect to it:
   p.launch()
Launch() first forks a new process and then exec's the player program. Then the player module connects to the new player process with the connect() method. Launch() takes the sampling rate and number of output channels from the player's variables p.rate and p.channels. These can be set before using launch() to set the desired values.

See also: terminating the player

1.2 · Sample classes

The player.sample class defines the sample object and its methods. Samples have methods for all the operations that are defined in the interface protocol, such as play(), stop() and setvolume().

Before any new sample objects are created the sample class has to be told which player instance to use:

   gpSoundPlayer.sample.SoundPlayer = p
Samples created after that use that player for playing the samples. It is therefore, in theory, possible to have multiple players at one time each with it's own set of samples.

New sample objects are created by making instances of the derived classes gpSoundPlayer.filesample and gpSoundPlayer.nullsample.

2 · Loading and unloading samples

There are two types of samples that can be loaded: file samples and null samples. File samples are loaded from disk and are expected to be of allowed formats. Null samples are samples that contain only silence of specified length.

2.1 · Loading

File samples are created by calling the player.filesample class with the filename as a string argument. For example, to load the intro from MTV's Beavis & Butthead (assuming you have it):
   s1 = gpSoundPlayer.filesample('audiofiles/BBintro.aiff')
Now s1 is a new sample instance. Raw data samples can be loaded by adding two optional arguments:
   s2 = gpSoundPlayer.filesample('audiofiles/sample_data', channels, endian)
where channels is an integer telling how many channels there are in the sample and endian is a string, either 'LITTLE_ENDIAN' or 'BIG_ENDIAN', which specifies the byteorder of the data. Endian can be omitted in which case the endianess of the data is assumed to be the same as the host's.

Null samples are similarly created by calling the gpSoundPlayer.nullsample class with the length of the sample as argument:

   s3 = gpSoundPlayer.nullsample(44100)
where in this case, if the sampling rate were 44.1KHz, the sample s3 would be a one second sample of silence.

2.2 · Unloading

Samples are unloaded with the sample's kill() method:
   s1.kill()
The sample data is freed in the player and the sample is no longer usable. Deleting a sample object in python doesn't unload the sample (there were some problems).

A sample that has been killed can be reloaded with the reload() method:

   s1.reload()
After that the sample is again usable.

2.3 · Limitations

Filenames cannot contain double quotes (").

3 · Sample commands

There are methods for starting and stopping sample play, setting the volume levels and moving the sample pointer. In the following, s is an arbitrary sample object (or the class).

3.1 · Playing samples

Methods for playing samples are:
   s.start()
   s.start(s2, s3, ...)
   s.stop()
   t = s.play()
   t = s.play(s2, s3, ...)
   m = s.Play()
   m = s.Play(s2, s3, ...)
The s.start() command starts playing the sample and returns immediately. The start() method can be given any number of other sample ohjects as parameters. This means that the samples will be started at the same time.

s.stop() stops the sample. If the sample was not playing it has no effect.

s.play() plays the sample and returns after the sample has been played. It returns the time when the sample ended (struct timeval converted to a float). When more samples are given as parameters they are started at the same time, as in start(). However, the function returns when the sample s has been played. The parameter-samples may or may not have ended at that time. (This might seem strange but it is the way it is now). Other version of play() is Play() which returns immediately a message. This message can be used to wait for the reply to this message, ie. the notification that the sample has stopped. (Waiting for messages and other more advanced features will not be discussed at this point).

3.2 · Volume control

The sample's volume can be set individually for each channel in the sample. The method for setting the volume is:
   s.setvolume(vol)

   s.setvolume((chan, vol), (chan, vol), ...)
There are two alternative forms: The first sets the volume level of all the channels in the sample to vol (floating point number). The second form takes any number of (channel, vol) tuples where channel is the channel number and vol is the volume and sets the volumes of the channels accordingly.

Examples: 1. set volume of sample s1 (all channels) to 20dB below the samples normal level:
   s1.setvolume(gpSoundPlayer.dB(-20))
(the gpSoundPlayer.dB() is a function that converts decibels to the values the player wants.

2. set channels' volumes separately:

   s1.setvolume((0, 0.1), (1, 0.2))
which sets channel 0's volume to 0.1 (-20dB) and channel 1's to 0.2 (about -14dB).

3.3 · Output connections control

The output connections specify to which outputs the samples channels are connected to and with what weights. The method for setting the volume is:
   s.setvolume((chan, output, vol), (chan, output, vol), ...)
Setvolume() takes any number of (channel, output, vol) tuples where channel is the channel number, output is the output channel number and vol is the volume and sets the connections accordingly: Channel chan is connected to output channel output with weight vol. The meaning of the parameters are similar to those in the volume control.

3.4 · Pointer control

The sample pointer is the index of the next sample word played from the sound sample. Setting the pointer to 0 resets the sample to the start, etc. Methods for changing the pointers are (s is an arbitrary sample):
   s.setpointer(pointer)
   s.setpointer((channel, pointer), (channel, pointer), ...)

   s.movepointer(pointer)
   s.movepointer((channel, pointer), (channel, pointer), ...)

   s.set_initpointer(pointer)
   s.set_initpointer((channel, pointer), (channel, pointer), ...)

Where pointer is an integer number. The alternative forms work exactly the same way as with the volume control.

setpointer() sets the pointer to a value. movepointer() adds a value to the current sample pointer.

Setting the sample pointer to a negative value is allowed in which case the sample outputs silence until the pointer reaches zero and then begins outputting the sample data.

Set_initpointer() is used to set the 'initial pointer' of a channel. When the sample is stopped or ends the sample pointer is reset from this value. It can be used to set a delay before the sample starts (using a negative value for this pointer) or to start it from some point in the sample. When the sample is set to loop, the sample pointer is reset to 0 when the end of sample is reached regardless of the value of the initial pointer.

3.5 · Looping samples

By default all samples are one-shot samples. A sample's looping status can be set with the looping() method. It takes one parameter and sets the sample to loop if the value was true (in python's sense) and to not loop if the value was false. Example:
   s1.looping(1)

   s1.looping(0)
The first one turns looping on, the second turns it off. To play the looping sample, use the start() method and to stop, use stop(). Using play() with a looping sample is considered illegal (play() returns when the sample stops. When does a looping sample stop?)

4 · Output control

The setvolume() method of the player object is used to set the output level of the player (p is a player object):
   p.setvolume(vol)
   p.setvolume((ochan, vol), (ochan, vol), ...)
The method is very similar to the sample volume control, except that there is a player involved (not a sample) and the channel number is now output channel number. This command would be used to set the output to the 'most comfortable listening level' at the beginning of the test.

5 · Terminating the server

The server is terminated with the player's quit() method:
   p.quit()
This tells the player to terminate and then closes the connection. If the player was started with the launch() method, the module wait's for the player process to exit before returning. A new connection can be established with the connect() or launch() methods.

6 · Error handling

When errors occur, the functions and methods generally raise an exception in the spirit of python's exception handling. Thus all python's exception handling systems are available, such as the try/except construct.


· Sound Player Index · Document index · Guinea Pig ·