CodeSounding library: how to make computer generated music sounds with CodeSounding java library

SourceForge.net Logo

Demo

Wiki Home   Download   Documentation  
The sonification process starts with an injection of a Decorator pattern into "if", "for", etc. statements, in what is known as token stream rewriting. Callbacks are structured around the Template design pattern, so the real sounding algorithm is interchangeable and configured at runtime. The sonification is therefore not on the static source code structure but on the dynamic behaviour during the execution.
Code parsing is accomplished by an ANTLR parser, while sound generation by different engines:

Library usage - Configuration file

General requirements:
  • codesounding-embedded.jar in the classpath
  • JDK 5
In order to be "sonified", Java source files have to be post-processed with the codesounding.cl.ApplyTemplate class, which applies an ANTLR token transformation. On this topic see the ANT-based tutorial or the command line interface documentation. For example, if we get a Java source file (PingPong.java) and instrument it (either using an Instrumenter or the ANT task task) we obtain a new instrumented source file (PingPong.java) which at runtime will call a custom sound processor.
After instrumentation, compile the source files with codesounding-embedded.jar in the classpath. Finally, run your classes / jars and let them sound.

The sound generation algorithm is defined by the property PROCESSOR.TYPE; this can be set by the JVM's -D flag or appended into a configuration file named, by default, codesounding.properties or whatever you define with the property -DCONFIG_FILE.

Allowed values for PROCESSOR.TYPE are the following (in order to install JSyn see its documentation):
  • codesounding.UDPProcessor: for every Java istruction sends an UDP message. It enables the communication with Max/MSP or Pure Data patches for further audio processing (see an example). The -Dtarget=[ip address] option sets the host where the patch is running.
    Statement typeUDP port
    Variable declaration7001
    {7002
    }7003
    break7004
    continue7005
    do7006
    for7007
    if7008
    return7009
    throw7010
    while7011
  • codesounding.jsyn.GrainScaledSkipperProcessor: every thousandth Java istruction triggers an enveloped oscillation (of 50 ms), with each instruction having a different frequency. They are finally added and reverberated. Faders enable you to change the oscillators's frequencies, how many instructions are skipped and the grains's envelope. Furthermore the skipped instructions scale the amplitude of each oscillator.
  • codesounding.jsyn.GrainSkipperProcessor: an implementation similar to GrainScaledSkipperProcessor, with a larger envelope and without scaling.
  • codesounding.jsyn.OneSampleProcessor: every Java instruction queues just one sample. Every 200s they are played by a sampler. A fader enables the change of the sampling frequency.
  • codesounding.jsyn.filter.OctaveProcessorWithFilter: similar to GrainScaledSkipperProcessor, here the output is band-pass filtered in a bank tuned to MIDI's C60, ..., F77 pitches.
  • codesounding.jsyn.InstrumentProcessor: here I'm just joking with instruments exported from SoftSynth's Wire; the same effects (that is, skipping instructions and playing them with short, equal tempered notes) can be obtained through mere MIDI - see for example the JMusic based SynthSyncopate.java class.
  • codesounding.javoice.JaVoiceProcessor: the Java trace is translated into an "image", then converted into sound. The core algorithm is quite the same as hificode.c's, published in JavOICe. The audio is rendered by JSyn.
  • codesounding.jjack.SamplerSumProcessor: on Linux OSs, creates a sound wave in a JACK format. You must have the jjack library and a JACK server running. Other mandatory properties are jjack.ports, jjack.input.ports (set to 0), java.library.path for the native .so library (see the jjack manual), and ns, which sets the nanoseconds for the sampling interval.
    You must also include jjack.jar into the classpath.
    Here an example:
    java -Djjack.ports=2 -Dns=500 -Djjack.input.ports=0 -DPROCESSOR.TYPE=codesounding.jjack.SamplerSumProcessor -Djava.library.path="/usr/lib" -cp "/usr/share/java/jjack.jar:./java2demo.jar:../../dist/codesounding-embedded.jar" java2d.Java2Demo
  • codesounding.jmusic.LogaRythm: generates music depending on quantity and variability of instruction types during time, using a logarithmic function
  • codesounding.abc.MidiBasicPlayer: generates and plays temporary MIDIs; it requires the abc2midi binary
  • codesounding.abc.MidiGenerator: generates MIDIs without playing them; it requires the abc2midi binary
  • codesounding.abc.BufferedProcessor: creates a file in ABC format; you must specity its path using the OUTPUT_FILE property. From that file you can create manually the MIDIs:
    abc2midi music.abc -o my_midi.mid
    You can also export the musical score to a PS file with abcm2ps, then export that as a PDF file.
  • codesounding.jmusic.CrazyPianist
  • codesounding.jmusic.DamnBirds
  • codesounding.jmusic.DiehardPeople
  • codesounding.jmusic.IrritatingPianists

Configuration file

Currently with the configuration file you can detail the behaviour of codesounding.abc.* and codesounding.jmusic.LogaRythm classes.

The configuration file is a standard Java properties file; each row contains a key-value pair:
PROPERTY_NAME=VALUE
There are four property groups, with the following prefixs:
  1. basic (for codesounding.abc.* processors)
  2. filter (for codesounding.abc.* processors)
  3. midi (for codesounding.abc.Midi* processors)
  4. basic.instr (for codesounding.jmusic.LogaRythm processor)
No property is mandatory: will be used they default values / behaviours. When in trouble, remember that on CodeSounding the configuration file's values shadow the command line's ones, and that a config file in the current directory takes precedence on the classpath.

1. basic properties
These are the ABC configuration properties. I'm not an ABC expert, so I refer you to the great Guido Gonzato's work, in english and italian language, or to Chris Walshaw's site.
For our aims, it's enough to know that an ABC file is a textual file, make up of a header and a body.
  • basic.header: sets the ABC file header; by default is empty:
    X: 1
    K: C

  • basic.var_declaration: assigns a note to a variable declaration statement. Default value is A (= La).
  • basic.break: assigns a note to the break statement. Default value is " ", that is space (the space between notes).
  • basic.continue: assigns a note to the continue statement. Default value is ', that is the apostrophe character (rises the preceding note by an octave).
  • basic.do: assigns a note to the do statement. Default value is F (= Fa).
  • basic.for: assigns a note to the for statement. Default value is E (= Mi).
  • basic.while: assigns a note to the while statement. Default value is G (= Sol).
  • basic.start_block: assigns a note to the open brace {. Default value is B (= Si).
  • basic.end_block: assigns a note to the closed brace}. Default value is C (= Do).
  • basic.if: assigns a note to the if statement. Default value is D (= Re).
  • basic.return: assigns a note to the return statement. Default value is z (a musical pause).
  • basic.throw: assigns a note to the throw statement. Default value is , (that is the comma character; lowers the preceding note by an octave, the apostrophe reverse).
2. filter properties
When making ABC music, with a filter you can associate a runtime logic of post-processing. Before to be saved on a file, notes are buffered in a temporary buffer. A filter can decide whether write a note in the buffer, or change its content. At the moment, there are four filters:
  • codesounding.abc.filter.BasicFilter: write all notes in the buffer.
  • codesounding.abc.filter.OneThousandthFilter: write one note out of thousand, the others are discarded.
  • codesounding.abc.filter.DurationFilter: in a random way transforms a sequence of the same note (on the buffer) in the same note of greater duration: for example, AAA sequence (3 La) is converted in A3, a La of triple duration.
  • codesounding.abc.filter.SheetMusicFilter: formats suitably the ABC buffer, particularly it creates more rows, more voices, assigns instruments.
The first two filters work on the buffer, whereas the last two process its content. It is possibile to combine more filters, sequentially, using the filter.# property, for example:
filter.1=codesounding.abc.filter.OneThousandthFilter
filter.2=codesounding.abc.filter.DurationFilter
filter.3=codesounding.abc.filter.SheetMusicFilter
set the processing order: OneThousandthFilter is the first, then is applied the DurationFilter, finally the SheetMusicFilter.
If none is used, by default is loaded only the codesounding.abc.filter.BasicFilter. If you want to use more filters, remember to use at least one that writes on the buffer.
With a bit of imagination, you can write more complex filters.

3. midi properties
These properties allow to create an ABC polyphonic music and to associate an instrument to a voice. In a few words, they allow to have more instruments sounding simultaneously.
In order to use the first two properties (totvox and voxnum) you have to apply the codesounding.abc.filter.SheetMusicFilter filter.
  • midi.totvox: allow to create a polyphonic music, setting the instruments number which we'll sound together. Default value is a single voice.
  • midi.instrument.voxnum.#: allow to associate a given instrument to the # voice. For example, midi.instrument.voxnum.2=47 assigns timpani to the second voice. For a list of codes and MIDI instruments, see here (remember to subtract one from these codes, because index range is 0 to 127).
    If none is set, default instrument is 1, that is the piano.
    Notice: you can set instruments only if there are at least two voices.
  • midi.conversion.abc_min_kbytes: set the minimun size of temporary ABC files (in kilobytes), in order they can be converted in MIDI files. Default value is 2.
  • midi.conversion.wait_seconds: frequency (in seconds) of ABC temporary file convertion. Default is 4 seconds.
4. basic.instr properties
When using the codesounding.jmusic.LogaRythm class you can assign an instrument to each instruction category. Use the mnemonics names as definited on the jm.constants.ProgramChanges interface, for example:
basic.instr.continue=EL_GUITAR
As defaults will be used instruments starting from jm.constants.ProgramChanges.PIANO.
  • basic.instr.var_declaration
  • basic.instr.break
  • basic.instr.continue
  • basic.instr.do
  • basic.instr.for
  • basic.instr.while
  • basic.instr.start_block
  • basic.instr.end_block
  • basic.instr.if
  • basic.instr.return
  • basic.instr.throw
Finally, if you want to save in the current directory the sound generated by codesounding.jmusic.LogaRythm processor, you can set the jmusic.writemidi property to true.

~ Copyright © 2006 2012 - Roberto Mannai (robermann@gmail.com) ~