Model Architecture
Purpose and Scope
This document describes the neural network architecture used in Basic Pitch's pitch detection system. It explains the model's components, how audio signals are transformed and processed through the network, and how the three primary outputs (pitch contours, notes, and onsets) are generated. For information about how the model is loaded and used for inference, see Model Loading and Initialization.
Model Overview
Basic Pitch uses a convolutional neural network architecture that processes audio spectrograms to detect musical notes, their onsets, and fine-grained pitch contours (including pitch bends). The model employs a multi-task learning approach with three output heads to simultaneously predict different aspects of musical content.
Output Interpretations
Audio Input
(22050Hz Mono)
CQT Calculation
Harmonic Stacking
Contour Branch
Note Branch
Onset Branch
Contour Posteriorgram
(264x430 matrix)
Note Posteriorgram
(88x430 matrix)
Onset Posteriorgram
(88x430 matrix)
Pitch contours
with pitch bends
Note activations
at semitone level
Note onset
detection
Sources: basic_pitch/models.py173-299 basic_pitch/constants.py18-63
Input Processing and CQT Transformation
Basic Pitch processes raw audio input using a Constant-Q Transform (CQT), which is a time-frequency representation particularly well-suited for music analysis as it provides logarithmically-spaced frequency bins that align with musical pitch intervals.
get_cqt Function
Audio Input
(batch, AUDIO_N_SAMPLES, 1)
FlattenAudioCh Layer
CQT Layer
NormalizedLog Layer
BatchNormalization Layer
Processed CQT
(batch, n_freq_bins, time_frames, 1)
The CQT implementation uses the following key parameters:
| Parameter | Value | Description |
|---|---|---|
| Sample Rate | 22050 Hz | Audio input sampling rate |
| Hop Length | 256 | Step size between analysis frames |
| Base Frequency | 27.5 Hz | Lowest detectable frequency (A0 on piano) |
| Bins Per Octave | 36 | 3 bins per semitone for contours, 1 for notes |
| Total Bins | 264 | 88 semitones × 3 bins per semitone |
Sources: basic_pitch/models.py137-170 basic_pitch/constants.py22-45 basic_pitch/layers/nnaudio.py455-493
Harmonic Stacking
After the CQT transformation, the model applies a Harmonic Stacking layer that captures harmonic relationships by stacking frequency-shifted versions of the spectrogram. This layer helps the model identify fundamental pitches by providing explicit access to harmonic patterns.
Harmonic Shifts
Stack channels
CQT Input
(batch, time, freq, 1)
HarmonicStacking Layer
Original (×1)
Octave Below (×0.5)
First Harmonic (×2)
Second Harmonic (×3)
...
Nth Harmonic (×N)
Output
(batch, time, N_FREQ_BINS_CONTOURS, n_harmonics)
The harmonic stacking layer:
- Takes frequency bins from the CQT output
- Creates frequency-shifted versions for each harmonic
- Stacks these shifted versions along the channel dimension
- By default, uses harmonics [0.5, 1, 2, 3, 4, 5, 6, 7, 8] (subharmonic + fundamental + 7 overtones)
Sources: basic_pitch/nn.py26-85 basic_pitch/models.py193-204
Model Branches
The model uses a multi-headed architecture with three main branches:
1. Contour Branch
The contour branch predicts fine-grained pitch activation with 3 bins per semitone, enabling the detection of pitch bends and microtonal information.
if not no_contours
Harmonic Stacked Input
Conv2D (5×5)
n_filters_contour=32
BatchNormalization + ReLU
Conv2D (3×39)
8 filters
BatchNormalization + ReLU
Conv2D (5×5)
1 filter
Sigmoid Activation
FlattenFreqCh
'contour' output
Input to Note Branch
Sources: basic_pitch/models.py207-243
2. Note Branch
The note branch produces semitone-level note activations that indicate which notes are being played, with 1 bin per semitone (standard piano note resolution).
Pre-flattened
Contour Output
or Intermediate Features
Conv2D (7×7)
n_filters_notes=32
stride=(1,3)
ReLU Activation
Conv2D (7×3)
1 filter
Sigmoid Activation
FlattenFreqCh
'note' output
Input to Onset Branch
Sources: basic_pitch/models.py247-267
3. Onset Branch
The onset branch detects note onsets, which are the beginning points of musical notes.
Harmonic Stacked Input
Conv2D (5×5)
n_filters_onsets=32
stride=(1,3)
BatchNormalization + ReLU
Note Pre-output
Concatenate
Conv2D (3×3)
1 filter
Sigmoid Activation
FlattenFreqCh
'onset' output
Sources: basic_pitch/models.py272-295
Complete Model Architecture
The following diagram shows the complete architecture with detailed layer dimensions:
Audio Input
(batch, 43264, 1)
CQT + Log + BatchNorm
(batch, 264, 430, 1)
Harmonic Stacking
(batch, 264, 430, n_harmonics)
Contour Conv2D
(batch, 264, 430, 32)
BatchNorm + ReLU
Contour Conv2D
(batch, 264, 430, 8)
BatchNorm + ReLU
Contour Conv2D
(batch, 264, 430, 1)
FlattenFreqCh
(batch, 430, 264)
Conv2D
(batch, 264, 430, 1)
Conv2D stride(1,3)
(batch, 264, 144, 32)
ReLU
Note Conv2D
(batch, 264, 144, 1)
FlattenFreqCh
(batch, 144, 88)
Onset Conv2D stride(1,3)
(batch, 264, 144, 32)
BatchNorm + ReLU
Concatenate
Onset Conv2D
(batch, 88, 144, 1)
FlattenFreqCh
(batch, 144, 88)
Contour Output
(batch, 430, 264)
Note Output
(batch, 144, 88)
Onset Output
(batch, 144, 88)
Loss Functions
The model is trained using binary cross entropy loss functions for each output head:
| Output Head | Loss Function | Description |
|---|---|---|
| Contour | transcription_loss |
Standard binary cross entropy with label smoothing |
| Note | transcription_loss |
Standard binary cross entropy with label smoothing |
| Onset | weighted_transcription_loss |
Binary cross entropy with positive sample weighting |
The model uses label smoothing to prevent overconfident predictions, which is particularly important for pitch detection where the boundaries between notes may not be perfectly defined.
Sources: basic_pitch/models.py39-126
Model Parameters
The default model configuration has the following parameters:
| Parameter | Default Value | Description |
|---|---|---|
| n_harmonics | 8 | Number of harmonics used in harmonic stacking |
| n_filters_contour | 32 | Number of filters for contour convolutional layers |
| n_filters_notes | 32 | Number of filters for note convolutional layers |
| n_filters_onsets | 32 | Number of filters for onset convolutional layers |
| no_contours | False | Whether to exclude contour output (for optimization) |
Sources: basic_pitch/models.py173-178
Implementation Details
The model implementation uses several custom techniques to improve performance:
- Kernel Initialization: Uses variance scaling initialization for stable training
- Kernel Constraints: Applies unit norm constraints to control filter magnitudes
- Early Downsampling: For efficient CQT computation on lower frequencies
- Multi-resolution Output: Different frequency resolutions for different tasks (3 bins/semitone for contours, 1 bin/semitone for notes)
The model is designed to be lightweight while still achieving high-quality transcription results, with a particular focus on accurate pitch contour detection that enables capturing expressive pitch characteristics like vibrato and pitch bends.
Sources: basic_pitch/models.py129-136 basic_pitch/layers/nnaudio.py30-135