Born out of frustration with DAWs and traditional sheet music software, Schisma is a lightweight, feature-rich composition tool. From notation to sound design, Schisma aims to give complete control of the composition process to the musician.
- Ability to create and use complex synthesizers
- Ability to use custom temperaments and tuning systems
- Support for custom input formats
- MIDI interoperability
- Lightweight text format, allowing for portability and the use of a wide range of editing tools
- Type-safe sound design and instrument creation
You'll need to install Csound, PortMidi, and then Stack.
After that's done, make sure to add ~/.local/bin to your $PATH, and then
run the following from the project root:
stack installThat should place the schisma executable within your $PATH.
Schisma aims to support a variety of input methods. At the heart of each input method is an instruments file.
An instruments file is simple JSON. Here's an excerpt from the Commemoration example:
{
"instruments": [
{
"number": 1,
"name": "QBSA",
"instrument": "Profit",
"soundFontPath": "",
"parameters": {
"amplitude" : 0.63,
"polyModSourceAmountFilterEnvelope" : 0,
"polyModSourceAmountOscillatorB" : 0,
"polyModDestinationFrequencyA" : 0,
"polyModDestinationPulseWidthA" : 0,
"polyModDestinationFilter" : 0,
...
},
"midiChannel": 1
}
]
}The top-level keys are:
instruments- an array of instrument definitions whose keys are:number- a number by which to identify it in the tracker filename- a nameinstrument- the instrument to be usedsoundFontPath- the path to the SoundFont file shouldinstrumentbe "SoundFont", blank otherwiseparameters- an object containing the instrument parameters along with their corresponding valuesmidiChannel- the MIDI channel (1-16) if MIDI interop is desired, or 0 to disable
Schisma's tracker derives inspiration from popular trackers like
Renoise. Contrary to most trackers, Schisma's
tracker interface is just a .csv file. This makes for easy editing within a
variety of applications.
Here's an excerpt from the Commemoration example:
#,Master,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA,I1 QBSA
0,bpm:60 lpb:1,F#2,,,D5 amp:0.2,,,,,,,,
1,,,,,,,,,,,,,
2,,,,,,,,,,,,,
3,,,,,C#5 amp:0.2,,,,,,,,
----------,----------,----------,----------,----------,----------,----------,----------,----------,----------,----------,----------,----------,----------
4,,G2,,,D5 amp:0.2,,,,,,,,
5,,,,,,,,,,,,,
6,,,,,,,,,,,,,
7,,,,,C#5 amp:0.2,,,,,,,,
The header row should consist of the following columns:
#- cells within this column contain the line numberMaster- cells within this column contain project-wide settings, such as:bpm:<double>- the beats per minute [default: 60]lpb:<double>- the number of tracker lines (rows) per beat [default: 16]tn:<string>/tuning:<string>- the tuning [default: "a440"]tmp:<string>/temperament:<string>- the temperament [default: "12tet"]
- Any instrument names written in the following format:
- An optional "M" or "S" prefix, in order to mute or solo the track, respectively
- The letter "I" (short for "Instrument"), followed by the instrument number
referenced in
instruments.json - An optional space, followed by an optional name
Cells within instrument columns can be blank or can contain one of the following:
- A pitch name followed by its octave number (e.g., "Bb4")
- The value "OFF" - this is used to turn the prior note off
Notes are held (i.e., across blank cells) until another pitch or the word "OFF" is encountered.
Blank cells or cells with pitches can also contain effects. An effect is a
key-value pair, where the key is the name of an instrument parameter (or an
alias listed in parameterRenamings) within instruments.json, and the value
is a number.
A row can begin with a hyphen (-); this can be helpful for visually marking
sections within a composition.
A prior iteration of Schisma had a LilyPond parser. Its development stalled when it became apparent that conventional notation has serious limitations when handed off to a computer for playback. There is a ticket to restore it, but more ideation is required (especially around performance notation) before it will achieve parity with the tracker.
Composition-wide settings can be configured in a JSON file. Here are the contents of the Commemoration example:
{
"trackerSettings": {
"parameterRenamings": {
"aa": "amplifierAttack",
"rel": "amplifierRelease",
"amp": "amplitude"
},
"frequencyMapper": {
"name": "default",
"arguments": []
}
}
}The top-level keys are:
trackerSettings- an object containing the tracker settingsparameterRenamings- an object containing parameter aliases that can be used within the tracker
frequencyMapper- an object containing the name of the frequency mapper, along with the arguments to be passed to it
Currently, there are two supported frequency mappers:
default: The default frequency mapper will convert pitches using the specified tuning and temperamentwithRandomDetuning: This frequency mapper will convert pitches using the specified tuning and temperament, and then randomly detune each pitch by a maximum number of cents (specified as the first argument toarguments)
The project file ties together the instruments file, the tracker file, and the composition file into one "project". Here are the contents of the Commemoration example:
{
"compositionFile": "./composition.json",
"instrumentsFile": "./instruments.json",
"trackerFile": "./tracker.csv"
}Both absolute and relative filenames are supported.
Currently, Schisma only supports output via Csound. All notation and instruments are compiled down to Csound code and then run automatically.
Listen to an example score below. (It's a good idea to lower your volume first!)
schisma tracker play -p examples/Commemoration/project.json -s 0 -e 89The ability to render to an audio file will be available shortly. For now, you
can edit the resulting Csound file (located at /tmp/tracker.csd):
; Replace this line
-odac -+rtmidi=portmidi -Ma
; with this:
-o /tmp/tracker.wavAnd then render /tmp/tracker.wav by running Csound:
csound /tmp/tracker.csdSchisma supports MIDI input. Run the following in GHCi to play around with a simple sine wave from a virtual MIDI keyboard:
let osc = oscilWithDefaults (i# 1) cpsmidi :: ARateSignal
playWithVirtualMidi empty [osc, osc] If you have a physical MIDI device, try the following:
let osc = oscilWithDefaults (i# 1) cpsmidi :: ARateSignal
playWithMidiDevice empty [osc, osc]Or try taking the "Profit" synthesizer for a spin using its default settings:
let p = Schisma.Synth.Emulations.Profit.profit (Data.Map.Strict.fromList [("amplitude", i# 1), ("frequency", cpsmidi)])
playWithMidiDevice empty [p, p]- Profit - based on the highly influential Prophet-5
- SoundFont - a
generic SoundFont player, capable of loading any
.sf2file
Running the following will print out a list of instrument (synth) names along with information about their parameters:
schisma synth listPlaintext not for you? Check out the GUI, which can assist greatly with notation and instrument design (as parameters can be tweaked on the fly).
The codebase has been meticulously documented (particularly around the Csound opcodes). View it with:
stack haddock schisma --openRun them with:
stack testA world of gratitude is owed to the folks behind Csound. It is a truly amazing piece of software and the community around it is incredible.
Special thanks to Paul Hudak, whose lucid writing in The Haskell School of Music helped kickstart the ideas in this project.
And the biggest thanks of all to DR, whose poking and prodding at my musical discontents made all of this possible.