Filterclavier – MIDI controllable filter “piano”

Today I got the first usable version of Filterclavier running,
a low/high/bandpass filter which cutoff and resonance (and gain)
are set by MIDI input.

“Portamento time” adds viscosity to the filter following the MIDI notes.
In the moment it is monophonic, but in the future there
may be several filters in parallel.

The code is largely based on Krzysztof Foltmans excellent Calf plugin framework.
When I saw the beauty of its code and GUI I could not resist to write the Filterclavier.

Here is the mandatory screenshot:

The Filterclavier

New, sophisticated MIDI Clock Slave implementation works

On Saturday,
I got the new MIDI Clock Slave implementation working: It now consists of a Delay Locked Loop (DLL). Since a DLL has the property of always minimizing the loop error (which means the difference of ARDOURs transport position relative to where it should be according to the latest MIDI clock message), it will even follow tempo changes.

That means, you can change the tempo from 120 up to 400 and down to 40, and after a short time Ardour will be exactly
on the beat again.

Of course you can just use the same tempo as in ARDOUR
and enjoy drift-free synchronization between ARDOURs audio and your MIDI device.


Wikipedia Affiliate Button

Today I decided to support Wikipedia which has been a great source of knowledge and support to me.
If you have some money to dump into it, I can highly recommend it.

Drobilla fixes sending immediate events / Playing edited notes works

Dave Robillard fixed sending immediate events in 3.0 now, for which I am really grateful,
because the MIDI Panic button works again and now the basis for playing edited notes
while editing works, since my implementation depends on it:

Playing edited notes

Notice the loudspeaker icon in the MIDI toolbar. When it is active, all selected notes will be played back while editing (e.g. stepping through note velocities).
The window at the right bottom shows the MIDI output while editing.

Three MIDI Note coloring modes work now

From now on, it is possible to color MIDI notes according to:

  1. Velocity, with colors from the Mixer meters
  2. Channel (velocity = opaqueness, colors courtesy Thorsten Wilms)
  3. Track color (velocity = opaqueness)

Here is the screenshot:

Three MIDI note coloring modes

Haskell Jack client with absolute time

I just modified the Sound.JACK package so that the MIDI event loops
are passed an additional parameter which represents jacks frame time
at the start of the processing cycle.

Now a simple MIDI monitor that prints its input and forwards all events to output
looks like that:

{-# options -O2 #-}
module Main where

import qualified Sound.JACK as Jack
import Sound.JACK.Midi

main ∷ IO ()
main = Jack.mainMidi foo

foo ∷ NFrames →  (NFrames, Event) →  IO (NFrames, Event)
foo cycleStart (t, e) = do
    putStrLn $ "Time: " ⊕ (show $ cycleStart + t) ⊕ " " ⊕ (show e)
    return (t, e)

and its output (two notes and pressing a program button on my keyboard):

$ dist/build/midimon/midimon | grep -v ActiveSensing
started midimon...
Time: 302239993 MIDIEvent (Channel {fromChannel = 0}) (NoteOn (Pitch {fromPitch = 60}) (Velocity {fromVelocity = 52}))
Time: 302256544 MIDIEvent (Channel {fromChannel = 0}) (NoteOff (Pitch {fromPitch = 60}) (Velocity {fromVelocity = 64}))
Time: 302284765 MIDIEvent (Channel {fromChannel = 0}) (NoteOn (Pitch {fromPitch = 62}) (Velocity {fromVelocity = 58}))
Time: 302303650 MIDIEvent (Channel {fromChannel = 0}) (NoteOff (Pitch {fromPitch = 62}) (Velocity {fromVelocity = 64}))
Time: 302394999 MIDIEvent (Channel {fromChannel = 0}) (Control BankSelectMSB 0)
Time: 302395028 MIDIEvent (Channel {fromChannel = 0}) (Control BankSelectLSB 112)
Time: 302395055 MIDIEvent (Channel {fromChannel = 0}) (ProgramChange (Program {fromProgram = 1}))
Time: 302395097 MIDIEvent (Channel {fromChannel = 0}) (Control MainVolumeMSB 79)
Time: 302395125 MIDIEvent (Channel {fromChannel = 0}) (Control Controller4A 50)
Warning: Did not understand Event: MidiEvent @ 52	: [240,67,16,76,8,0,118,21,247]
Warning: Did not understand Event: MidiEvent @ 51	: [240,67,16,76,8,0,114,84,247]
Warning: Did not understand Event: MidiEvent @ 51	: [240,67,16,76,8,0,119,52,247]
Warning: Did not understand Event: MidiEvent @ 49	: [240,67,16,76,8,0,115,72,247]
Time: 302395676 MIDIEvent (Channel {fromChannel = 0}) (Control ChorusDepth 0)
Warning: Did not understand Event: MidiEvent @ 27	: [240,67,16,76,3,2,11,30,247]
Warning: Did not understand Event: MidiEvent @ 27	: [240,67,16,76,8,0,34,50,247]
jack_client_thread zombified - exiting from JACK

We see that the output is nicely parsed (except for the sysex events, which I dont care about right now)

Distributed compilation is fun….

Since I have a relatively powerful laptop (2x2GHz Turion64, 2GB RAM)
I installed another copy of Ubuntu Hardy 8.04 on my laptop, added the distcc
package, configured a bit, and voila…….
distributed compilation:

Distributed compilation is fun

It was quite crucial, that the slave system on my laptop was 64 bit too, so I installed
a minimal Ubuntu with the c++ compiler and distcc (thats enough, no build deps needed).

Changing Patches by Context Menu works

Now it is possible to change to another patch with the context menu on a flag:

Changing Patches by Context Menu

The patches are organized into the patch banks defined in the MIDNAM file.

Stepping through the patchlist with the mouse wheel works

When using the mouse wheel on program change flags, the CC0, CC32 and program change automation lists are set to the values of the next or preceding patch in the patch list of the MIDNAM file.

first working prototype which resolves program changes to their patch names

first working prototype which resolves program changes to their patch names

On each program change event,
bank select msb and lsb are read and the
corresponding patch name is found.

Program changes show up as little flags,
later it will be possible to edit them.
(Change patch name, etc.)