Skip to content
SirGFM edited this page Jun 21, 2016 · 5 revisions

Overview

The following image describe the overall structure of the synthesizer:

Architecture overview Blocks in white are either input or output of the synthesizer

Each module shall be released as a separated tools (usually called "offline" or standalone tools). The parser, for instance, will be bundled with the c_synth library, but will also be used on a tool to analyze the memory requirements for a given song.

On later versions, tools may support multiples output formats. Eventually, the encoder may support ogg vorbis and the compiler may support "fun platforms".

Parser

The parser is the entry point for the synthesizer. It takes an input, written on the library's own MML-based language, and parse it into tokens that the compiler may use to synthesize the song.

The language defines three objects:

Instruments

Describes how notes are played. It's composed of a base waveform and an envelop.

Envelop graph of amplitude x time This is only the note's envelope. Each instrument also has an volume envelop (which may be either a constant or linear volume). The final volume for each sample is actually: volume sample * note envelop * volume envelop

Each track keeps a local copy of their instrument. Therefore, even though loaded instruments are immutable, one can modify a instrument that was loaded into a track. Also, instruments may be loaded into track whenever desired (perhaps, reverting local modifications).

Songs/Tracks

Sequence of tokens used to synthesize a song. Each track has its own local instrument, which may be modified as desired.

During a track's parsing, there are a few tokens that may affect it:

  • Parser token: Whenever a new track starts to be parsed, default values for the note duration, its octave etc are loaded into the parser. Those values alter how notes are tokenized, but they aren't stored within a track's tokens. A slightly counter-intuitive effect caused by those tokens is that modifications (e.g., to the octave) done at the end of a loop will be ignored when the song jumps back to its start.

  • Track tokens: Modifies how notes are played. Those token may mainly affect a track's instrument, but their effect is permanent. This means that if a song repeats, care must be taken to make sure that the playing instrument is reloaded as soon as it goes back to the start.

  • Flow tokens: Those are used by the compiler to jump to another position in the track. Currently, there are only two tokens on this category: the repeat token (that marks the position within the track where it should continue, after finishing playing it) and the loop token (that marks the number of times and the segment that should be played). However, 'coda' and 'dal segno' tokens may be added later.

  • Note tokens: The note to be played and its duration.

Different from instruments, tracks aren't immutable. The compiler may operate on the track itself in a "non-destructive" way. Usually, it will simply modify flow tokens to count how many iterations should be done.

A song is nothing more than a collection of tracks.

Macros

c_synth macros are really similar to C macros. A macro defines sequences of tokens that shall be output whenever they it's parsed. Different from an instrument, a macro may be used to ease loading an instrument and playing a few notes with it.

This feature can be highly desired for percussion tracks, since they are usually defined by "single tone instruments" (e.g., snare, cymbal, tones, hi-hat) which are achieved by playing a specific note with specifics configurations.

Different from instruments, macros are temporary and only last until the parsing of the current track is complete.

Persistent memory

This region is used to store instruments and songs, as they are parsed and loaded into memory.

Compiler

The compiler takes a song in "tokenized form" and converts it to a playable format. Usually, the song is compiled into a playable bitstream, encoded in PCM (Pulse Code Modulation).

Note for future self: About sounds on the Sega Genesis/Megadrive

Seems like the m68k doesn't actually directly loads "samples" into its YM2612. The Z80 actually runs its own sequencer which writes the song to a SN76489 (a sound chip with 3 square waves and a noise generator) and, I'm guessing, to the YM2612...

Since this sequencer must be written per game, it should be an implementation of the compiler, and I wonder if it wouldn't be able to decompress songs... Maybe the m68k should decompress the song during loading screen/zones and just change some pointers/load some data to the Z80...

Reference: https://bigevilcorporation.co.uk/2012/09/03/sega-megadrive-10-sound-part-i-the-psg-chip/

Encoder

This module is only intended for offline use. It takes the song's bitstream and encode it into a new format, usually for exporting the song. One such format is the Waveform Audio File Format (WAVE).