Mild achievements and severe disappointments

posted by Kirill on 2016-04-14

Reaper is a digital audio workstation that gained a lot of devoted followers since its appearance. What is special about Reaper, apart from its enormous functionality and customizability, is two things: Community and Extensibility. You can check the former on Reaper forums, which is a thriving place, but the latter is achieved via user-coded scripts and open API. Since I've started using Reaper as my main DAW, the temptation grew. Then finally a need for a function that wasn't present in Reaper has arisen.


MIDI_Compress_By_Pitch is a simple Lua script for Reaper which takes selected MIDI notes and compresses/expands their velocity by a given rate, but the average velocity is computed per-pitch. The primary usage is for midi percussion or drums or any other instrument where pitches correspond to completely different sounds.


  • Add script to Reaper
    • Click Menu>Actions
    • Find ReaScript section, press Load…
  • Select your MIDI event and open MIDI editor
  • Select the notes you want the script to work on
  • Run the script
    • The processing rate is a difference of velocity for each note and the average velocity in %.
    • First input box is per-pitch compression/expansion in %
    • Second input is compression/expansion rate for all selected notes
    • Use positive values for compression and negative values for expansion.
    • Expansion value can exceed %100 (try -200 or -400)
[Download at GitHub]

Here's the script in action:

midi_compress_by_pitch demo

Using this script can help with evening the dynamics from a live-input, but it retains inter-pitch dynamic difference, so when, say, you're playing with a MIDI-drum set your hi-hat can stay soft while your backbeat is loud as hell.

Where the global expansion can help is when you need to separate the volume of different sounds which is often needed from a drum part but takes a lot of practice to achieve even playing real drums, and if you use a simple midi-controller it's even harder.

The code of the script is open under GPLv2+ license and now resides in my **GitHub repo:** This is my first working script in Lua, so any corrections and suggestions are welcome. Reaper allows using a whole lot of three languages for writing scripts, the other two being Python, which is not bundled with Reaper (but very likely sits on your machine already) and homebrewed EEL which is clearly C-inspired. What drew me to Lua in this case is that Reaper doesn't need a separate interpreter for it and it's a widely used script language with easy to find documentation, help and existing code snippets.

At this point my impressions of Lua are mixed, but this is probably due to my previous almost exclusive usage of compiled, strongly typed languages like my favourite Rust. Lua is very simple so at many places I kept thinking: How is my variable passed? What about coercion? Where's Pattern-matching and Map and function return type? This probably should be evident from the code. Oh, and I'm completely spoiled by extensive compiler feedback and corrections!