A quick deeper view: the sonification process starts with an injection of a
Decorator pattern into "if", "for", etc. statements, in what is called
token stream rewriting. Callbacks are structured around the
Template design pattern, so the real sonification algorithm is interchangeable and configured at runtime. Properly 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 music generation by an ABC language/notation (see
Guido Gonzato's
and
Chris Walshaw's sites), the
jMusic library, by the
JACK audio server or by the
JSyn library.
General requirements:
- codesounding-embedded.jar in the classpath
- JDK 6
In order to be "sonified", java source files have to be post-processed with
codesounding.cl.ApplyTemplate class, which applies an ANTLR token transformation. On this topic
see the
ANT tutorial or
the
command line interface documentation.
After post-processing the source files, compile them, having codesounding-embedded.jar
into the classpath. Finally, run your classes / jars and let them sound.
For example, if you get a Java source file (
plain PingPong.java) and instrument it (either using an
Instrumenter or the ANT task) you can obtain a new instrumented source file (
PingPong.java) which at runtime will call a custom sound processor.
Sound generation algorithm can be chosen with the property
PROCESSOR.TYPE; this can be set with the
-D JVM flag or inserted into a configuration file named
codesounding.properties, which if present in the classpath or in the current directory will be automatically load, or inserted into a file specified by the property
CONFIG_FILE (its format is specified in the following section).
In case of multiple definitions, the configuration file overrides any parameter set by the command line, whereas the classpath is overriden by a possible file in the current directory.
Note that as for now jsyn classes are available only in the SVN repository. You must install its library, following
these instructions.
Allowed values for
PROCESSOR.TYPE are:
-
codesounding.UDPProcessor: for every Java istruction sends an UDP message. It enables the communication with MAX/MSP patches for further audio processing (see an example).
-
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
codesounding.abc.* and
codesounding.jmusic.LogaRythm processors can be configured. The configuration file is a standard properties java file; each row contains a key-value pair:
PROPERTY_NAME=VALUE
There are four property groups, with the following prefixs:
- basic (for codesounding.abc.* processors)
- filter (for codesounding.abc.* processors)
- midi (for codesounding.abc.Midi* processors)
- basic.instr (for codesounding.jmusic.LogaRythm processor)
No property is mandatory: default values / behaviours will be used.
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 2010 - Roberto Mannai (robermann@gmail.com) ~