SASS
A Music-Oriented Programming Language

Contents

·         Introduction

o        What is SASS?

o        Supported Targets

·         Linguistics

o        Constants

o        Comments

o        Timing

o        Macro Instruments and Sound Effects

o        Music Tracks

 

 

♫ Introduction ♫

 

What is SASS?

Sound ASSembly is an audio programming language designed for use with embedded platforms, particularly game consoles.

 

As the capabilities of SASS targets may vary wildly, the SASS standard only encompasses basic macro instrument structure and music script decoding (note on, note off, loops, calls, etc.). Many of the richer features (and inconvenient limitations) are platform-specific, so it’s best to check the manual of your target’s SASS compiler for more details.

 

SASS may be viewed as an alternative to existing music languages such as MML (Music Macro Language) and is a derivative of Atari’s SPL (Sound Programming Language). Users coming from an MML background should pay careful attention to the macro instrument structure, music blocks, and timing as these differ significantly from how MML is usually written.

 

SASS does not have to be exclusively written by hand. Music scripts can be generated from a MIDI source using MID2SASS, which may serve as a helpful starting point for the language.

 

 

Supported Targets

SASS is available for use with the platforms listed below, more details are available in the each of their drivers’ respective documentation.

 

Platform

Type

Sound Driver

Microsoft Windows

Wavetable

BupBoop

Atari Lynx

PSG + PCM

HandyMusic

NEC TurboGrafx-16

WSG + PCM

HuSound

 

 

♫ Linguistics ♫

 

Constants

Values may be entered in decimal, hexadecimal, and binary using the following syntax…

 

       32            ; Decimal (No prefix)

       -32           ; Negative Decimal (Leading “-”)

       $20           ; Hexadecimal (Leading “$”)

       %100000       ; Binary (Leading “%”)

 

As most SASS targets use mixed precision values (i.e. 16.16, 16.8, or 8.8), fractions can be declared after a decimal point…

 

       32.16         ; Decimal

       -32.16        ; Negative Decimal
       f32.0625      ; Float

       f-32.0625     ; Negative Float

       $20.10        ; Hexadecimal

       %100000.10000 ; Binary

 

The fraction’s format must match that of its leading integer - this can be somewhat convoluted for decimals, as a value of 31/2 would be written as 3.128 in 16.8 precision or 3.32768 in 16.16. Compilers which support the gfloat parameter can optionally disable this behavior.

 

 

Comments

Follow a semicolon “;” and encompass the remainder of the current line…

 

       ; This is a comment spanning an entire line

       as4 60 ; Comments may also follow commands and values

 

 

Timing

All values quantifying time are given in driver ticks, the exact rate of which is dependent upon the current target and driver implementation. Most targets use a 60Hz base tick, using this assumption we can write the note sequence below…

 

       f.3 60        ; F-Natural 3rd octave, one second

       rest 20       ; Note off and rest, 1/3 second

       as5 40        ; A-Sharp 5th octave, 2/3 second

 

If the driver tick was 240Hz, the example above would have to be changed to…

 

       f.3 240       ; F-Natural 3rd octave, one second

       rest 80       ; Note off and rest, 1/3 second

       as5 160       ; A-Sharp 5th octave, 2/3 second

 

 

Macro Instruments and Sound Effects

Instruments are intended for use in music tracks under the control of the driver’s parser, whereas sound effects are spontaneously dispatched by the game software. Both feature unique attributes based upon these applications - but are mostly identical during processing. Drivers usually merge both of these into one entity as macros or patches and their declarations reflect this unity…

 

name priority                            ; <- Label

       volume value                      ; <- Header

       frequency value

       tuning value

       {

              rest ticks                 ; <- Body

 

              volume value

              frequency value

              loop count

                     ; (Loop Body)

              endloop

 

              noteoff

              end

       }

 

All declarations begin with a label, which contains a name and priority (if a sound effect). Names consist of one or more characters (such as select_item, explosion, or poof) and are used to select instruments in music scripts or generate equates for sound effects. Priorities are only used for sound effects and specify their importance relative to both music tracks and other sound effects - higher priorities win out during channel contention. Instruments have no inherent priority as this is set within their attached music track.

 

Following the label is a header; this specifies the initial state of the instrument or sound effect through various parameter adjustments. Nearly all of these are platform specific, so it is best to check the documentation for your target’s driver. Common parameters are volume, frequency, and tuning.

 

After the header is the macro body, which specifies how the sound will change over time and is composed of one or more note, flow control, and parameter adjustment commands within { Curly Braces }.

Select targets support multi-channel macros, these resemble a normal sound effect definition but feature a { Curly Brace } region enclosing one or more headers and bodies after the label…

 

name priority                            ; <- Label
{

       volume value                      ; <- 1st Channel Header

       frequency value

       {

              rest ticks                 ; <- 1st Channel Body

              loop count

                     ; (Loop Body)

              endloop

              end

       }

       volume value                      ; <- 2nd Channel Header

       frequency value

       {

              rest ticks                 ; <- 2nd Channel Body

              end

       }
}

 

Commands are divided into three types : note, parameter adjustment, and flow control. Note commands encompass delays and region tagging. Parameter adjustments control how the instrument or sound effect will create its sound - these are the only commands which can be used in the header. Flow control commands include loops and end markers.

 

Some commands available to instruments and sound effects are listed below…

 

o        noteoff,n : note off
Only applicable to instruments - tags the region following it as the note off (or release) portion of its script. If an instrument is playing and the music script hits a rest command, this region of the script will start decoding on the next update cycle.

       ...           ; When a rest command is encountered in

       noteoff       ; the music script while an instrument

       rest 8        ; is playing, the instrument will start

       end           ; executing the portion of its script

       ...           ; directly following the noteoff command.

 

o        rest,r ticks : rest
Pause for the specified number of ticks before advancing to the next command, the instrument or sound effect will continue to play during this time.

       rest 14       ; Wait 14 ticks

       end           ; Stop



o        volume,v value: set the current volume

o        frequency,f value: set the current frequency offset

Patch volume and frequency controls (platform-specific).

o        tuning,t value: set instrument tuning
Only applicable to instruments, specifies the tuning / waveform period (platform-specific).


o        loop,l count : loop start
Specifies the start of a loop region, and the number of times it will repeat. If negative values are used, the loop will continue indefinitely.

       ...
      
loop -1                     ; Repeat outer loop forever

              loop 10              ; Inner loop 10 times

                     rest 6

              endloop

       endloop

       end                        ; Stop

 

o        endloop,el : loop end
Specifies the end of a loop region.

       ...
      
loop -1                     ; Repeat forever

              rest 18

       endloop                    ; Marks end of above loop

       end                        ; Stop

 

o        end,e : sound end
Halts decoding of the instrument or sound effect, then frees its pertinent channel(s).

       ...
      
end                        ; Stop

 

 

Music Tracks

Each music track consists of one or more script blocks which contain commands representing how and when to play instruments or dispatch samples and sound effects. An example of their format is below…

 

name priority                            ; <- Main Block

{

       using instrument

       priority value

 

       call name

       loop count

              ; (Loop Body)

       endloop

 

       rest ticks

       as3 ticks

       wait ticks

       end

}

 

name                                     ; <- Sub Block

{

       ...

       return or break

}

 

 

All blocks start with a label, which at minimum contains the block’s name. Each music track must contain a single main block which is the first to be played and also contains an initial priority in its label. Names consist of one or more characters used to identify the block while priorities are an integer value. Higher priorities indicate a more important track relative to sound effects - using a priority of zero will cause the track to never decode.

 

Following the label, and enclosed between two { Curly Braces } are one or more commands composing the block body. As with macro instruments, the music command set may be divided into three categories : notes, parameter adjustment, and flow control. Note commands specify when to play particular note (key on and key off). Parameter adjustments select which instrument is used and how it will be played. Flow control commands change how the script will decode - such as loops, calls to different blocks, and termination of playback.

 

Some commands available to music scripts are listed below…

 

o        notes
A key on event is specified with a three letter note command followed by a duration in driver ticks. The note command’s three characters are arranged as…

           
( Letter ) ( Natural / Sharp / Flat ) ( Octave )

Note letters may be
c, b, d, e, f, g, and a. Natural, Sharp, and Flat for the given note may be specified using “.” (period), “s”, and “b” respectively. The octave number may range from 0-9.

       ...

       c.4 60        ; C-Natural 4th octave, 60 ticks

       rest 10

       bs4 20        ; B-Sharp 4th octave, 20 ticks

       rest 10

       bb2 80        ; B-Flat 2nd octave, 80 ticks

       rest 10

       ...

 

o        rest,r ticks : rest
Acts as a key off event if following a note, or a general delay if used on its own.

       ...

       as4 20

       rest 30       ; Key off, wait for 30 ticks

       ...

       rest 60       ; Wait for 60 ticks

       ...

 

o        frest,fr ticks : force rest
Always acts as a key off event regardless of whether it follows a note. This can be used to repeatedly snap an instrument back to the note off section of its script.

       ...

       as4 20

       frest 30      ; Key off, wait for 30 ticks

       ...

       frest 60      ; Key off, wait for 60 ticks

       ...

 

o        wait,w ticks : wait
Pauses decoding for the specified number of ticks. Useful for delays where note off behavior is not desired.

       ...

       wait 60       ; Wait for 60 ticks

       ...



o        using,u instrument : set current instrument
Select the instrument used for playing notes, applies only to the current channel.

       ...

       using piano   ; Using instrument “piano”

       g.3 20        ; The following notes will be played with

       rest 10       ; “piano,” with each note request

       b.3 20        ; specifying a key on, and each rest

       rest 10       ; indicating a key off.

       a.3 20

       rest 10

       ...

 

o        priority,pr value : set track priority
Adjust the current priority of the music track, this can be used to give sections of a piece more or less importance relative to sound effects. Setting the priority to zero will cause the track to cease decoding.

       ...

       priority 120  ; Set priority to 120

       ...

       priority 240  ; Set priority to 240 (higher)

       ...



o        loop,l count : loop start
Specifies the start of a loop, and the number of times it will repeat. If negative values are used, the loop will continue indefinitely.

       loop -1                     ; Repeat outer loop forever

              loop 10              ; Repeat inner loop 10 times

                     as4 20

                     rest 20

              endloop

              gs3 30

              rest 20

       endloop

       end                        ; Stop

 

o        endloop,el : loop end
Specifies the end of a given loop.

       loop -1                     ; Repeat forever

              fs4 20

              rest 30

              call drumSolo

       endloop                    ; Marks end of above loop

       end                        ; Stop

 

o        call,c label : call script block
Begin decoding a given script block with the name specified by label.

       ...

       call pianoSolo       ; Call the script block below

       ...

}

 

pianoSolo

{

       ...

       return

}

 

o        return,rt : return from called script block
Resume decoding from where a given script block was called.

       ...

       call pianoSolo

       ...

}

 

pianoSolo

{

       ...

       return        ; Resume decoding after “call pianoSolo”

}

 

o        break,b : pattern break
Returns all music tracks to the lowest entry in their call stack. Effectively, all tracks will be snapped back to the “main” script if they’re not already there.

mainTrack 120

{

       ...

       call pianoSolo

       ...

}

 

pianoSolo

{

       ...

       call drumminThang

}

 

drumminThang

{

       ...

       break         ; Resumes decoding after “call pianoSolo”

}

 

o        end,e
Stops decoding of the music track and frees the channel.

       ...

       end           ; Stop