Instructions to use litert-community/Basic-Pitch-LiteRT with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use litert-community/Basic-Pitch-LiteRT with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
| license: apache-2.0 | |
| library_name: litert | |
| pipeline_tag: audio-classification | |
| tags: [music-transcription, audio-to-midi, basic-pitch, cqt, litert, tflite, on-device, gpu] | |
| base_model: spotify/basic-pitch | |
| # Basic Pitch — LiteRT (CompiledModel GPU) music transcription | |
|  | |
| *Audio input → note posteriorgram (MIDI pitch × time) from the on-device model.* | |
| [Basic Pitch](https://github.com/spotify/basic-pitch) (Spotify, ICASSP 2022, Apache-2.0) | |
| re-authored to a **GPU-native** LiteRT `.tflite` — **including the conv-based CQT front-end** | |
| (9 octaves, shared 36×256 kernel banks, lowpass downsample chain, no FFT). Bit-exact torch | |
| re-implementation of the official ONNX (corr 1.000000). FP32, **0.84 MB**. | |
| Pixel 8a (Tensor G3): **241/241 nodes LITERT_CL** (1 partition), **~4.4 ms** per 2 s window; | |
| note-event F1@0.5 **0.98** vs the official model, per-frame argmax agreement 98%. | |
| ## I/O | |
| - Input `[1, 43844]` float32 — 2 s @ 22 050 Hz mono, [-1, 1] (official window; overlap windows by | |
| 7 680 samples and keep center frames when stitching). | |
| - Outputs: `contour [1,172,264]`, `note [1,172,88]`, `onset [1,172,88]` — sigmoid posteriorgrams | |
| (~11.6 ms frames; note/onset bins = MIDI 21–108). | |
| ## Minimal usage | |
| ```python | |
| import numpy as np, soundfile as sf | |
| from ai_edge_litert.interpreter import Interpreter | |
| wav, _ = sf.read("audio_22050.wav", dtype="float32") # mono 22.05 kHz | |
| x = np.zeros(43844, np.float32); n = min(len(wav), 43844); x[:n] = wav[:n] | |
| it = Interpreter(model_path="basicpitch.tflite"); it.allocate_tensors() | |
| it.set_tensor(it.get_input_details()[0]["index"], x[None]); it.invoke() | |
| contour, note, onset = (it.get_tensor(o["index"])[0] for o in | |
| sorted(it.get_output_details(), key=lambda o: o["index"])) | |
| active = np.argwhere(note > 0.5) # (frame, key); midi = key + 21, t = frame * 256/22050 | |
| ``` | |
| ### Kotlin (Android, LiteRT CompiledModel GPU) | |
| ```kotlin | |
| // implementation("com.google.ai.edge.litert:litert:2.1.5") | |
| val model = CompiledModel.create(File(ctx.filesDir, "basicpitch.tflite").absolutePath, | |
| CompiledModel.Options(Accelerator.GPU), null) | |
| val inBuf = model.createInputBuffers(); val outBuf = model.createOutputBuffers() | |
| inBuf[0].writeFloat(window43844) // 2 s @ 22.05 kHz mono | |
| model.run(inBuf, outBuf) | |
| val note = outBuf[1].readFloat() // [172 * 88], frame-major; midi = bin + 21 | |
| val onset = outBuf[2].readFloat() // onset-triggered decoding -> note events | |
| ``` | |
| ## Conversion | |
| Extracted from the official `nmp.onnx` (102 constants; no TensorFlow). Reflect-pad → | |
| anti-diagonal-constant `FULLY_CONNECTED`; PACK → concat + static slices. Two fp16-on-GPU fixes, | |
| both exact: post-log clamp `clamp(10·log10(p+1e-10), min=-100)` (recovers `log(0)` from the | |
| fp16-flushed floor; desktop no-op) and the per-bin CQT norm folded into per-octave kernel copies | |
| (magnitude is linear in kernel scale). FP32 flatbuffer (fp16 weights cost ~0.005 corr on the tiny | |
| CQT kernels). | |
| ## Upstream | |
| [spotify/basic-pitch](https://github.com/spotify/basic-pitch) (Apache-2.0). Please cite | |
| Bittner et al., *A Lightweight Instrument-Agnostic Model for Polyphonic Note Transcription and | |
| Multipitch Estimation* (ICASSP 2022). | |