ugBASIC User Manual

Audio and music support

This page explains how to use the sound capabilities of the retrocomputers. It will deal with simple audio effects and, more over, the use of music in ugBASIC.

Effects Notes Channels Play Instruments Music

Basic effects

Generally, the sound capabilities of a retrocomputer are a bit limited, but ugBASIC sound commands could operate independently from other routines (on many targets), so that they could never interfere with your programming. On the contrary, they should enhance your work in any way that you chose, acting as markers, adding realism, shooting, shocking or providing comic relief.

Audio, notes and sound effects can be used in an ugBASIC program. There are three common sound effects that can be called up by their own commands, and used for testing and punctuating your routines.



By making use of the internal chipset to simulate "white noise", or by sending random samples to any internal ADC, the BOOM command plays a realistic explosive sound effect. On many targets, or if DEFINE AUDIO ASYNC pragma is used and supported, this does not delay the program at all, so it may be necessary to use WAIT between successive explosions, or to create specific audio effects. Otherwise, on other targets or if you are using the DEFINE AUDIO SYNC, this will not happen. In any case, it is possible to give a duration (in milliseconds) for the audio effect.

For example, there codes are equivalent:

DEFINE AUDIO ASYNC
CENTRE "Thunderbolt and Lightning"
BOOM : WAIT 1000 MS: BOOM: CLS
CENTRE "Very Very Frightening"
WAIT 500 MS: BOOM


DEFINE AUDIO SYNC
CENTRE "Thunderbolt and Lightning"
BOOM 1000 MS: BOOM 500 MS: CLS
CENTRE "Very Very Frightening"
BOOM



On the other hand, the SHOOT command generates a (shorter) sound effect in exactly the same way as BOOM.

For example:
DEFINE AUDIO ASYNC
SHOOT: WAIT 1000 MS: SHOOT: PRINT "Ouch!"

DEFINE AUDIO SYNC
SHOOT: WAIT 750 MS: SHOOT: PRINT "Ouch!"



Unlike the built-in explosive sound effects, BELL produces a simple pure tone. To better explain the meaning of the parameter that can be given to the BELL command, it is essential to introduce at least a hint about the concept of frequency, "pitch" and note.


Every sound can be represented by a given frequency, basically an oscillation with a certain period. However, not all systems are capable of generating audio at any frequency, due to many factors and limitations. So there are some special frequencies that are, so to speak, "guaranteed" (or better, approximated), and they are called "pitch".


Each pitch is identified by a natural number, which goes from 0 to the maximum number of guaranteed frequencies. Only for convenience, the frequencies linked to the "pitch" are linked to those of the notes of a tempered scale, that are defined for eight (8) octaves.

A temperate scale is a way to divide the various octaves of music. Each octave is subdivided into 12 "elementary" intervals (tempered semitones) all of which have exactly the same amplitude. The amplitude of an interval corresponds to the ratio between the fundamental frequencies of the two notes (and not to the difference in frequencies). In this way twelve semitones cover exactly the interval of one octave.

OCT 0OCT 1OCT 2OCT 3OCT 4OCT 5OCT 6OCT 7
C012243648607284
C#/Db113253749617385
D214263850627486
D#/Eb315273951637587
E416284052647688
F517294153657789
F#/Gb618304254667890
G719314355677991
G#/Ab820324456688092
A921334557698193
A#/Bb1022344658708294
B1123354759718395

In summary: the entire musical representation is covered by 8 octaves of 12 semitones each, each semitone is associated with a specific pitch, which corresponds to the guaranteed frequency, as can be seen on the previous table. The "pitch" of this sound can be changed by adding a "pitch value" after the BELL command, ranging from 0 for a very deep sound, up to higher values, for an ultra high pitched sound.

With this example it is possible to listen to the tempered scale of the fifth octave:

DEFINE AUDIO ASYNC
FOR f=60 TO 71
   BELL f
   WAIT 1000 MS
NEXT

DEFINE AUDIO SYNC
FOR f=60 TO 71
   BELL f
NEXT

Another way to produce sound in ugBASIC is with the use of the SOUND command. This command can accept various parameters, depending on the use you want to make of it.

The simplest form is to reproduce a certain frequency for a certain duration:

SOUND 440, 1000 MS :'(reproduce a 440 Hz sound for 1 second)

Sometimes it can be useful to be able to reproduce a sound while doing other processing. In this case, you can omit the duration and the sound will continue until the next command or until it is stopped with the SOUND OFF command.

SOUND 440
FOR i=0 TO 10 : PRINT "OK!": WAIT 500 MS : NEXT
SOUND OFF

Sometimes it can be useful to reproduce frequencies on multiple channels, or "voices". The SOUND command also accepts a third parameter prefixed by the keyword ON, which is a bitmask with the mapping of the voices.

SOUND 440, 1000 MS ON %0010 (reproduce a 440 Hz sound for 1 second on voice 1)

This additional parameter with the voice is clearly available even if you do not indicate a duration, and this allows you to produce polyphony.

SOUND 440 ON %0001: SOUND 480 ON %0010
FOR i=0 TO 10 : PRINT "OK!": WAIT 500 MS : NEXT
SOUND OFF

Musical notes

The values from 0 to 107 that are used to control the pitch of the BELL sound correspond to the notes on the keyboard of a piano. The white key at the extreme left-hand side of the keyboard is known as "Bottom C", and corresponds to pitch value 0. Value 1 is the equivalent to the black note next to it, which is a C#, and so on up to “Middle C” at pitch value 6, then all the way up to 107.

In reality, grand piano keyboards run out of notes after 88, and most synthesizer keyboards have a lot less than that.

In Western music, notes are given their own code letter so that musicians can all refer to the same pitch when they try and play together. These letters repeat themselves after twelve notes, and each group of twelve is known as an “octave”.

To indicate a specific note (of middle octave) you can use the NOTE command, like NOTE C# or NOTE D. In order to indicate the octave, you can use the NOTE C4 annotation. So you can use the following command to sound a bell with A note:

BELL NOTE A4

Channels and voices

The retrocomputer produces sound like a river, and ugBASIC allows you to split this river into various separate channels, all pouring out at the same time, but each capable of individual control. These channels can be heard individually, or mixed together, or directed to the left and right creating stereo sound. They can also be individually increased and decreased in volume, or dammed up altogether. Obviously, it depends on the specific chipset capabilities if these channels can be given a different "voice", and each voice can be controlled in terms of volume and direction.

The VOLUME command controls the level of sound flowing through one or more channels, ranging from MIN VOLUME (complete silence) up to MAX VOLUME (ear-splitting), like this:

FOR level=VOLUME MIN TO VOLUME MAX
   VOLUME level
   BELL NOTE C4
   WAIT 500 MS
NEXT

Once the VOLUME level has been set, all future sound effects and music will be delivered at that level, across all four channels. In order to create "stereo" effects and perfect sound mixes, each of the voices needs to be adjusted independently from one another.

The volume of each voice can now be controlled by specifying voices and volumes, like this:

VOLUME 63 ON %0001
BOOM : WAIT 100 MS
VOLUME 5 ON %1110
BOOM : WAIT 50 MS
BELL 40 : WAIT 50
VOLUME 60: BELL 40

Playing notes

Patterns of individual notes can be played, allocated to any voice, given a pitch and delayed for pause, using just one PLAY command:

PLAY voice, note, delay

The voice parameter is optional, allowing notes to be played through any combination of the retrocomputer voices, and is set by the usual bitmap format. The note parameter uses the values from 0 to 107, or by using the NOTE annotation. The parameter delay sets the length of any pause between this PLAY command and the next instruction in the program, with a value of zero starting the note and immediately going on to the next command.

The next example demonstrates this technique, including stereo harmonies:

PLAY 40, 0 ON 1: PLAY 50, 0 ON 2
WAIT KEY
PLAY 50, 15 ON 1: PLAY 50, 15 ON 2
DO
   v = RND(5)
   p = RND(108)
   PLAY p, 3 ON v
LOOP

PLAY is not restricted to pure notes. It is possible to assign complex wave forms to voices, using the WAVE and NOISE commands, which are explained next. To stop the playing process, simply turn it off like this:

PLAY OFF

Instruments

Some audio chipsets have the ability to define the waveform of the sound that will be output, to make it look like an instrument. Others have the ability to use actual "samples", which will then be reproduced at certain frequencies. The ugBASIC language provides a set of primitives that allow you to take advantage of this feature.

The most useful (and easy) command is INSTRUMENT. This command allows you to modify the waveform of one of the voices, so that subsequent commands such as SOUND or PLAY modify the sound.

The syntax is quite easy:

INSTRUMENT $42 ON %0001 : ' Use the saxophone on voice 1

The instrument can also be indicated symbolically.

Playing music

Available on:
atari atarixl c128 c128z c64 coco coco3 coleco pc128op vic20

The ugBASIC music system allows soundtracks in background to be added to any program. Music can be created from a variety of sources, including MIDI and PSG files.

Play MIDI soundtracks

Available on:
atari atarixl c128 c128z c64 coco coco3 coleco pc128op vic20

The ugBASIC language is able to use directly the MIDI file format. This kind of file is converted into internal format (called IMF - Isomorphic Music Format), that is a format that the hardware is able to use almost directly. So, actually, the file inside the executable is IMF format and not MIDI.

MIDI files can be loaded using the LOAD MUSIC command:

soundtrack := LOAD MUSIC("some.mid")

Once load, they can be played anytime using the MUSIC command:

MUSIC soundtrack

The volume is controlled by MUSIC VOLUME, and speed (used during conversion) by MUSIC TEMPO. Individual music passages can be suspended by using the MUSIC PAUSE, and resumed by MUSIC RESUME. Moreover, it can be stopeed by MUSIC STOP instruction.

Play SJ2 soundtracks

Available on:
coco

The ugBASIC language is able to load the SJ2 files. The format consists of a 1-bit sample stream of samples for two independent voices, which can be played synchronously with the 1-bit DAC. The player is based on the highly optimized algorithm called "2 voice squarewave pattern", developed by Simon "invisibleman" Jonassen and adapted for ugBASIC. The audio card is properly emulated by the latest version of XRoar emulator.

The file can be loaded as:

soundtrack := LOAD("some.sj2")

Once loaded, they can be played anytime using the MUSIC ... SJ2 command:

MUSIC soundtrack SJ2

Since they are played synchronously, the tracks can't be suspended, resumed or stopped.

Play PSG soundtracks

Available on:
coco coco3 coleco pc128op

The ugBASIC language is able to load the PSG files with the target that has a SN-76489 audio chipset. For TRS-80 Color Computer 1/2 and 3 it means that a Game Master Cartridge should be attached to slot 0. The audio card is properly emulated by the latest version of XRoar emulator. For Olivetti Prodest PC128 it means that an external soundcard should be attached, like the one built by Dino Florenzi. The audio card is properly emulated by the latest version of DC MOTO emulator.

The file can be loaded as:

soundtrack := LOAD("some.psg")

Once loaded, they can be played anytime using the MUSIC ... PSG command:

MUSIC soundtrack PSG

Individual music tracks can be suspended by using the MUSIC PAUSE, and resumed by MUSIC RESUME. Moreover, it can be stopeed by MUSIC STOP instruction.

Any problem?

If you have found a problem, if you think there is a bug or, more simply, you would like something to be improved, write a topic on the official forum, or open an issue on GitHub.

Thank you!