wcnt logo & demo sound

Compilation and installation Top

Use the download link on the right to download wcnt-1.25.tar.bz2. Once you have the source archive, type the following commands to extract and build wcnt:

tar -jxf wcnt-1.25.tar.bz2
cd wcnt-1.25
su root "install wcnt /usr/local/bin"

Note that the last command requires you to have access to the root password. If this is not possible, you can copy wcnt to a place that is in your user command search path, or create a symlink to it.

Experienced Linux users who frequently compile programs from source should check the Makefile that the compile options are within their agreement. It is very simple to change them.

Now that wcnt has been compiled, you can create the examples, although you can do this before compiling and it will compile first.

make examples

The wav files produced by the examples are located in the examples directory. Each example produces a wav file of the same name.

Command Line Options Top

wcnt has several command line options. The command wcnt, issued without any options at all will display a list of the options for you.

These options process a wcnt file and if no errors occur run the synth generated to produce the audio output files.

wcnt filename.wc
wcnt --verbose filename.wc

To display the wcnt file identifier (that which should be on the very first line of a wcnt file) use

wcnt --header

These options will display a list of all the module types you can create, and specifying a module name after the option will display a definition of that module which can be copied into a text editor and edited to your satisfaction.

wcnt --module-help
wcnt --module-help modulename

These options display a list of stand-alone data objects which can be created. Data objects do not act like modules, but they are used by modules to define certain characteristics the module is to employ. There are two types of data objects in wcnt, the first are defined outside of a module definition, and can be used by more than one module. The second are defined inside a module definition as an integral part of the module, and cannot be used by any other module. Examples of stand-alone data objects are riffs and wavfilein. Examples of in-module data objects are, track for the sequencer, and envelope for the adsr.

To display a list of stand-alone data objects:

wcnt --data-object-help
wcnt --data-object-help dataobjectname

These options display compatible outputs, and the module they are contained in, for the input type specified on the command line.

wcnt --input-help inputname
wcnt filename.wc --input-help inputname

The first option displays a list of all outputs from all possible modules which are compatable with the input specified. Note that it is not neccessary to enter the module which the input is from, and doing so will cause an error message. The second option tells wcnt to limit the list of outputs to those available from the modules defined in a .wc file.

Here are some miscellaneous options:

wcnt --sample-info samplename.wav
wnct --note-info notename
wcnt --freq-info frequency samplerate

The first option displays header information about the wav file, if it stereo or mono, if it is 16bit so that wcnt can read it, and the length in samples, and seconds. The second option converts a note name to a frequency. An example note name is c#-1, another is f0. The third option converts a frequency to a step size of degrees per sample. More on that later.

wcnt .wc files Top

A .wc file is a plain text file in which module and data object definitions are placed. The extension .wc is not neccessary, but used to help to identify the file in directory listings.

The first mandatory part of a .wc file is the identifier. This is where wcnt decides if it will read the file or not, so the very first line must be


The identifier is also used to mark the end of a .wc file. If the second identifier is not found, wcnt will stop and display an error message, which may not make any sense.

Next in the .wc file should be header information.

samplerate 44100
bpm 120
signature 4/4

Again, wcnt will exit if it does not get it. The samplerate value sets the global samplerate which all modules operate at, and also the samplerate at which any .wav files written, will playback at. The bpm and signature have to be set even if there are no modules for which they will be relevant.

The header information can be in a seperate file. To use this feature, remove the header information, and place it in another plain text file. The file does not require an identifier in it, but wcnt is fussy about the placement of the information. The first three lines of that file must be the three lines above.

To use a seperate file for header information, do the following

header filename.wc

Comments Top

Comments are useful at times. A typical comment takes the form

// I am a media sound bite, do and think as I say!
// blah, blah, blah. (what a pile of cak - ed)

Thankfully, wcnt skips such demands. The // characters tell wcnt to skip to the next line to continue reading. Comments can only be placed at the end of a line, or seperate lines. The following illustrates incorrect and correct usage of comments

// comment will be read as username:
osc_clock // main osc_clock

// correct form:
osc_clock osc1 // main osc_clock

// comment will be read as output of sequencer1:
in_trig sequencer1 // connect to sequencer1
// correct form:
in_trig sequencer1 out_note_on_trig // connect to sequencer1 out_note_on_trig

Names Top

When naming a module or data object in a .wc file, you can use any normal ascii character for the name, except for the dot . character. The . character is reserved for use in the names of grouped modules only. See the page on grouping for more on that.

There are only two reserved words you may not use to name a module or data object, and these are editlist and off.

The name of a module or data object immediately follows the module or data object type name, and the name is also used to terminate the definition.

Stopping wcnt Top

In order for wcnt to stop executing the synth created from a .wc file, the wcnt_exit module is used. The wcnt_exit is the only mandatory module, and there cannot be more than one of it.

    in_bar time1 out_bar
    exit_bar 4

The definition contains the following information. The module type is wcnt_exit, it's user name is exit_module. It has one input, in_bar, which is connected to an output from a module with a user name of time1. The output used from that module is out_bar. It has one parameter exit_bar set to 4, which means stop at the beginning of bar 4. Bar 0 is the first bar, so four bars are processed.

Be warned that all inputs in wcnt can be turned off, and doing so in the wcnt_exit module would require a forced kill. The best place for the wcnt_exit module is at the end of a .wc file.

A forced killing of wcnt during the writting of any wav files prevents them from being closed properly, and left without wav header information.

Numbers in wcnt Top

Suppose you defined your wcnt_exit module like this:

    in_bar time1 out_bar
    exit_bar 4.5

It seems reasonable and logical enough, exit half way through the fifth bar (remember bar 0 is the first bar). Except that the output out_bar from the time_map module outputs integer (whole) numbers, and the exit_bar parameter only accepts integer numbers.

When wcnt is told to read an integer number, and that number is a floating point number, it reads the number up to the decimal place. The decimal places are left unread.

The example above generates the error message

In module wcnt_exit_module, expected definition termination wcnt_exit_module, got .5 instead.

Beware of similiar messages as at first glance nothing in the definition appears incorrect.

Using the timer Top

There are two module types that are generally used to provide an output for the wcnt_exit module to use, timer, and time_map (which is explained in the sequencing section). The timer can be used when creating a wav file of a specific length in seconds.

        time seconds 0.0
        time seconds 25.0
// outputs for timer
// out_trig
// out_count

The definition above sets the timer module to trigger at 0.0 seconds, that is on the very first sample of execution. It then triggers again 25 seconds later. Each time is triggered n seconds after the previous trigger. The second time says not to trigger at 25 seconds, but 25 seconds after the previous trigger.

A wcnt_exit module definition to use the above timer module would look something like this:

    in_bar t1 out_count
    exit_bar 1

Although the input and output names do not match, they are both of the same category. The out_count output from the timer is a count of how many times the timer module has already triggered. The first time it triggers then, out_count has a value of zero. (Before the module triggers at all, out_count has a value of -1.0).

One further point to note, is if in the above example, you changed the exit_bar parameter of the ecnt_exit module to a value of 2 wcnt will never exit, unless, you created a 3rd time in the timer.

A .wc layout to generate a sine wave Top

Here is a very simple .wc file layout to generate a 1 second wav file of a 220 hrtz sine wave.


// examples/sinewave.wc

samplerate 44100
bpm 120
signature 4/4

// duration of sound

timer t1
        time seconds 0.0
        time seconds 1.0

// clock will run at frequency of sine wave

clock clock1
    in_freq_mod1 off
    freq 220
    freq_mod1_size 1.0

// the sine waveform, driven by clock1

sine_wave sinewave
    in_phase_trig clock1 out_phase_trig
    in_deg_size clock1 out_deg_size
    recycle_mode off
    on_trig_reset_phase off
    phase_cycles 1.0

// amplify waveform to a 16 bit signal

constant one value 1.0 one

mono_amp amp1
    in_signal sinewave out_output
    in_amp_eg one out_output
    in_amp_mod off
    amplitude 20000
    amp_mod_size 0.0
    clip_level 32767

// write amplified signal to wav file

wavfile_out wav1
    in_left amp1 out_mono
    in_right amp1 out_mono
    in_bar t1 out_count
    in_bar_trig t1 out_trig
    filename sinewave.wav
    start_bar 0
    end_bar 1

// when to stop

wcnt_exit wcnt_exit_module
    in_bar t1 out_count
    exit_bar 1


It is almost the most stripped .wc file that can generate a wav with something audible in it. The next thing to do is to make the sound somewhere between slightly vaguely interesting, and, less tacky on the old ear drums.

Using the adsr Top

An ADSR is an envelope of three or more stages, which can be used by another module to shape the amplitude of a signal, acting like a gate, letting sound through and then stopping it again. The stages are Attack, Decay, Sustain, Release. In wcnt multiple sections of A, D, and R, can be added.

In order for the ADSR to be activated and deactivated, it has two inputs. When triggered by in_note_on_trig the attack section starts. When triggered by in_note_off_trig, and provided the envelope has already started, the release section starts.

The parameter sustain_state controls how the sustain section behaves. When set off, first the attack stage is generated. After the decay stage, it skips sustain and resumes at the release stage. Except when the parameter min_time is set longer than the combined length of the attack and decay stages, in which case what time remains to elapse will be created as the sustain stage.

If the sustain_state is on then as soon as the envelope is triggered off by in_note_off_trig it goes straight to the start of the release section. Except of course, if the time elapsed of the envelope so far does not surpass min_time. If the envelope had not yet reached the sustain state, the release level begins at the level of envelope output at the point of deactivation. If the adsr reaches the sustain section before note off, the output level is sustained at the level of the last decay section until note off. If the max_sustain_time parameter is not zero, then the sustain section can last only for that length of time and the release section could be activated before note off occurrs.

Here is a definition for wcnt's implimentation of the ADSR, which will be added to the .wc layout above, just before the mono_amp definition.

        section name attack
            ut 5.0 ul 0.1
            lt 6.0 ll 0.0
        section name attack
            ut 6.0 ul 0.4
            lt 7.0 ll 0.0
        section name attack
            ut 7.0 ul 1.0
            lt 8.0 ll 0.0
        section name decay
            ut 125.0 ul 0.63
            lt 75.0 ll 0.0
        section name release
            ut 795.0 ul 0.0
            lt 50.0 ll 0.0
    in_note_on_trig t1 out_trig
    in_note_off_trig off
    in_velocity one out_output
    up_thresh 1.0
    lo_thresh 0.0
    start_level 0.0
    min_time 75.0
    max_sustain_time 0.0
    release_is_ratio on
    sustain_state off
    zero_retrigger off

In the adsr definition the envelope lines mark the data object definition of the ADSR shape. Each section is also a data object which contains five parameters. The first, name, is the name of the section type, one of attack, decay, or release. The section types can be added in any order, they will be sorted by A's first, D's next, R's last. Multiple instances of the same type are ordered by when they are defined.

The ut, ul, lt, and ll parameters are abreviations for Upper Time, Upper Level, Lower Time, and Lower Level, respectively. The time parameters are the number of milliseconds the section takes to complete, and the level parameters are the target levels to reach at completion of the section.

The in_velocity input and up_thresh and lo_thresh parameters, control which of the shapes is created, upper or lower. Values from in_velocity below lo_thresh produce the lower shape, and values above up_thresh produce the upper shape. In-between values produce in-between shapes. The value used is that of in_velocity when the adsr was activated, it does not grab new values from in_velocity for each stage.

The zero_retrigger is only appropriately named if start_level is set to 0.0. When on the envelope will always begin with the value of start_level, but when off will always begin at the level it is currently at. The envelope could be re-triggered at any time between initial activation and completion, so setting the start_level, zero_retrigger, and the levels of the last release section are important to avoid sudden non-sensical volume changes.

The release_is_ratio controls how the adsr interprets the release section only. Sometimes it's usage is unneccessary, but other times it becomes useful. Usually when there is a long attack stage but a quick note off occurrs before the volume reached full amplitude, you don't want the release section to get louder though.

The adsr defined above, to save unnecessarily creating another module, has it's sustain_state parameter, and it's in_note_off_trig input, turned off. You might mistakenly think you could set in_note_on_trig and in_note_off_trig both the same, and it would know that the first trigger should activate it, while the second deactivates it, but it knows nothing of your plans. All it would do is activate and immediately deactivate, twice.

Applying the adsr Top

To use the adsr to apply volume changes to a wave form you multiply one by the other. The multiplier does just that.

multiplier m1
    in_signal sinewave out_output
    in_modifier adsr1 out_output

But for our sinewave.wc example, we will make use of the mono_amp in_amp_eg input which does the same thing. Change the mono_amp definition to look as this:

mono_amp amp1
    in_signal sinewave out_output
    in_amp_eg adsr1 out_output
    in_amp_mod off
    amplitude 32767
    amp_mod_size 0.0
    clip_level 32767

The sound now starts off silent and quickly increases to full volume, before gradually fading away.

Implimenting an LFO Top

To make the example a little more interesting, some frequency modulation will be applied to the clock driving the waveform, by means of an LFO implimentation.

The clock module could be used for driving a waveform to be used as an LFO, but there is another module, lfo_clock suited for more sophisticated use. Here is the lfo_clock definition to be added after the timer module.

lfo_clock lfoc1
    in_phase_trig t1 out_trig
    in_freq_mod1 off
    in_freq_mod2 off
    freq 7.5
    freq_mod1_size 1.0
    freq_mod2_size 1.0

The lfo_clock is set to oscilate 7.5 times a second. It won't begin until it recieves a trigger via it's in_phase_trig input. Here is a sine_wave definition to generate the basic LFO waveform.

sine_wave lfosw1
    in_phase_trig lfoc1 out_phase_trig
    in_deg_size lfoc1 out_deg_size
    recycle_mode off
    on_trig_reset_phase off
    phase_cycles 1.0

The begining of one cycle of the waveform is triggered by lfoc1 out_phase_trig. The parameter phase_cycles tells the module how many cycles to produce each time the waveform is triggered. Here it is 1 full cycle of a sine wave through 360 degrees. If in_phase_trig was set to t1 out_trig It would only be triggered twice, producing two seperate one cycle waveforms, except, it would not get the chance to produce the second before wcnt exits. The on_trig_reset_phase off prevents the sine_wave from reseting it's internal phase when triggered, which lets it get on with it's own devices. When set on tiny clicks in the waveform are audible when using cycle times of 1.0, but fractional cycle times would render properly.

Finally, one last module can be used to create a delay and ramp to the waveform output. Here is the lfo_controller module definition to do so.

    in_trig t1 out_trig
    in_waveform lfosw1 out_output
    in_amp_mod off
    delay_time 50.0
    ramp_time 50.0
    start_level 0.0
    end_level 1.0
    response_time 0.0
    amp_mod_size 0.0

The lfo_controller does not actually control, but shapes the output of the lfosw1 waveform. The start_level sets the level of the waveform when the lfo_controller is triggered, that is the output of the waveform is multiplied by it. The end_level is how much to multiply the waveform by after the decay and ramp times have elapsed. The response_time parameter is used to specify in milliseconds how long to take, for the current output level to reach the start_level when in_trig recieves a trigger. This can be used to prevent clicking of sudden volume changes when an lfo_controller is being used for amplitude modulation.

Using an LFO for frequency modulation Top

Now we have added the LFO modules there is only one more step to have working frequency modulation. The clock module which drives the frequency of the sound needs to have information to modulate its frequency.

clock clock1
    in_freq_mod1 lfoctrl out_output
    freq 220
    freq_mod1_size 1.5

The input in_freq_mod1 of clock1 is set to use the shaped waveform, but it could equally be set to the unshaped waveform. The amount of modulation applied is 1.5.

Assuming the range of values provided by lfoctrl out_output is between -1.0 and 1.0, then a freq_mod1_size set to 2.0, and a -1.0 from in_freq_mod1 will halve the frequency, and a 1.0 will double the frequency. Effectively dropping an octave, or adding an octave.

As in the example, freq_mod1size is set at 1.5. This means the clock's frequency will modulate around the original frequency by -0.5 and +0.5 octaves.

Instead of increasing the frequency, when lfoctrl out_output is 1.0, the freq_mod1_size parameter can be set between 0.0 and 1.0 to invert the effects of in_freq_mod1. Using a waveform with it's positive and negative phases balanced between 1.0 and -1.0 for both frequency modulation inputs of a clock type module, with freq_mod1_size set to 2.0, and freq_mod2_size set to 0.5, will make the second frequency modulation cancel out the first. By the way, a freq_mod1_size set to 1.0 will provide no frequency modulation at all.



Basic Usage



Trigger modules

File inclusion

Groups and Copying





SourceForge.net Logo