Add worldwide instrument catalog

This commit is contained in:
diyaa
2026-09-13 23:52:07 +02:00
parent e7a46772ec
commit b51102b65d
3 changed files with 314 additions and 1 deletions
@@ -0,0 +1,284 @@
public struct LocalInstrumentCatalog: Sendable {
public let items: [InstrumentCatalogItem]
public init(items: [InstrumentCatalogItem] = LocalInstrumentCatalog.worldwideItems) {
self.items = items
}
public static let worldwideItems: [InstrumentCatalogItem] =
western + middleEastern + african + southAsian + eastAsian + southeastAsian + latinAmerican + folkAndModern
private static let western: [InstrumentCatalogItem] = [
item("piano", "Piano", "Keyboard", "Western"),
item("upright-piano", "Upright Piano", "Keyboard", "Western"),
item("grand-piano", "Grand Piano", "Keyboard", "Western"),
item("electric-piano", "Electric Piano", "Keyboard", "Western"),
item("harpsichord", "Harpsichord", "Keyboard", "Western"),
item("celesta", "Celesta", "Keyboard", "Western"),
item("pipe-organ", "Pipe Organ", "Keyboard", "Western"),
item("electric-organ", "Electric Organ", "Keyboard", "Western"),
item("accordion", "Accordion", "Free reed", "Europe"),
item("concertina", "Concertina", "Free reed", "Europe"),
item("melodica", "Melodica", "Free reed", "Western"),
item("violin", "Violin", "Bowed strings", "Western", aliases: ["fiddle"]),
item("viola", "Viola", "Bowed strings", "Western"),
item("cello", "Cello", "Bowed strings", "Western", aliases: ["violoncello"]),
item("double-bass", "Double Bass", "Bowed strings", "Western", aliases: ["upright bass"]),
item("concert-harp", "Concert Harp", "Plucked strings", "Western"),
item("classical-guitar", "Classical Guitar", "Plucked strings", "Western", aliases: ["nylon-string guitar"]),
item("acoustic-guitar", "Acoustic Guitar", "Plucked strings", "Western"),
item("electric-guitar", "Electric Guitar", "Plucked strings", "Western"),
item("bass-guitar", "Bass Guitar", "Plucked strings", "Western"),
item("twelve-string-guitar", "Twelve-string Guitar", "Plucked strings", "Western"),
item("mandolin", "Mandolin", "Plucked strings", "Europe"),
item("banjo", "Banjo", "Plucked strings", "North America"),
item("ukulele", "Ukulele", "Plucked strings", "Oceania"),
item("resonator-guitar", "Resonator Guitar", "Plucked strings", "North America", aliases: ["dobro"]),
item("lap-steel-guitar", "Lap Steel Guitar", "Plucked strings", "North America"),
item("pedal-steel-guitar", "Pedal Steel Guitar", "Plucked strings", "North America"),
item("flute", "Concert Flute", "Woodwinds", "Western", aliases: ["flute"]),
item("piccolo", "Piccolo", "Woodwinds", "Western"),
item("recorder", "Recorder", "Woodwinds", "Europe"),
item("oboe", "Oboe", "Woodwinds", "Western"),
item("english-horn", "English Horn", "Woodwinds", "Western", aliases: ["cor anglais"]),
item("bassoon", "Bassoon", "Woodwinds", "Western"),
item("contrabassoon", "Contrabassoon", "Woodwinds", "Western"),
item("clarinet", "Clarinet", "Woodwinds", "Western"),
item("bass-clarinet", "Bass Clarinet", "Woodwinds", "Western"),
item("soprano-saxophone", "Soprano Saxophone", "Woodwinds", "Western", aliases: ["soprano sax"]),
item("alto-saxophone", "Alto Saxophone", "Woodwinds", "Western", aliases: ["alto sax"]),
item("tenor-saxophone", "Tenor Saxophone", "Woodwinds", "Western", aliases: ["tenor sax"]),
item("baritone-saxophone", "Baritone Saxophone", "Woodwinds", "Western", aliases: ["baritone sax"]),
item("trumpet", "Trumpet", "Brass", "Western"),
item("cornet", "Cornet", "Brass", "Western"),
item("flugelhorn", "Flugelhorn", "Brass", "Western"),
item("trombone", "Trombone", "Brass", "Western"),
item("bass-trombone", "Bass Trombone", "Brass", "Western"),
item("french-horn", "French Horn", "Brass", "Western", aliases: ["horn"]),
item("tuba", "Tuba", "Brass", "Western"),
item("euphonium", "Euphonium", "Brass", "Western"),
item("sousaphone", "Sousaphone", "Brass", "North America"),
item("drum-kit", "Drum Kit", "Percussion", "Western", aliases: ["drum set"]),
item("snare-drum", "Snare Drum", "Percussion", "Western"),
item("bass-drum", "Bass Drum", "Percussion", "Western", aliases: ["kick drum"]),
item("timpani", "Timpani", "Percussion", "Western", aliases: ["kettle drums"]),
item("xylophone", "Xylophone", "Mallet percussion", "Western"),
item("marimba", "Marimba", "Mallet percussion", "Central America"),
item("vibraphone", "Vibraphone", "Mallet percussion", "Western", aliases: ["vibes"]),
item("glockenspiel", "Glockenspiel", "Mallet percussion", "Europe"),
item("tubular-bells", "Tubular Bells", "Mallet percussion", "Western", aliases: ["orchestral chimes"]),
item("triangle", "Triangle", "Percussion", "Western"),
item("tambourine", "Tambourine", "Frame drums", "Western"),
item("cowbell", "Cowbell", "Percussion", "Western"),
item("cymbals", "Cymbals", "Percussion", "Western"),
item("gong", "Gong", "Percussion", "East Asia"),
item("castanets", "Castanets", "Percussion", "Spain"),
item("claves", "Claves", "Percussion", "Latin America"),
item("harmonica", "Harmonica", "Free reed", "Western", aliases: ["mouth organ"])
]
private static let middleEastern: [InstrumentCatalogItem] = [
item("oud", "Oud", "Plucked strings", "Middle East", aliases: ["ud"], terms: ["عود"]),
item("qanun", "Qanun", "Zithers", "Middle East", aliases: ["kanun"], terms: ["قانون"]),
item("ney", "Ney", "End-blown flutes", "Middle East", aliases: ["nai"], terms: ["ناي"]),
item("daf", "Daf", "Frame drums", "Middle East", terms: ["دف"]),
item("riq", "Riq", "Frame drums", "Middle East", aliases: ["riqq"], terms: ["رق"]),
item("darbuka", "Darbuka", "Goblet drums", "Middle East", aliases: ["doumbek", "tabla"], terms: ["دربكة"]),
item("kamancheh", "Kamancheh", "Bowed strings", "Middle East", aliases: ["kamanche"]),
item("santur", "Santur", "Hammered zithers", "Middle East"),
item("baglama", "Baglama", "Plucked strings", "Middle East", aliases: ["saz"]),
item("buzuq", "Buzuq", "Plucked strings", "Middle East", aliases: ["bozuk"]),
item("mijwiz", "Mijwiz", "Double reeds", "Middle East"),
item("arghul", "Arghul", "Double reeds", "Middle East"),
item("zurna", "Zurna", "Double reeds", "Middle East"),
item("naqqara", "Naqqara", "Kettle drums", "Middle East"),
item("tombak", "Tombak", "Goblet drums", "Middle East", aliases: ["zarb"]),
item("setar", "Setar", "Plucked strings", "Middle East"),
item("tar", "Tar", "Plucked strings", "Middle East"),
item("duduk", "Duduk", "Double reeds", "Middle East"),
item("kemence", "Kemenche", "Bowed strings", "Middle East"),
item("saz-bagpipes", "Tulum", "Bagpipes", "Middle East")
]
private static let african: [InstrumentCatalogItem] = [
item("djembe", "Djembe", "Hand drums", "West Africa"),
item("talking-drum", "Talking Drum", "Tension drums", "West Africa", aliases: ["dundun"]),
item("kora", "Kora", "Harps", "West Africa"),
item("balafon", "Balafon", "Mallet percussion", "West Africa"),
item("mbira", "Mbira", "Lamellophones", "Southern Africa", aliases: ["thumb piano"]),
item("kalimba", "Kalimba", "Lamellophones", "Africa"),
item("shekere", "Shekere", "Shakers", "West Africa"),
item("udu", "Udu", "Clay drums", "West Africa"),
item("ngoni", "Ngoni", "Plucked strings", "West Africa"),
item("xalam", "Xalam", "Plucked strings", "West Africa"),
item("dunun", "Dunun", "Bass drums", "West Africa"),
item("ashiko", "Ashiko", "Hand drums", "West Africa"),
item("marovany", "Marovany", "Box zithers", "Madagascar"),
item("endongo", "Endongo", "Harps", "East Africa"),
item("masenqo", "Masenqo", "Bowed strings", "East Africa"),
item("krin", "Krin", "Slit drums", "West Africa"),
item("agogo", "Agogo Bells", "Percussion", "West Africa"),
item("goje", "Goje", "Bowed strings", "West Africa"),
item("adungu", "Adungu", "Harps", "East Africa"),
item("ekwe", "Ekwe", "Slit drums", "West Africa")
]
private static let southAsian: [InstrumentCatalogItem] = [
item("sitar", "Sitar", "Plucked strings", "South Asia"),
item("tabla", "Tabla", "Hand drums", "South Asia"),
item("tanpura", "Tanpura", "Drone strings", "South Asia", aliases: ["tambura"]),
item("sarod", "Sarod", "Plucked strings", "South Asia"),
item("bansuri", "Bansuri", "Side-blown flutes", "South Asia"),
item("shehnai", "Shehnai", "Double reeds", "South Asia"),
item("santoor", "Santoor", "Hammered zithers", "South Asia"),
item("harmonium", "Harmonium", "Free reed", "South Asia"),
item("mridangam", "Mridangam", "Hand drums", "South Asia"),
item("veena", "Veena", "Plucked strings", "South Asia"),
item("sarangi", "Sarangi", "Bowed strings", "South Asia"),
item("dholak", "Dholak", "Hand drums", "South Asia"),
item("dhol", "Dhol", "Bass drums", "South Asia"),
item("ghatam", "Ghatam", "Clay drums", "South Asia"),
item("kanjira", "Kanjira", "Frame drums", "South Asia"),
item("nadaswaram", "Nadaswaram", "Double reeds", "South Asia"),
item("esraj", "Esraj", "Bowed strings", "South Asia"),
item("pakhawaj", "Pakhawaj", "Hand drums", "South Asia"),
item("khol", "Khol", "Hand drums", "South Asia"),
item("ektara", "Ektara", "Drone strings", "South Asia"),
item("rabab", "Rabab", "Plucked strings", "South Asia"),
item("morsing", "Morsing", "Jaw harps", "South Asia"),
item("nagada", "Nagada", "Kettle drums", "South Asia")
]
private static let eastAsian: [InstrumentCatalogItem] = [
item("erhu", "Erhu", "Bowed strings", "East Asia"),
item("guzheng", "Guzheng", "Zithers", "East Asia", aliases: ["Chinese zither"]),
item("pipa", "Pipa", "Plucked strings", "East Asia"),
item("dizi", "Dizi", "Side-blown flutes", "East Asia"),
item("xiao", "Xiao", "End-blown flutes", "East Asia"),
item("suona", "Suona", "Double reeds", "East Asia"),
item("sheng", "Sheng", "Mouth organs", "East Asia"),
item("yangqin", "Yangqin", "Hammered zithers", "East Asia"),
item("ruan", "Ruan", "Plucked strings", "East Asia"),
item("guqin", "Guqin", "Zithers", "East Asia"),
item("liuqin", "Liuqin", "Plucked strings", "East Asia"),
item("hulusi", "Hulusi", "Free reed", "East Asia"),
item("morin-khuur", "Morin Khuur", "Bowed strings", "Central Asia", aliases: ["horsehead fiddle"]),
item("koto", "Koto", "Zithers", "Japan"),
item("shamisen", "Shamisen", "Plucked strings", "Japan"),
item("shakuhachi", "Shakuhachi", "End-blown flutes", "Japan"),
item("biwa", "Biwa", "Plucked strings", "Japan"),
item("taiko", "Taiko", "Drums", "Japan"),
item("hichiriki", "Hichiriki", "Double reeds", "Japan"),
item("ryuteki", "Ryuteki", "Side-blown flutes", "Japan"),
item("gayageum", "Gayageum", "Zithers", "Korea"),
item("geomungo", "Geomungo", "Zithers", "Korea"),
item("haegeum", "Haegeum", "Bowed strings", "Korea"),
item("daegeum", "Daegeum", "Side-blown flutes", "Korea"),
item("janggu", "Janggu", "Hourglass drums", "Korea"),
item("piri", "Piri", "Double reeds", "Korea"),
item("ajaeng", "Ajaeng", "Bowed strings", "Korea"),
item("bawu", "Bawu", "Free reed", "East Asia"),
item("konghou", "Konghou", "Harps", "East Asia")
]
private static let southeastAsian: [InstrumentCatalogItem] = [
item("angklung", "Angklung", "Shaken idiophones", "Southeast Asia"),
item("gamelan", "Gamelan", "Metallophones", "Southeast Asia"),
item("kendang", "Kendang", "Hand drums", "Southeast Asia"),
item("suling", "Suling", "Side-blown flutes", "Southeast Asia"),
item("rebab", "Rebab", "Bowed strings", "Southeast Asia"),
item("kulintang", "Kulintang", "Gong chimes", "Southeast Asia"),
item("agung", "Agung", "Gongs", "Southeast Asia"),
item("khene", "Khene", "Mouth organs", "Southeast Asia"),
item("ranat-ek", "Ranat Ek", "Mallet percussion", "Southeast Asia"),
item("saw-duang", "Saw Duang", "Bowed strings", "Southeast Asia"),
item("tro", "Tro", "Bowed strings", "Southeast Asia"),
item("saung-gauk", "Saung Gauk", "Harps", "Southeast Asia"),
item("pat-waing", "Pat Waing", "Drums", "Southeast Asia"),
item("rondalla", "Rondalla", "Plucked strings", "Southeast Asia"),
item("bandurria", "Bandurria", "Plucked strings", "Southeast Asia"),
item("tinikling-bamboo", "Bamboo Percussion", "Percussion", "Southeast Asia"),
item("sape", "Sape", "Plucked strings", "Southeast Asia"),
item("serunai", "Serunai", "Double reeds", "Southeast Asia")
]
private static let latinAmerican: [InstrumentCatalogItem] = [
item("conga", "Conga", "Hand drums", "Latin America"),
item("bongo", "Bongo", "Hand drums", "Latin America"),
item("timbales", "Timbales", "Drums", "Latin America"),
item("cajon", "Cajon", "Box drums", "Latin America"),
item("guiro", "Guiro", "Scrapers", "Latin America"),
item("maracas", "Maracas", "Shakers", "Latin America"),
item("cuica", "Cuica", "Friction drums", "Latin America"),
item("berimbau", "Berimbau", "Musical bows", "Brazil"),
item("bandoneon", "Bandoneon", "Free reed", "South America"),
item("charango", "Charango", "Plucked strings", "Andes"),
item("cuatro", "Cuatro", "Plucked strings", "Latin America"),
item("tres", "Tres", "Plucked strings", "Cuba"),
item("vihuela", "Vihuela", "Plucked strings", "Mexico"),
item("requinto", "Requinto", "Plucked strings", "Latin America"),
item("zampogna", "Zampona", "Panpipes", "Andes", aliases: ["siku"]),
item("quena", "Quena", "End-blown flutes", "Andes"),
item("bombo-leguero", "Bombo Leguero", "Bass drums", "South America"),
item("surdo", "Surdo", "Bass drums", "Brazil"),
item("pandeiro", "Pandeiro", "Frame drums", "Brazil"),
item("candombe-drums", "Candombe Drums", "Hand drums", "South America"),
item("tambora", "Tambora", "Bass drums", "Caribbean"),
item("guira", "Guira", "Scrapers", "Caribbean"),
item("bata-drums", "Bata Drums", "Hand drums", "Caribbean"),
item("arpa-llanera", "Arpa Llanera", "Harps", "Latin America"),
item("marimbola", "Marimbola", "Lamellophones", "Caribbean"),
item("tiple", "Tiple", "Plucked strings", "South America")
]
private static let folkAndModern: [InstrumentCatalogItem] = [
item("bagpipes", "Bagpipes", "Bagpipes", "Europe"),
item("tin-whistle", "Tin Whistle", "Folk winds", "Ireland", aliases: ["penny whistle"]),
item("bodhran", "Bodhran", "Frame drums", "Ireland"),
item("dulcimer", "Appalachian Dulcimer", "Folk strings", "North America"),
item("hammered-dulcimer", "Hammered Dulcimer", "Hammered zithers", "Europe"),
item("hurdy-gurdy", "Hurdy-gurdy", "Folk strings", "Europe"),
item("nyckelharpa", "Nyckelharpa", "Bowed strings", "Europe"),
item("balalaika", "Balalaika", "Plucked strings", "Europe"),
item("domra", "Domra", "Plucked strings", "Europe"),
item("bouzouki", "Bouzouki", "Plucked strings", "Greece"),
item("cimbalom", "Cimbalom", "Hammered zithers", "Europe"),
item("jaw-harp", "Jaw Harp", "Jaw harps", "Folk", aliases: ["mouth harp"]),
item("didgeridoo", "Didgeridoo", "Aerophones", "Oceania"),
item("clapsticks", "Clapsticks", "Percussion", "Oceania"),
item("native-american-flute", "Native American Flute", "End-blown flutes", "North America"),
item("fiddle", "Fiddle", "Folk strings", "Folk"),
item("washboards", "Washboard", "Percussion", "North America"),
item("musical-saw", "Musical Saw", "Folk instruments", "Folk"),
item("theremin", "Theremin", "Electronic", "Modern"),
item("modular-synthesizer", "Modular Synthesizer", "Electronic", "Modern", aliases: ["modular synth"]),
item("synthesizer", "Synthesizer", "Electronic", "Modern", aliases: ["synth"]),
item("drum-machine", "Drum Machine", "Electronic", "Modern"),
item("sampler", "Sampler", "Electronic", "Modern"),
item("turntables", "Turntables", "Electronic", "Modern", aliases: ["DJ decks"]),
item("midi-controller", "MIDI Controller", "Electronic", "Modern"),
item("electric-violin", "Electric Violin", "Electronic strings", "Modern"),
item("electric-cello", "Electric Cello", "Electronic strings", "Modern"),
item("electronic-drum-pad", "Electronic Drum Pad", "Electronic percussion", "Modern"),
item("vocoder", "Vocoder", "Electronic", "Modern"),
item("keytar", "Keytar", "Electronic", "Modern")
]
private static func item(
_ id: String,
_ name: String,
_ familyCategory: String,
_ regionOrigin: String? = nil,
aliases: [String] = [],
terms: [String] = []
) -> InstrumentCatalogItem {
InstrumentCatalogItem(
id: id,
name: name,
familyCategory: familyCategory,
regionOrigin: regionOrigin,
aliases: aliases,
searchTerms: terms
)
}
}
@@ -0,0 +1,29 @@
import MusicAssistantCore
import XCTest
final class LocalInstrumentCatalogTests: XCTestCase {
func testWorldwideCatalogCoversRequiredRegionsAndInstrumentTypes() {
let catalog = LocalInstrumentCatalog()
let expectedRegions = [
"Western", "Middle East", "Africa", "South Asia", "East Asia", "Southeast Asia", "Latin America", "Modern"
]
let expectedInstrumentIDs = [
"piano", "oud", "djembe", "sitar", "erhu", "angklung", "charango", "bagpipes", "synthesizer"
]
XCTAssertGreaterThanOrEqual(catalog.items.count, 200)
XCTAssertTrue(expectedRegions.allSatisfy { region in
catalog.items.contains { $0.regionOrigin?.contains(region) == true }
})
XCTAssertTrue(expectedInstrumentIDs.allSatisfy { id in
catalog.items.contains { $0.id == id }
})
}
func testWorldwideCatalogHasUniqueStableInstrumentIDs() {
let items = LocalInstrumentCatalog.worldwideItems
XCTAssertEqual(Set(items.map(\.id)).count, items.count)
XCTAssertTrue(items.allSatisfy { !$0.name.isEmpty && !$0.familyCategory.isEmpty })
}
}
+1 -1
View File
@@ -77,7 +77,7 @@ requirement is missing and blocks implementation, record it in
- [x] Create structured catalog models for instrument id, name,
family/category, optional region/origin and aliases/search terms.
- [ ] Provide large worldwide catalog data covering Western, Middle
- [x] Provide large worldwide catalog data covering Western, Middle
Eastern, African, South Asian, East Asian, Southeast Asian, Latin
American, traditional, folk, orchestral, electronic and modern
instruments.