NET OwnChordDetect API Reference
Advanced musical chord detection and analysis library with support for real-time and file-based processing. Features key detection, extended chord recognition, and configurable detection modes.
Overview
OwnChordDetect provides comprehensive chord detection capabilities:
- File-based analysis - Detect chords from audio files with timing information
- Real-time detection - Process notes as they come in for live applications
- Key detection - Automatic musical key detection using Krumhansl-Schmuckler algorithm
- Extended chords - Support for 7th, 9th, 11th, 13th, sus, dim, aug chords
- Multiple detection modes - Basic, Extended, Optimized, and KeyAware modes
- Configurable sensitivity - Adjustable confidence and ambiguity thresholds
Main API - ChordDetect
The main entry point for chord detection functionality.
public static class ChordDetect
{
// File-based chord detection with key and tempo detection
public static (List<TimedChord>, MusicalKey, int) DetectFromFile(
string audioFile,
float intervalSecond = 1.0f);
// Real-time chord detection from note list
public static (string chord, float stability) DetectRealtime(
List<Note> notes,
DetectionMode mode = DetectionMode.Optimized,
int buffersize = 5);
}
DetectFromFile
Analyzes an audio file and returns timed chord progression with key and tempo.
| Parameter | Type | Description |
|---|---|---|
audioFile |
string | Path to the audio file to analyze |
intervalSecond |
float | Analysis window size in seconds (default: 1.0f) |
| Returns | Description |
|---|---|
List<TimedChord> |
List of detected chords with timing information |
MusicalKey |
Detected musical key of the song |
int |
Detected tempo in BPM |
DetectRealtime
Processes a list of notes for real-time chord detection with stability tracking.
| Parameter | Type | Description |
|---|---|---|
notes |
List<Note> | List of notes to analyze |
mode |
DetectionMode | Detection mode to use (default: Optimized) |
buffersize |
int | Buffer size for stability analysis (default: 5) |
Chord Detectors
Various chord detector implementations for different use cases.
ChordDetector (Base)
Core chord detection engine with multiple detection modes.
public class ChordDetector
{
public ChordDetector(
DetectionMode mode = DetectionMode.Basic,
float confidenceThreshold = 0.7f,
float ambiguityThreshold = 0.0f,
int bufferSize = 0);
// Main detection methods
public (string chord, float confidence) DetectChord(List<Note> notes);
public ChordAnalysis AnalyzeChord(List<Note> notes);
public (string chord, float stability) ProcessNotes(List<Note> newNotes);
// Key management
public MusicalKey DetectKeyFromNotes(List<Note> notes);
public void SetKey(MusicalKey key);
}
BaseChordDetector
Basic chord detection for triads and simple chords.
public class BaseChordDetector : ChordDetector
{
public BaseChordDetector(float confidenceThreshold = 0.7f)
: base(DetectionMode.Basic, confidenceThreshold) { }
}
ExtendedChordDetector
Extended chord detection including 7th, 9th, 11th, 13th chords.
public class ExtendedChordDetector : ChordDetector
{
public ExtendedChordDetector(float confidenceThreshold = 0.6f)
: base(DetectionMode.Extended, confidenceThreshold) { }
}
OptimizedChordDetector
Optimized detection with ambiguity analysis and alternative suggestions.
public class OptimizedChordDetector : ChordDetector
{
public OptimizedChordDetector(
float confidenceThreshold = 0.6f,
float ambiguityThreshold = 0.1f)
: base(DetectionMode.Optimized, confidenceThreshold, ambiguityThreshold) { }
public (string chord, float confidence, bool isAmbiguous, string[] alternatives)
DetectChordAdvanced(List<Note> notes);
}
KeyAwareChordDetector
Key-aware detection with appropriate note naming (sharps vs flats).
public class KeyAwareChordDetector : ChordDetector
{
public KeyAwareChordDetector(
float confidenceThreshold = 0.6f,
float ambiguityThreshold = 0.0f)
: base(DetectionMode.KeyAware, confidenceThreshold, ambiguityThreshold) { }
}
RealTimeChordDetector
Real-time chord detector with stability tracking for continuous analysis.
public class RealTimeChordDetector
{
public RealTimeChordDetector(
int bufferSize = 5,
DetectionMode mode = DetectionMode.Optimized);
public (string chord, float stability) ProcessNotes(List<Note> newNotes);
}
Analysis Classes
SongChordAnalyzer
Analyzes complete songs and extracts timed chord progressions with key awareness.
public class SongChordAnalyzer
{
public SongChordAnalyzer(
float windowSize = 1.0f,
float hopSize = 0.5f,
float minimumChordDuration = 0.8f,
float confidence = 0.6f);
public MusicalKey? DetectedKey { get; }
public List<TimedChord> AnalyzeSong(List<Note> songNotes);
public List<TimedChord> AnalyzeSongInKey(List<Note> songNotes, MusicalKey key);
}
| Parameter | Description | Default |
|---|---|---|
windowSize |
Analysis window size in seconds | 1.0f |
hopSize |
Step size between windows in seconds | 0.5f |
minimumChordDuration |
Minimum chord duration to include in results | 0.8f |
confidence |
Minimum confidence threshold | 0.6f |
TimedChord
Represents a detected chord with timing information.
public class TimedChord
{
public float StartTime { get; } // Start time in seconds
public float EndTime { get; } // End time in seconds
public string ChordName { get; } // Chord name (e.g., "Cm7")
public float Confidence { get; } // Detection confidence (0.0 to 1.0)
public string[] Notes { get; } // Note names in the chord
public override string ToString();
}
ChordAnalysis
Detailed chord analysis result with ambiguity detection.
public class ChordAnalysis
{
public string ChordName { get; } // Detected chord name
public float Confidence { get; } // Confidence level (0.0 to 1.0)
public string Explanation { get; } // Detailed explanation
public string[] NoteNames { get; } // Notes forming the chord
public bool IsAmbiguous { get; set; } // Whether detection is ambiguous
public string[] Alternatives { get; set; } // Alternative chord names
public int[] PitchClasses { get; set; } // Pitch classes used
public float[] Chromagram { get; set; } // Chromagram data
public override string ToString();
}
Core Classes
MusicalKey
Represents a musical key with signature and note naming preferences.
public class MusicalKey
{
public string KeyName { get; } // Key name (e.g., "C", "F#", "Bb")
public bool IsMajor { get; } // Major (true) or Minor (false)
public int Sharps { get; } // Number of sharps (0-7)
public int Flats { get; } // Number of flats (0-7)
public string[] PreferredNoteNames { get; } // Note naming preference
public override string ToString(); // Returns "KeyName major/minor"
}
KeyDetector
Detects musical key using the Krumhansl-Schmuckler algorithm.
public class KeyDetector
{
public MusicalKey DetectKey(List<Note> notes);
}
ChordTemplates
Manages chord templates and note name conversion with key-aware naming.
public static class ChordTemplates
{
// Get note name for pitch class with key context
public static string GetNoteName(int pitchClass, MusicalKey? key = null);
// Create chord template from pitch classes
public static float[] CreateTemplate(int[] pitchClasses);
// Create all chord templates with key-aware naming
public static Dictionary<string, float[]> CreateAllTemplates(
MusicalKey? key = null,
bool includeExtended = true);
}
Detection Modes
Different detection modes for various use cases.
public enum DetectionMode
{
Basic, // Basic triads and simple chords only
Extended, // Includes 7th, 9th, 11th, 13th chords
Optimized, // Extended + ambiguity analysis
KeyAware // Optimized + key-aware note naming
}
| Mode | Chord Types | Features | Use Case |
|---|---|---|---|
Basic |
Major, Minor, 7th, maj7, m7 | Fast, simple | Simple songs, quick analysis |
Extended |
Basic + sus2/4, dim, aug, add9, 6th, 9th, 11th, 13th | Comprehensive chord set | Complex songs, jazz |
Optimized |
All extended chords | Ambiguity detection, alternatives | Professional analysis |
KeyAware |
All extended chords | Optimized + key-aware naming | Music theory applications |
Supported Chord Types
| Type | Suffix | Example | Intervals |
|---|---|---|---|
| Major | (none) | C | 0, 4, 7 |
| Minor | m | Cm | 0, 3, 7 |
| Dominant 7th | 7 | C7 | 0, 4, 7, 10 |
| Major 7th | maj7 | Cmaj7 | 0, 4, 7, 11 |
| Minor 7th | m7 | Cm7 | 0, 3, 7, 10 |
| Suspended 2nd | sus2 | Csus2 | 0, 2, 7 |
| Suspended 4th | sus4 | Csus4 | 0, 5, 7 |
| Diminished | dim | Cdim | 0, 3, 6 |
| Augmented | aug | Caug | 0, 4, 8 |
| Add 9 | add9 | Cadd9 | 0, 4, 7, 2 |
| 6th | 6 | C6 | 0, 4, 7, 9 |
| Minor 6th | m6 | Cm6 | 0, 3, 7, 9 |
| 9th | 9 | C9 | 0, 4, 7, 10, 2 |
| Minor 9th | m9 | Cm9 | 0, 3, 7, 10, 2 |
| Major 9th | maj9 | Cmaj9 | 0, 4, 7, 11, 2 |
| 11th | 11 | C11 | 0, 4, 7, 10, 2, 5 |
| Minor 11th | m11 | Cm11 | 0, 3, 7, 10, 2, 5 |
| 13th | 13 | C13 | 0, 4, 7, 10, 2, 9 |
| Minor 13th | m13 | Cm13 | 0, 3, 7, 10, 2, 9 |
Usage Examples
File-Based Analysis
using OwnaudioNET.Features.OwnChordDetect;
// Detect chords from audio file
var (chords, key, tempo) = ChordDetect.DetectFromFile(
audioFile: "song.mp3",
intervalSecond: 1.0f
);
Console.WriteLine($"Detected key: {key}");
Console.WriteLine($"Detected tempo: {tempo} BPM");
Console.WriteLine($"Found {chords.Count} chords:");
foreach (var chord in chords)
{
Console.WriteLine($" {chord.StartTime:F1}s - {chord.EndTime:F1}s: " +
$"{chord.ChordName} (confidence: {chord.Confidence:F2})");
Console.WriteLine($" Notes: {string.Join(", ", chord.Notes)}");
}
Real-Time Detection
using OwnaudioNET.Features.OwnChordDetect;
using OwnaudioNET.Features.OwnChordDetect.Detectors;
// Initialize real-time detector
var detector = new RealTimeChordDetector(
bufferSize: 5,
mode: DetectionMode.Optimized
);
// Process incoming notes
List<Note> currentNotes = GetCurrentNotes(); // Your note input
var (chord, stability) = detector.ProcessNotes(currentNotes);
Console.WriteLine($"Current chord: {chord}");
Console.WriteLine($"Stability: {stability:P1}");
// Alternative using static method
var (chord2, stability2) = ChordDetect.DetectRealtime(
currentNotes,
DetectionMode.Optimized,
buffersize: 5
);
Custom Analysis with SongChordAnalyzer
using OwnaudioNET.Features.OwnChordDetect.Analysis;
// Create analyzer with custom parameters
var analyzer = new SongChordAnalyzer(
windowSize: 1.0f, // 1 second windows
hopSize: 0.5f, // 0.5 second steps
minimumChordDuration: 1.0f, // Min 1 second chords
confidence: 0.90f // 90% confidence threshold
);
// Analyze song (auto-detect key)
List<Note> songNotes = GetNotesFromAudio(); // Your note extraction
var chords = analyzer.AnalyzeSong(songNotes);
Console.WriteLine($"Detected key: {analyzer.DetectedKey}");
// Or analyze with specified key
var key = new MusicalKey("F#", true, 6, 0, sharpNoteNames);
var chordsInKey = analyzer.AnalyzeSongInKey(songNotes, key);
Advanced Chord Detection
using OwnaudioNET.Features.OwnChordDetect.Detectors;
// Use optimized detector with ambiguity detection
var detector = new OptimizedChordDetector(
confidenceThreshold: 0.6f,
ambiguityThreshold: 0.1f
);
List<Note> notes = GetNotes();
var (chord, confidence, isAmbiguous, alternatives) =
detector.DetectChordAdvanced(notes);
Console.WriteLine($"Detected: {chord} (confidence: {confidence:F2})");
if (isAmbiguous)
{
Console.WriteLine("Ambiguous detection!");
Console.WriteLine($"Alternatives: {string.Join(", ", alternatives)}");
}
// Get detailed analysis
var analysis = detector.AnalyzeChord(notes);
Console.WriteLine(analysis.ToString());
Key Detection
using OwnaudioNET.Features.OwnChordDetect.Core;
// Create key detector
var keyDetector = new KeyDetector();
// Detect key from notes
List<Note> notes = GetNotesFromSong();
var key = keyDetector.DetectKey(notes);
Console.WriteLine($"Detected key: {key.KeyName} {(key.IsMajor ? "major" : "minor")}");
Console.WriteLine($"Sharps: {key.Sharps}, Flats: {key.Flats}");
Console.WriteLine($"Preferred notes: {string.Join(", ", key.PreferredNoteNames)}");
// Use key for chord detection
var detector = new KeyAwareChordDetector();
detector.SetKey(key);
var (chord, confidence) = detector.DetectChord(notes);
Custom Chord Templates
using OwnaudioNET.Features.OwnChordDetect.Core;
// Get note name with key context
var key = new MusicalKey("Bb", true, 0, 2, flatNoteNames);
string noteName = ChordTemplates.GetNoteName(10, key); // Returns "Bb"
// Create custom chord template
int[] pitchClasses = { 0, 4, 7 }; // Major triad
float[] template = ChordTemplates.CreateTemplate(pitchClasses);
// Get all chord templates for a key
var templates = ChordTemplates.CreateAllTemplates(
key: key,
includeExtended: true
);
Console.WriteLine($"Generated {templates.Count} chord templates");
foreach (var kvp in templates.Take(10))
{
Console.WriteLine($"{kvp.Key}: {string.Join(", ", kvp.Value.Select(v => v.ToString("F2")))}");
}
DetectionMode.Optimized with appropriate buffer size.
For analysis of complete songs, use SongChordAnalyzer with suitable window and hop sizes.
Lower confidence thresholds detect more chords but may increase false positives.
DetectFromFile or implement your own note extraction for custom audio sources.
Configuration Guidelines
| Parameter | Low Value | Default | High Value | Effect |
|---|---|---|---|---|
confidenceThreshold |
0.4f | 0.6f - 0.7f | 0.9f | Lower = more detections, higher = stricter |
ambiguityThreshold |
0.05f | 0.1f | 0.2f | Lower = more alternatives suggested |
windowSize |
0.5f | 1.0f | 2.0f | Smaller = more responsive, larger = more stable |
hopSize |
0.25f | 0.5f | 1.0f | Smaller = finer resolution, more processing |
minimumChordDuration |
0.5f | 0.8f - 1.0f | 2.0f | Filters out short/transient chords |
bufferSize |
3 | 5 | 10 | Real-time stability (higher = more stable) |