BADASS is a pipeline designed to automate large parts of the authoring process for instrument-based rhythm games, starting with drums. It takes raw audio stems and converts them into game-ready MIDI maps (PART DRUMS) using a combination of Lua scripts and custom JSFX plugins.
V.0.1
- Only tested on 2 songs for now
- Software: Cockos Reaper 7 (or any version supporting Lua and the required plugins).
- Template:
Automatic Mapping.RPP(The project template with pre-routed tracks). - Scripts:
prep_automation_drums_tracks.luaprep_drums_recording.luafix_automated_drums.lua- (loaded with the Action List > New Action > Load...)
- Plugins:
Audio To MIDI Drum Trigger (True Peak Logic)
- Source Dependency: Automated drums authoring only works based on what the stems make available. If some sound has been wrongly assigned to another instrument or stem during separation, it won't be correctly picked up.
- Binary Toms: This is very much a binary system: all tom notes will be assigned to the same color (defaulting to the mapped note). There is no pitch detection to separate High/Mid/Low toms automatically.
- No Flams: Flams are not detected and must be manually added later.
- Maximum accuracy for 1/8th notes, for 1/16h notes it varies: Because of the way wave forms work, rapid hits are hard to detect without on the other hand triggering false positivies. 1/16th notes are fairly reliable on snare and kicks and possibly on rides (not tested yet). On toms and crashes accuracy only goes down to 1/8th notes. For hi-hats, see below.
- Hi-Hat Dynamics: Accuracy for 16th notes on the Hi-Hat is lower. Since these ghost notes are softer by nature, if a soft Hi-Hat note comes immediately after a loud accent (common in two-handed patterns), it will likely get lost in the transient detection.
- Not perfect by design: This system was created to drastically speed up authoring. For this reason, settings and algorithms are mainly targeted at average good/great results, not perfect results for one song but decent for others.
You can do a deep dive in the later part of the document and in the Wiki, this is just the quick and dirty rundown of going from having an MP3 of your song to having PART DRUMS created
You need isolated drum stems. A simple "Drums vs Song" split is not enough. Use a high-quality stem separator (e.g., using the latest Ensemble models in MVSEP) to extract the following specific tracks:
- Kick
- Snare
- Hi-Hat
- Ride
- Crash
- Toms
The automation script relies on strict pattern matching. Your filenames must contain specific keywords, either delimited by dashes/underscores or wrapped in them.
Required Keywords: kick, snare, toms, crash, ride, hh, drums, residual (or other).
| Filename Example | Status | Reason |
|---|---|---|
01-Snare-Top.wav |
✅ Good | Delimited by - |
Song_Kick_01.wav |
✅ Good | Delimited by _ |
Ride-Main.wav |
✅ Good | Delimited |
MySnare.wav |
❌ Bad | No delimiter |
KickDrum.wav |
❌ Bad | No delimiter |
Open Automatic Mapping.RPP.
Drag all your prepared stems into the project, placing them at the bottom of the track list (below existing tracks).
- Open the Action List (
?key). - Run:
Script: prep_automation_drums_tracks.lua.- Alert: The script will ask for confirmation to delete tracks twice. Click Confirm/Yes.
Once processed, ensure your audio is aligned with the project grid. You can now import your existing tempo map or create one to match the audio.
- Open Action List and run:
Script: prep_drums_recording.lua. - Record the song from start to finish.
- Open Action List and run:
Script: fix_automated_drums.lua. - Click Run Process.
Check the PART DRUMS track. It now contains a quantized, cleaned, and mapped drum chart ready for final human review.
[ SUMMARY FLOWCHART ]
[ Raw Stems ]
│ (Renamed: Kick_01.wav, etc.)
▼
[ Drag to Reaper ]
│
▼
[ Run: prep_automation_drums_tracks.lua ] ──► (Moves tracks, Normalizes Cymbals)
│
▼
[ JSFX Triggers ] ──────────────────────────► (Detects Hits via True Peak)
│
▼
[ Record to "TRANSCRIPTION" ]
│
▼
[ Run: Drum Transcription Processor.lua ] ──► (Quantizes, Dedupes, Remaps)
│
▼
[ ✅ PART DRUMS READY ]
This script automates the organization, processing, and cleanup of imported drum multitracks in Cockos Reaper.
- Strict Token Matching: Prevents false positives. A track named
SnareTopwill be ignored; only explicitly delimited names likeSnare_Top,01-Snare, orSong_Snare_01are processed. - Immediate Processing: items are moved and processed the millisecond they are identified, preventing Reaper from losing track of item IDs during batch imports.
- Safe "Bake" Logic: When processing Crash tracks, the script verifies that the FX render was successful (take count increased) before reverting the original track.
- Ripple Edit Protection: Temporarily disables Ripple Editing to prevent accidental shifts on other tracks during the move process.
The Automatic Mapping.RPP project already contains tracks with the exact names defined in the configuration:
Kick,Snare,TomsHH,Ride,CrashHH Processed,Ride Processed,Crash Processed(for processed copies)
The script ignores loose matches to prevent accidents. The instrument name must be delimited by non-alphanumeric characters (underscores or dashes) or be at the absolute start/end of the filename.
| Imported File Name | Status | Reason |
|---|---|---|
01-Snare-Top.wav |
✅ Match | Delimited by - |
Song_Snare_01.wav |
✅ Match | Delimited by _ |
Snare_Main.wav |
✅ Match | Starts with Snare_ |
MySnare.wav |
❌ Ignore | No delimiter |
SnareBus.wav |
❌ Ignore | No delimiter |
The script follows this logical flow for every track in the project:
[ START SCRIPT ]
│
▼
[ DISABLE RIPPLE EDITING ]
│
▼
[ SCAN SOURCE TRACKS ]
│
├─(No Match)─────────────► [ IGNORE TRACK ]
│
▼
( Match Found ) ──► [ MOVE ITEM TO DESTINATION ]
│
▼
[ CHECK DRUM TYPE ]
┌────────────────────────┼─────────────────────────┐
▼ ▼ ▼
( Standard ) ( HH / Ride ) ( Crash )
Snare/Kick/Toms │ │
│ │ ▼
│ │ [ APPLY TRACK FX ]
│ │ (Bake as new take)
│ │ │
│ ▼ ▼
│ [ COPY TO "PROCESSED" ] < Bake Success? >
│ │ │ │
│ ▼ (Yes)│ │(No)
│ [ NORMALIZE ] ▼ ▼
│ │ [ COPY BAKED ] [ KEEP ]
│ │ [ TO PROCESS ] [ RAW ]
│ │ │
│ │ ▼
│ │ [ REVERT ORIG ]
│ │ (Clean Backup)
▼ ▼ │
[ CLEANUP: DELETE EMPTY SOURCE TRACKS ] ◄────────────┘
│
▼
[ RESTORE RIPPLE STATE ]
This part of the process is designed to automate the cleaning, quantization, and re-mapping of raw MIDI drum transcriptions.
It bridges the gap between raw transcription (e.g., from audio-to-MIDI tools) and production-ready drum parts by applying smart quantization logic, removing artifacts, and mapping specific notes to a destination track.
- GUI Control: Simple interface to toggle specific post-processing rules.
- Safety First: Automatically creates a backup of your source track (
TRANSCRIPTION RAW) before processing. - System Optimization: Disables FX on all tracks to ensure smooth processing speed.
- Smart Deduplication: Removes double-triggered crash cymbals (Note 49) based on a specific time threshold.
- Hybrid Quantization: Intelligently detects if a note is closer to a Straight 1/16 or Triplet 1/16 grid and snaps accordingly.
- Legato Processing: Automatically adjusts note lengths to prevent overlaps.
- Auto-Mapping: Copies and transforms notes from the source track to a destination
PART DRUMStrack.
- Download the
.luascript. - Open REAPER.
- Go to Actions -> Show Action List.
- Click New Action -> Load ReaScript.
- Select the downloaded file.
- Launch the script from the Action List.
The GUI:
- A window will appear. Select your options (see Logic Details below).
- Click Run Process.
This script performs several passes over the MIDI data. Here is the exact logic applied:
Raw transcriptions often accidentally double-trigger crash cymbals.
- Target: Note 49.
- Threshold:
1/16th note + 1/32nd noteduration. - Action: If two Note 49s occur within this window, the second one is deleted.
Hi-Hats (42) and Crashes (49) have a very loose attack. In part because of their inherent wave forms, in part because stem splitting might end up chewing up a portion of the shape. For this reason we compensate moving their notes back a bit: hi-hats require less movement, while crashes have an even looser attack. We don't follow this process only if the note is already seemingly on grid: this can happen if the attack is actually cleaner or in case of consecutive hits.
- Logic: The script calculates the distance of the note to the nearest Straight 1/16 vs. the nearest Triplet 1/16.
- Action: If the note is closer to the Triplet grid, it is pre-shifted backwards slightly (1/64 or 1/32) to ensure the subsequent quantization step catches it correctly.
The script does not force a single grid type, to avoid mangling triplets. However it doesn't go as fine as 1/32nd notes because transcription is likely to not being able to discern them and in turn we would be stuck with a number of notes off by 1/32nd. It iterates through every note:
- Compare: Distance to Straight 1/16 vs. Distance to Triplet 1/16.
- Snap: The note is moved to whichever grid point is closer.
Controlled via the GUI Checkbox: "Remove 98 if overlapping 99" This cleans up articulations where a "Open Hi-Hat" might clash with a "Snare/Rim". Sometimes the stem splitter correctly recognizes the ping of the ride but it confuses its wash with that of a hi-hat. So any hi-hat and ride note couple gets reduced to a ride hit. This is optional in case there are genuine tracks in which ride and hi-hat sound at the same time.
- Rule: Delete Note 98 (Hi-Hat) IF:
- Note 99 (Snare/Rim) exists at the same position.
- AND Note 111 (Specific Rim check) does NOT exist.
The script copies notes from TRANSCRIPTION to PART DRUMS and re-pitches them according to this table:
| Source Pitch (Input) | Destination Pitch (Output) | Instrument / Articulation |
|---|---|---|
| 35 | 96 | Kick |
| 38 | 97 | Snare |
| 42 | 98 | Closed Hi-Hat |
| 47 | 99 & 111 | Toms (With pro note marker) |
| 49 | 100 | Crash Cymbal |
| 51 | 99 | Ride |
- REAPER: Tested on REAPER 6.x and 7.x.
This version of the standard JSFX Drum Trigger includes a True Peak analysis algorithm. Unlike standard triggers that fire solely based on a fixed volume threshold, this mod analyzes the context of the audio. It compares the incoming transient against the average volume of the preceding audio (the "Lookback" window) to distinguish genuine drum hits from bleed or sustain.
- Slider 9
- Range: 0ms to 200ms
This defines the "Context Window" preceding a potential hit. When the signal crosses the open threshold, the plugin looks backwards into a memory buffer for the duration set here. It calculates the average volume of that previous audio.
- Higher Values (e.g., 50-100ms): The plugin compares the hit against the general "noise floor" or room tone. This is more stable for isolated tracks.
- Lower Values (e.g., 10-20ms): The plugin compares the hit against the immediate previous audio. This is better for fast rolls where the sustain of the previous hit might mask the attack of the next one.
- Slider 10
- Range: 1.0 to 100.0
This acts as a "Contrast Control". It sets the required ratio between the Detected Peak and the Lookback Average.
- Example (Ratio 3.0): The transient peak must be 3 times louder than the average volume of the lookback window to trigger a MIDI note.
- Tuning:
- Increase this value to eliminate bleed (e.g., snare bleed on a kick track).
- Decrease this value if ghost notes or soft hits are being ignored.
- Slider 11
- Options: Average Window (Diluted), True Peak (Accurate)
This changes how the plugin calculates the "numerator" of the ratio formula.
- Mode 0: Average Window (Diluted)
- Logic: Uses
Hit Volume * 0.5. - Behavior: This mimics older "RMS" style detection. It is less sensitive and smoother. Use this for messy recordings where the transient is not very sharp.
- Logic: Uses
- Mode 1: True Peak (Accurate)
- Logic: Uses the raw
Hit Volume. - Behavior: This uses the absolute loudest sample found within the 4ms attack window. It is highly accurate and aggressive. This is the recommended mode for modern, punchy drums.
- Logic: Uses the raw
Unlike standard triggers that fire the instant a threshold is crossed, this plugin adds a smart logic phase:
- Gate Open: Signal crosses the
Open Threshold(Slider 1). - Wait Phase: The plugin waits for 4ms (hardcoded
attack_ms) to scan for the true maximum peak of the transient. - Context Check: It calculates the average volume of the
Lookbackwindow. - Decision:
- If
(Peak / Lookback) > Sensitivity, the Note is fired. - If the ratio is too low (meaning the volume rose, but not sharply enough relative to the background), the trigger is rejected as "Bleed/Sustain".
- If
The plugin features an on-screen Graphics Overlay (@gfx) that displays the statistics of the last 10 detected hits:
- MBT: Measure.Beat.Time location.
- Jump: The calculated ratio (e.g.,
3.5x). - Hit: The volume of the peak.
- Tail: The average volume of the lookback window.
Use these numbers to fine-tune your Sensitivity Ratio slider.