MIT License

项目介绍

cemolcay/MusicTheory 是一个托管在 GitHub 上的开源项目,主要使用 Swift 编写,采用 MIT License 许可证,目前获得 477 个 Star、52 次 Fork。

仓库全名
cemolcay/MusicTheory
开源许可证
MIT License
Star 数
477
Fork 数
52
未关闭 Issue
1

README 摘要

MusicTheory === A music theory library with NoteName, Pitch, Interval, Scale and Chord representations in Swift. Requirements Swift 5.0+ iOS 13.0+ macOS 10.15+ tvOS 13.0+ watchOS 6.0+ Install Swift Package Manager CocoaPods Usage MusicTheory provides strongly-typed, correct-by-construction primitives for music theory. All types conform to Codable, Hashable, Sendable and CustomStringConvertible. Equality is…

完整内容见 GitHub 原始 README 或本页 。

常见问题

MusicTheory 用什么语言开发?

主要使用 Swift 编写,采用 MIT License 许可证,目前有 477 个 Star。

MusicTheory 可以免费商用吗?

仓库采用 MIT License 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 MusicTheory 的源码?

可以直接克隆仓库:git clone https://github.com/cemolcay/MusicTheory.git,默认分支为 master;安装与运行步骤见仓库 README。

MusicTheory 最近还在维护吗?

仓库最近一次更新为 8月27日,当前有 1 个未关闭 Issue;Star 数为 477,可作为社区活跃度的参考。

关于

Universal music theory library for iOS, iPadOS, macOS, tvOS and watchOS in Swift

描述取自 GitHub 官方 API,中文内容由 GitRead 中文社区 编辑团队整理。

简要分析

热度分
609
价值分
304
活跃状态
活跃

语言占比

Objective-C
Ruby
Swift

Release

README

MusicTheory

A music theory library with NoteName, Pitch, Interval, Scale and Chord representations in Swift.

Requirements

  • Swift 5.0+
  • iOS 13.0+
  • macOS 10.15+
  • tvOS 13.0+
  • watchOS 6.0+

Install

Swift Package Manager

let package = Package(
  name: "...",
  dependencies: [
    .package(url: "https://github.com/cemolcay/MusicTheory.git", from: "2.0.0")
  ],
  targets: [
    .target(name: "...", dependencies: ["MusicTheory"])
  ]
)

CocoaPods

pod 'MusicTheorySwift'

Usage

MusicTheory provides strongly-typed, correct-by-construction primitives for music theory. All types conform to Codable, Hashable, Sendable and CustomStringConvertible.

Equality is structural throughout: C# ≠ D♭. Use isEnharmonic(with:) wherever you want sound-based comparison.

NoteName and LetterName

NoteName is a letter (A–G) combined with an Accidental. Accidentals are a struct wrapping a single semitones: Int — no degenerate states possible.

let cSharp = NoteName(letter: .c, accidental: .sharp)  // C#
let dFlat  = NoteName(letter: .d, accidental: .flat)   // Db

cSharp == dFlat                        // false — structural equality
cSharp.isEnharmonic(with: dFlat)       // true  — same pitch class

// Convenience constants
let root: NoteName = .fs               // F#
let flat: NoteName = "Bb"             // string literal

// Accidental arithmetic
let doubleSharp = Accidental.sharp + Accidental.sharp  // ##
let natural: Accidental = 0
Pitch

A NoteName combined with an octave number. Middle C is C4 (MIDI 60).

let c4  = Pitch(noteName: .c, octave: 4)
let a4  = Pitch(noteName: .a, octave: 4)

a4.midiNoteNumber           // 69
a4.frequency()              // 440.0 Hz
a4.frequency(a4: 432.0)     // 432.0 Hz (custom tuning)

// Transposition with correct enharmonic spelling
let d4 = c4 + .M2           // D4
let b3 = c4 - .m2           // B3

// Interval between pitches — handles B→C correctly
let b3pitch = Pitch(noteName: .b, octave: 3)
b3pitch.interval(to: c4)    // m2 (minor second, not a major seventh)

// MIDI and string literals
let pitch: Pitch = 60       // C4
let gFlat3: Pitch = "Gb3"  // G♭3

// Enharmonic comparison
let cs4 = Pitch(noteName: .cs, octave: 4)
let db4 = Pitch(noteName: .db, octave: 4)
cs4 == db4                          // false — structural
cs4.isEnharmonic(with: db4)         // true  — same MIDI note

// Nearest pitch from frequency
let nearest = Pitch.nearest(frequency: 440.0)  // A4
Interval

Intervals are defined by a Quality and a degree. Semitones are always computed — never stored — so invalid combinations are unrepresentable.

Interval.M3.semitones   // 4
Interval.P5.semitones   // 7
Interval.m7.semitones   // 10
Interval.P8.semitones   // 12
Interval.M9.semitones   // 14

// Validated construction
let tritone = Interval(quality: .augmented, degree: 4)  // A4, 6 semitones
let invalid = Interval(quality: .minor, degree: 1)      // nil — minor unison doesn't exist

// Inversion
Interval.M3.inverted    // m6
Interval.P4.inverted    // P5

// Enharmonic (same semitones, different quality/degree)
Interval.A4.isEnharmonic(with: .d5)  // true
Interval.A4 == Interval.d5           // false — structurally different
ScaleType and Scale

ScaleType is a lightweight named interval preset for common built-in scales. Scale is the flexible construction API: you can build a scale from a predefined ScaleType or provide your own interval collection directly.

// Built-in scale types
let cMajor = Scale(type: .major, root: .c)
cMajor.noteNames  // [C, D, E, F, G, A, B]

let dMajor = Scale(type: .major, root: .d)
dMajor.noteNames  // [D, E, F#, G, A, B, C#] — correctly spelled with sharps, not flats

let cMinor = Scale(type: .minor, root: .c)
cMinor.noteNames  // [C, D, Eb, F, G, Ab, Bb]

// Custom scale construction without predefined catalogs or validation
let custom = Scale(
    intervals: [.P1, .m2, .P4, .P5],
    root: .d,
    name: "Custom Tetrachord"
)
custom.noteNames  // [D, Eb, G, A]

// Scale type equality is by intervals
ScaleType.major == ScaleType.ionian          // true
ScaleType.lydianDominant.intervals           // [P1, M2, M3, A4, P5, M6, m7]

// Japanese, world and jazz scales are built in too
let hirajoshi = Scale(type: .hirajoshi, root: .a)
hirajoshi.noteNames  // [A, B, C, E, F]

// ScaleType.allScales enumerates every predefined scale type
ScaleType.allScales.count
ChordType and Chord

ChordType is a Set<ChordComponent>. Building from intervals returns a Result so failures are explicit, not silent. Chord symbols use canonical formatting for extended chords (9, Maj9, m9, 11, 13, etc.).

// Predefined types
let maj  = ChordType.major        // M
let min7 = ChordType.minor7       // m7
let dom9 = ChordType.dominant9    // 9
let maj9 = ChordType.major9       // Maj9
let min9 = ChordType.minor9       // m9

// Build from intervals — returns Result
switch ChordType.from(intervals: [.P1, .m3, .P5]) {
case .success(let type): print(type.symbol)   // "m"
case .failure(let err):  print(err)
}

// Chord with root
let cMaj  = Chord(type: .major,   root: .c)
let gDom7 = Chord(type: .dominant7, root: .g)

cMaj.noteNames           // [C, E, G]
cMaj.notation            // "C"
gDom7.notation           // "G7"

// Slash chord
let cOverE = Chord(type: .major, root: .c, bass: .e)
cOverE.notation          // "C/E"

// Pitches in any octave
cMaj.pitches(octave: 4)  // [C4, E4, G4]

// Inversions
let inversions = gDom7.inversions   // [G7, G7/B, G7/D, G7/F]

var firstInversion = Chord(type: .major, root: .c)
firstInversion.inversion = 1
firstInversion.notation  // "C/E"

Tempo and TimeSignature
let ts   = TimeSignature(beats: 4, beatUnit: 4)   // 4/4
ts.description   // "4/4"
ts.isCompound    // false

let ts68 = TimeSignature(beats: 6, beatUnit: 8)   // 6/8
ts68.isCompound  // true

let tempo = Tempo(timeSignature: ts, bpm: 120)

let quarter = NoteValue(type: .quarter)
tempo.duration(of: quarter)     // 0.5 seconds
tempo.sampleLength(of: quarter) // 22050.0 samples @ 44100 Hz

// Note modifiers use exact fractions
NoteModifier.triplet.multiplier      // 2.0/3.0 (exact)
NoteModifier.doubleDotted.multiplier // 1.75
NoteModifier.septuplet.multiplier    // 4.0/7.0

Playgrounds

  • Clone the project and open it in Xcode.
  • Build the Mac target.
  • Open the Playground page in the project navigator.
  • Select the macOS platform and Build Active Scheme in Playground settings.

Unit Tests

45 tests covering all primitives. Run with swift test or ⌘U in Xcode.

AppStore

This library is battle-tested in production across iOS, macOS, watchOS and tvOS:
KeyBud (iOS, watchOS, tvOS, macOS)
FretBud (iOS, watchOS, tvOS)
ChordBud (iOS)
ArpBud (iOS)
ScaleBud (iOS, AUv3, M1)
StepBud (iOS, AUv3, M1)
RhythmBud (iOS, AUv3, M1)
ArpBud 2 (iOS, AUv3, M1)
ChordBud 2 (iOS, AUv3, M1)
LoopBud (iOS, AUv3, M1)
Euclid Goes to Party (iOS, AUv3, M1)
SnakeBud (iOS, AUv3, M1)
MelodyBud (iOS, AUv3, M1)
ScaleBud 2 (iOS, AUv3, M1)
ShiftBud (iOS, AUv3, M1)
PolyBud (iOS, AUv3, M1)
PatternBud (iOS, AUv3, M1)
MIDI Motion (iOS, watchOS)
Textquencer (iOS, AUv3, M1)
In Theory (iOS, AUv3, M1)
BrainBud (iOS, AUv3, M1)
Binarhythmic (iOS, AUv3, M1)
Auto Bass (iOS, AUv3, M1)
BounceBud (iOS, AUv3, M1)
MuseBud (iOS, AUv3, M1)
Auto Fills (iOS, AUv3, M1)
Kebarp (iOS, AUv3, M1)
FuncBud (iOS, AUv3, M1)
Note to Be (iOS, AUv3, M1)
Harmonicc (iOS, AUv3, M1)

评论

暂无评论