MIDI/Note Operators as a Composition Tool

It would be useful to be able to combine two Note Clips into one Note Clip, or two Note In into one resulting Note Out, from within the Note Grid.
The resulting notes (combination) would depend on the source clips and a chosen Operator, which would define how the notes from both input Clips would be processed

Operators such as :

  • Add(A,B) = merge notes from both sources
  • Subtract(A,B) = play notes from A, without notes from B
  • Rythm(A,B) = play notes heights from track A, with note timings from track B applied
  • Transpose(A, B, root) = play the notes from track A, transposing each note by its relative heights from track B (relative to chosen root)

What problem(s) would this feature resolve?

Combining both using a “Ryhtm Operator” is the main feature here, allowing for flexible and rapid creation of rythm variations of a single note sequence.
It would help to manage rythm and notes heights independently, allowing for faster composition. Separating ryhtm (rythm clips) from chords (chord clips), would allow to have a pool of each (rythm pool, chord pool).

I bet you can see some creative use of the rest.

The whole would allow users to have a rapid composition tool embedded inside the DAW.

A proper study could reveal other use cases and lead to more Operators

How does this feature fit in Bitwig as a product?

Innovation at the heart of Bitwig’s selling point, the desire to elevate above other DAWs and provide a concurrential advantage over the competition

Is there already an alternative way to achieve this on Bitwig?

Don’t know. I tried to implement this using Note Grid, and miserably failed.

An arpeggiator could be used for applying various ryhtms to a sequence of notes, with a much lesser level of comfort, since it would rely on automation, and does not allow the user (composer) to view and manage its ryhtms and its chords using the same tools.

Could it be implemented using Bitwig components or APIs, without Bitwig team’s support?

I’m not sure Note Grid components would fit. The Grid only receives MIDI/Notes signal from a single track ?

Could it be provided by a VST or something else reasonably integrated with Bitwig?

Yes. Composition tools such as Scaler, Captain Chords. They provide their own piano roll and edition tools, which is not convenient.

Are there other products that offer this feature?

Not in the DAW category, but into the composition tools.

Relevant links (optional)

1 Like

I’ve been doing my research and coded a protoplug LUA script that achieves the “Rythm” combination feature as described above.

It takes note input from both channel 1 that serves as the “chord” track and channel 2 serves as the “rythm” track.

For those interested, here’s the script for protoplug


--[[
name: midi chordify
description: MIDI processor VST/AU. Send chords on channel 1, and trigger them on channel 2, output is gated chords.
author: ChrisDee
--]]

require "include/protoplug"

function kind(e)
    if e:isNoteOn() then
        return "on"
    elseif e:isNoteOff() then
        return "off"
    else
        return "--"
    end
end

function printEvent(e)
    print(""
    .. "{ " .. kind(e)
    .. ", ch=" .. tostring(e:getChannel())
    .. ", n#=" .. tostring(e:getNote())
    .. "}"
    )
end

function channelOrder(a,b)
    return a:getChannel() < b:getChannel()
end

-- what kind of chord ?
local chordStructure = {}
local outEvents = {}

function plugin.processBlock(samples, smax, midiBuf)
    inEvents = {}
	outEvents = {}
	-- collect events in table so we can sort them
	for ev in midiBuf:eachEvent() do
	    table.insert(inEvents, ev)
	end
	-- sort events by channel so chord events are processed before gate events
	table.sort(inEvents, channelOrder)
	-- 
	for _,ev in ipairs(inEvents) do
	    printEvent(ev)
		if ev:isNoteOn() then
		    if ev:getChannel() == 1 then
			    addNoteToChord(ev:getNote())
			else
			    openGate(ev)
			end
		elseif ev:isNoteOff() then
		    if ev:getChannel() == 1 then
		        -- printEvent(ev)
			    removeNoteFromChord(ev:getNote())
			else
			    closeGate(ev)
			end
		end	
	end
	-- fill midi buffer with prepared notes
	midiBuf:clear()
	if #outEvents>0 then
		print("--")
		for _,e in ipairs(outEvents) do
		    -- printEvent(e)
			midiBuf:addEvent(e)
		end
	end
end

function addNoteToChord(noteInChord)
	table.insert(chordStructure, noteInChord)
end

function removeNoteFromChord(noteInChord)
	for index,v in pairs(chordStructure) do
      if v == noteInChord then
        table.remove(chordStructure, index)
        local newEv = midi.Event.noteOff(1, noteInChord)
		table.insert(outEvents, newEv)
        break
      end
    end
end

function openGate(ev)
	for _, offset in ipairs(chordStructure) do
		local newEv = midi.Event.noteOn(1, offset, ev:getVel())
		table.insert(outEvents, newEv)
	end
end

function closeGate(ev)
	for _, offset in ipairs(chordStructure) do
		local newEv = midi.Event.noteOff(1, offset)
		table.insert(outEvents, newEv)
	end
end

Integrating inside a Bitwig project is kind of a hassle, but it works and helps to compose melodic lines / chording separately from their articulation. Having such a feature natively would be a productivity boost for composers, in most genres.

1 Like

Thank you @ChrisDee, way to go scratching your own itch! Also, I didn’t know about Protoplug. Interesting framework.

1 Like