Domifare – still a rough draft

Today’s diff. Everything compiles, but most things aren’t tested!

Today, I wrote the functions for most of the language structures, except the scheduling ones. And the shaking one, which I’ve just realised I’ve forgotten to include! For the variable classes, I am borrowing a lot of code from DubInstrument in AlgoRLib. Probably, this project and that should be folded into one repo or one should directly depend on the other.

For DubInstruments, asking for a random pattern can trigger the creation of a new one, but not here, as all patterns are entered by the performer.

I need some GUI, including sliders for thresholds and a text print out of entered stuff. Ideally, there should also be a record light for when the performer is entering loops.

As far as shaking goes, that’s sort of straight forward for the rhythm lines. For the melody lines, I might be looking at BufferTool. It’s designed to split up spoken text rather than played notes and relies on pauses. Another possibility is to keep onset data for melodic loops and use it to decide where cuts should be. I’ll need another trigger that gets sent by the recording synthdef when it’s gate opens, so I can relate the onset timings to the position in the buffer.

Tomorrow my wife is having a party and I’m doing marking on Monday and Tuesday, so it might be a few days before I can test properly.

Domifare Classes

Key still had some problems with transposition that related to frequency quanitsation, so those are (hopefully?) now sorted. I got rid of the gravity argument for freqToDegree because it doesn’t make sense, imo and calculating it is a tiny bit of a faff.

For Domifare, as with a spoken language, breaks between commands are articulated as pauses, so I’ve added a DetectSilence ugen. The threshold will need to be connected to a fader to actually be useful, as the margin of background noise will vary massively based on environment.

The next step is parsing. It’s been a loooong time since I’ve worried about how to do this… IxiLang uses a switch statement with string matching.

I need to draw out how this is going to work, since the repeat and the chance commands both take commands as arguments.

This might work as a statement data array:

[key, min_args, max_args, [types], function]

Types can be: \var, \number, \operator, \data. If it’s \operator, then the operator received will be the key for another statement, and the parser will listen for that too…. If it’s \data, that means start the fucntion asap….

Also, since variables are actually loop holders, I’m going to need to make a class for them.

My original plan to was to use pitch recognition to enter in midi notes, but that’s not going to work, so some commands are now defunct.


(
var lang, vars, numbers;
vars = (solfasire:nil, solfasisol:nil, soldosifa:nil);
numbers = (redodo: 1, remimi:2, refafa: 3, resolsol: 4, relala: 5, resisi: 6, mimido: 7, mimire:8);
lang = (
larelasi: [\larelasi, 2, 2, [\var, \data], nil], // func adds the name to the var array, runs the recorder
dolamido: [\dolamido, 0, 1, [\var], nil], // func stops names loop or all loops
domilado: [\domilado, 0, 1, [\var], nil], // func resumes named loop or all loops
mifasol: [\mifasol, 0, 1, [\var], nil], // func raises an octave, which is probably impossible
solfami: [\solfami, 0, 1, [\var], nil], // func lowers an octave- also impossible
lamidore: [\lamidore, 2, 2, [\var, \data], nil], // add notes to existing loop
dosolresi: [\dosolresi, 1, 1, [\var], nil], // shake the loop, which is possible with recordings also...
misisifa: [\misisifa, 0, 1, [\var], nil], // next rhythm
fasisimi: [\fasisimi, 0, 1, [\var], nil], //previous rhythm
misoldola: [\misoldola, 0, 1, [\var], nil], //random rhytm
refamido: [\refamido, 0, 0, [], nil], // die
sifala: [\sifala, 2, 2, [\number, \operator], nil], // repeat N times (1x/bar)
larefami: [\larefami, 2, 2, [\number, \operator], nil] // X in 8 chance of doing the command
);

After pondering this for a bit, I decided to write some classes, because that’s how I solve all my problems. I created a github project. This is the state of the sole file today.

Tested with human voice

Testing showed that for human voice, the frequency domain onsets and pitch tracking were more accurate and faster than the time domain, which is good to know.

Once the frequency is detected, it needs to be mapped to a scale degree. I’ve added this functionality to the Tuning Lib quark. While doing this, I could the help file was confusing and badly laid out and some of the names of flags on the quantisations were not helpful, so I fixed the helpfile, documented the new method, renamed some of the flags (the old ones still work). And then I found it wasn’t handling octaves correctly – it assumed the octave ratio is always 2, which is not true for Bohlen Pierce scales, or some scales derived by Dissonance Curve. So this was good because that bug is not fixed after a mere 8 years of lurking there. HOWEVER, the more I think about it, the less I think this belongs in Key….

Pitch detecting is flaky as hell, but onsets are solid, which is going to make the creation of melodic loops difficult, unless they actually just record the tuba and do stuff with it.

This is the code that’s working with my voice:


(

s.waitForBoot({

s.meter;

SynthDef(\domifare_input, { arg gate=0, in=0;

var input, env, fft_pitch, onset, chain, hasfreq;

input = SoundIn.ar(in, 1);
env = EnvGen.kr(Env.asr, gate, doneAction:2);

chain = FFT(LocalBuf(2048), input);
onset = Onsets.kr(chain, odftype:\phase);//odftype:\wphase);
#fft_pitch, hasfreq = Pitch.kr(input);

//send pitch
SendTrig.kr(hasfreq, 2, fft_pitch);

// send onsets
SendTrig.kr(onset, 4, 1);

//sin = SinOsc.ar(xings/2);

//Out.ar(out, sin);

// audio routing
//Out.ar(out, input);

}).add;

k = Key(Scale.major); // A maj
//k.change(6); // C maj - changing to c maj puts degree[0] to 6!

b = [\Do, \Re, \Mi, \Fa, \So, \La, \Si];
(scale:k.scale, note:k.scale.degrees[0]).play;

OSCdef(\domifare_in, {|msg, time, addr, recvPort|
var tag, node, id, value;

#tag, node, id, value = msg;
case
{ id == 2 } {
//value.postln;
//c = k.freqToDegree(value.asFloat).postln;
//b[c.asInt].postln;
b[k.freqToDegree(value.asFloat)].postln;
}
{ id == 4 } { "4 freq dom onset".postln; }

}, '/tr', s.addr);

s.sync;

a = Synth(\domifare_input, [\in, 0 , \out, 3, \rmswindow, 50, \gate, 1, \thresh, 0.01]);

})
)

Domifare input

Entering code requires the ability to determine pitch and entering data requires both pitch and onset. Ergo, we need a synthdef to listen for both things. There is also two ways to determine pitch, one in the time domain and the other in the frequency domain.

The frequency domain, of course, refers to FFT and is probably the best method for instruments like flute. It has a pure tone, where the loudest one is the fundamental. However, brass instruments and the human voice both have formants (loud overtones). In the case of tuba, in low notes, the overtones can be louder than the main pitch. I’ve described time-domain frequency tracking for brass and voice in an old post.

The following is completely untested sample code…. It’s my wife’s birthday and I had to go out before I could try it. It does both time and frequency domain tracking, using the fft code to trigger sending the pitch in both cases. For time domain tracking, it could -and possibly should- use the amplitude follower as a gate/trigger in combination with a frequency change of greater than some threshold. The onset cannot be used as the trigger, as the pitch doesn’t stabilise for some time after the note begins. A good player will get it within two periods, which is still rather a long time in such a low instrument. A less good player will take longer to stabilise on a pitch.

Everything in the code is default values, aside from the RMS window, so some tweaking is probably required. Presumably, every performer of this language would need to make some changes to reflect their instrument and playing technique.


(

s.waitForBoot({

SynthDef(\domifare_input, { arg in=0, out=3, rmswindow = 200;

var rms, xings, input, amp, peaks, sin, time_pitch, fft_pitch, onset, chain, hasfreq;

input = SoundIn.ar(in, 1);
amp = Amplitude.kr(input);
rms = RunningSum.rms(input, window);
peaks = input - rms;
xings = ZeroCrossing.ar(peaks);
time_pitch = xings * 2;

chain = FFT(LocalBuf(2048), input);
onset = Onsets.kr(chain, odftype:\wphase);
#fft_pitch, hasfreq = Pitch.kr(input);

//send pitch
SendTrig.kr(hasfreq, 0, time_pitch);
SendTrig.kr(hasfreq, 1, fft_pitch);

// send onsets
SendTrig.kr(onset, 2, 1);

//sin = SinOsc.ar(xings/2);

//Out.ar(out, sin);

// audio routing
//Out.ar(out, input);

}).add;

OSCdef(\domifare_in, {|msg, time, addr, recvPort|
var tag, node, id, value;

#tag, node, id, value = msg;
case
{ id == 0 } { "time dom pitch is %".format(value).postln; }
{ id == 1 } { "freq dom pitch is %".format(value).postln; }
{ id == 2 } { "onset".postln; }

}, '/tr', s.addr);

s.sync;

a = Synth(\domifare_input, [\in, 0 , \out, 3, \rmswindow, 200]);

})
)

Domifare fonts

Solresol can be notated in many ways: solfedge, numbers, notes and via two competing sets of special glyphs. These glyphs are a proposed edition to the unicode standard and part of a set of glyphs known as the CSUR. They’re included in some fonts, like the amazingly ugly Unifoundry includes the more abstract glyphs

      

and Constructium which just has single characters of solfedge

       

(and this is boring, but well-rendered and easy to understand – aside from the duplication of the final syllable as both ‘si’ and ‘ti’.).

Both sets of glyphs above should render in modern web browsers, but allow some time.

Many of my compuer music projects seem to quickly get bogged down in font issues and learning a new script is probably too much to ask of performers (myself included), even if it’s only 8 glyphs. However Constructum is, essentially, a monospace font in the sence that all 4-note words will render the same length, so it’s my likely choice for a display. It is a lot more easy to do than to draw actual music notation.

Like ixilang users type into a dedicated Document window Domifare users will be provided with an auto-transcription of their input. This is enough problem to solve by itself in early versions, but ixi-lang’s page re-writing properties seem like a good plan for later ones.

Domifare sisidomi

‘Domifare sisidomi’ means ‘live code’ in solresol, which is the first ever ‘constructed language’. That is, it was the first ever language to be intentionally designed. And, as this was a new idea, the creator, François Sudre, apparently felt like new syllables were needed. He used musical tones.

This last weekend, I played at an algorave in Newcastle with tuba and algorithms. The idea was to use a foot pedal to control things, but (despite working perfectly at home), it was non-responsive when the gig started, so my set included some live coding. Live coding with one hand while holding a tuba is not terribly efficient and it’s impossible to live code and play tuba at the same time . . . unless, playing the tuba is the live coding.

And thus, I’ve now specified an ixi lang-like language, domifare sisidomi. It’s a bit sparse, but there’s only so much a player can be expected to remember.

All variables are loops. There are three built in: solfasire, solfasisol and soldosifa (low percussion, high percussion and bassline). These are entered by playing the name of the variable followed by a rhythm or melody. As there is more than one kind low or high percussion instruments, different ones can be specified by playing different pitches.

The full (rough, unimplemented) specification follows:

// Enter a loop

solfasire [rhythm] //kick & toms
solfasisol [rhythm] // higher drums
soldosifa [melody] // bassline

larelasi [4 notes = the name] [melody] // declare a new loop

// start stop and modify a loop

dolamido [name] -- silence loop
domilado [name] -- resume loop
mifasol [name] -- raise an octave
solfami [name] -- lower an octave

lamidore [name] [rhythm] -- add notes to the loop
dosolresi [name] -- randomise loop // shake in ixilang

// every time a loop is changed by playing in new notes, shaking or adding, it gets added to a list of rhythms

// moving between loops in the list

misisifa / fasisimi [optional name] - move to next or previous rhythms
misoldola [optional name] - move to a random rhythm

// if no name is given, applies to all playing loops

// control structures

refamido - die

sifala dofadore [number] [next/prev/rand/randomise/chance/octave shift] [optional name] -- repeat the command x times

larefami [number] [next/prev/rand/randomise/repeat/octave shift/die] [optional name] - x in 8 chance of doing the command

//numbers

redodo - 1
remimi - 2
refafa - 3
resolsol - 4
relala - 5
resisi - 6
mimido - 7
mimire - 8

Scrambling and Rotating

I’m still doing stuff with the Bravura font, so you’re going to have to follow a link to see it.

New things on that page include changing font size per item, rotating an individual object, constraining random numbers and shuffling an array. The last of which is not included in javascript. I cut and pasted a function from stack overflow.
Right now I’m using random numbers, but the end version needs to work deterministically in response to data and probably everyone’s screens should more or less match. So the randomness is for now and not later.
I need to make some functions for drawing arrows and staves. And I need to figure out how the bounding boxes will work and how things will fade in and out. Every kind of glyph or drawn thing on the screen needs to be an object that takes parameters in regards to size and rotation and knows how to draw itself.
In short, it’s starting to look like music, but there’s a long way to go.

Friday’s Post

I found a really very handy PDF document showing every single available music glyph in the Bravura font, organised by type. Gaze upon it and be amazed by how much notation you don’t know and how very very many types of accidentals there are. I really like the treble clef whose lower stroke ends in a down arrow. I don’t know how I missed it earlier. This is truly the best font ever. I also has letters and numbers and stuff.
I’ve got an example of using Bravura in a canvas. You have to go elsewhere to see it, because it’s downloading the font via @font-face in css and I can’t do that from this blog.
If you look at it, you should see an upside down treble clef. This is from the Bravura font. If you don’t see the treble clef, please leave a comment with what browser you’re using (ex: Internet Explorer), the version number (ex: 4.05), the sort of device (ex: Desktop, laptop, tablet, iphone, etc) and the operating system.
I got that glyph into the canvas by typing the unicode into the string in my text editor. The editor is using a different font, so this is kind of annoying because looking at the text source doesn’t show the result or even the unicode number.
This is an example of an image in a canvas with some text:

Your browser does not support the HTML5 canvas tag.

Big Red Blob originally uploaded by celesteh.

var c=document.getElementById(“canvas_images”);
var context=c.getContext(“2d”);
var numGlyphs = Math.floor((Math.random()*3)+1) + 1;
var blob = new Image();
var x, y;

context.font = “150% Bravura”;
blob.src = “https://farm8.staticflickr.com/7322/9736783860_4c2706d4ef_m.jpg”
blob.onload = function() {
context.drawImage(blob, 0, 0);
for (var i = 0; i < numGlyphs; i++) { x = Math.floor((Math.random()*i*50) + 1) +5; y = Math.floor((Math.random()* 205) + 1) +7; //1f49b context.fillText("

Drawing

Today I went to the dentist because my dental surgery from last week was still all swollen and that turns out to not be a good sign. So I picked up some antibiotics and then went to the Goldsmiths degree show, which was interesting and extremely variable. I did not get a lot of creative pacting done today. I read a wee bit about how to declare objects in javascript, which is really easy:

var cleff = {
unicode: "&x#1d11e";
repeats: 1
};

What I really need is just a syntax cheat sheet, since I’m already familiar with most of the concepts of this language. So I skipped ahead to canvases.

Your browser does not support the HTML5 canvas tag.

var c=document.getElementById(“myCanvas”);
var ctx=c.getContext(“2d”);
ctx.fillStyle=”#FF0000″;
ctx.fillRect(0,0,200,100);
ctx.fillStyle=”#000000″;
ctx.moveTo(0,0);
ctx.lineTo(200,100);
ctx.stroke();
ctx.fillStyle=”#0000FF”;
ctx.moveTo(0, 32);
ctx.lineTo(200, 32);
ctx.stroke();
ctx.fillText(“unicode?”,32,32)

What the source for that looks like is:

<canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#FF0000";
ctx.fillRect(0,0,200,100);
ctx.fillStyle="#000000";
ctx.moveTo(0,0);
ctx.lineTo(200,100);
ctx.stroke();
ctx.fillStyle="#0000FF";
ctx.moveTo(0, 32);
ctx.lineTo(200, 32);
ctx.stroke();
ctx.fillText("unicode?",32,32)


</script>

I need to learn how to get unicode into those strings. Just typing it in with the ctrl-shift-u thing doesn’t work, nor does typing the html escape sequence. Also, it seems like changing the line colour didn’t work.

Chosen Symbols

I picked which symbols I’m going to use. (I have to link to them rather than post them on this page because they use a bundled font, and some web browsers want that font to come from the same server as the text. I can’t upload the font to blogspot, as far as I know.)
A couple of iPad users let me know they can see the upside-down treble clef, so I know that this font thing works on that device, so this is excellent news.
The symbols are sort-of grouped into noteheads, rests, lines, clefs, fermatas, circles, triangles, diamonds, and groovy percussion symbols. There are some cases in which different unicode chars seem to map to identical symbols. Some of the symbols, like the bars, don’t makse sense by themselves, but need to have several grouped together. There’s going to need to be some logic in how symbols are chosen by the program and used. Strings might be pre-defined, so regexes might indicate repetitions of a glyph.
While going through some papers, I found my first notes from when I first thought of this piece.
.flickr-photo { border: solid 2px #000000; }.flickr-yourcomment { }.flickr-frame { text-align: left; padding: 3px; }.flickr-caption { font-size: 0.8em; margin-top: 0px; }


First Notes, originally uploaded by celesteh.

This piece started as a pen and paper idea. The ideas were:

Lines

  1. staff lines that go funny, like intersecting lines, steps, etc.
  2. wavy lines using a line drawing tool.

Notes

  1. pitch sets definied before the lines go off –> indeterminate clefs
  2. Ink blots that fall from an ink pen
  3. granular clouds w/ pitch areas defined in margins

Changes

  1. Transparencies, ala Cage
  2. Apps written in processing or Open GL, use monitors or projector.
  3. phone app?

The staff lines that go off is a good idea. They could start straight and then curve or just always be intersecting. This can’t use the staff notation in the font, but will need to be a set of rules on how to draw lines.
Using indeterminate clefs is not as good an idea – it just means there are two possible versions of every note, which just builds chords.
By the end of making that outline, it was no longer a pen and paper piece!
Granular clouds are not well suited to vocal ensembles, but this idea did become another piece.
Cloud Drawings from Charles Céleste Hutchins on Vimeo.