Bass transcribe
Use when the user has played bass (or another monophonic instrument) and wants the take transcribed — to a MIDI file, an Ableton Live clip, or a tab/chart. Default pipeline is CREPE (full model + viterbi) on the recorded audio; basic-pitch for double-stops; includes note segmentation, cleanup rules, and real-time plugin alternatives.From its SKILL.md
npx -y skills add PerIPan/music-workflow-skills --skill bass-transcribeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 24 days oldThe repository was created 24 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.2 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
Bass Transcribe — played take → MIDI / Live clip / chart
Default is the offline CREPE pipeline (validated: CREPE full+viterbi beats pyin on
bass and vocals). For in-Live plugin options (NeuralNote, Jam Origin) read
references/realtime-options.md.
1. Get the audio
- User points at a file — wav/mp3/aiff of the take. Mono preferred; DI cleaner than mic.
- Record in Live — audio track, arm, record the take. MCP cannot export audio:
the user does File → Export, or point at the raw recording under the Set's
Samples/Recorded/folder. - Ask for (or detect) the take's BPM if the output will go into a Live clip.
2. Default pipeline — CREPE → MIDI
import crepe, librosa, numpy as np, pretty_midi
y, sr = librosa.load(AUDIO, sr=16000, mono=True)
time, freq, conf, _ = crepe.predict(y, sr, model_capacity='full', viterbi=True, step_size=10)
CONF, MIN_LEN, GAP = 0.55, 0.08, 0.05 # confidence gate, min note s, merge gap s
midi_f = 69 + 12*np.log2(freq/440.0)
notes, cur = [], None
for t, m, c in zip(time, midi_f, conf):
p = int(round(m)) if c >= CONF and np.isfinite(m) else None
if cur and p == cur['p'] and t - cur['end'] <= GAP:
cur['end'] = t
else:
if cur and cur['end'] - cur['start'] >= MIN_LEN:
notes.append(cur)
cur = {'p': p, 'start': t, 'end': t} if p is not None else None
if cur and cur['end'] - cur['start'] >= MIN_LEN:
notes.append(cur)
pm = pretty_midi.PrettyMIDI()
inst = pretty_midi.Instrument(program=33) # Electric Bass (finger)
for n in notes:
if 26 <= n['p'] <= 67: # octave sanity: drop-D D1 to 24th-fret G4
inst.notes.append(pretty_midi.Note(velocity=96, pitch=n['p'],
start=n['start'], end=n['end']))
pm.instruments.append(inst)
pm.write(OUT_MID)
Tuning knobs: CONF up to 0.6–0.7 for noisy takes; MIN_LEN down to 0.05 for fast
lines; step_size=10 ms is fine for bass.
3. Cleanup rules
- Drop blips < 80 ms (tracker flicker, fret noise).
- Octave sanity: 4-string bass ≈ MIDI 26–67 (drop-D D1 … 24th-fret G4). CREPE octave errors land a 5th/octave out — flag and correct outliers to the nearest in-range octave.
- Legato-join same-pitch notes split by < 50 ms gaps.
- Ghost notes / slides show as short low-confidence fragments — either drop (chart use) or keep (feel/groove analysis). Ask which the user wants.
- Double-stops or chords played? CREPE is monophonic and will pick one note — rerun
with basic-pitch (
basic-pitch <out_dir> <audio> --save-midi) for those passages.
4. Outputs
.midfile — the pipeline's direct product; drag into any DAW.- Live clip via the
ableton-mcpskill: convert seconds → beats (beats = sec * BPM / 60), size the clip in BARS (round up to 1/2/4/8…), push withadd_notes_to_clipin ≤140-note chunks (never two pushes to the same clip in parallel). - Tab / chart — bass tab or bar chart generation: chart craft lives in the
song-analysisskill (references/chart-and-lyrics.md); pitch-class per half-bar aggregation as in its Phase 3.
5. Verify before declaring done
Report note count, pitch range, and duration vs. take length. Sanity signals: a bass
take yields roughly 1–4 notes/second; a pitch histogram dominated by 2–5 pitch classes
(the song's roots). Wildly more notes → lower CONF gate is letting flicker through;
wildly fewer → gate too high or the take is quieter than expected.
Local environment (this machine)
- Python with crepe 0.0.16 + basic-pitch 0.4.0 + pretty_midi (verified 2026-07-16):
/Users/peripan/dev/abletonAI/audio-analysis/.venv-bp/bin/python - Prior art:
scripts/transcribe_bass_pyin.pyin the tooling root (pyin — superseded by CREPE).
What ships with it: 1 file
1.5 KB alongside SKILL.md
references/
- realtime-options.md1.5 KB