Documentation
¶
Overview ¶
Package songs provides built-in melodies for testing audio playback. All songs are defined using the beat-based notation system with tempo and time signature.
Index ¶
- Constants
- Variables
- func DurationSamples(durMs int, sampleRate int) int
- func DurationSamplesFormat(durMs int, format pcm.Format) int
- func GenerateChord(freqs []float64, samples int, sampleRate int, volume float64) []int16
- func GenerateRichNote(freq float64, samples int, sampleRate int, volume float64) []int16
- func GenerateSineWave(freq float64, samples int, sampleRate int) []byte
- func IDs() []string
- func Int16ToBytes(samples []int16) []byte
- func Names() []string
- func TotalDuration(melody []Note) int
- func VoiceToChunk(voice Voice, format pcm.Format, volume float64) pcm.Chunk
- type BeatNote
- type BeatVoice
- type Metronome
- type Note
- type RenderOptions
- type Song
- type Tempo
- type TimeSignature
- type Voice
Constants ¶
const ( // Octave 2 C2 = 65.0 D2 = 73.0 E2 = 82.0 F2 = 87.0 G2 = 98.0 A2 = 110.0 B2 = 123.0 // Octave 3 C3 = 131.0 D3 = 147.0 Eb3 = 156.0 // Eb3 / D#3 E3 = 165.0 F3 = 175.0 Fs3 = 185.0 // F#3 G3 = 196.0 Gs3 = 208.0 // G#3 A3 = 220.0 As3 = 233.0 // A#3 Bb3 = 233.0 // Bb3 (enharmonic with A#3) B3 = 247.0 // Octave 4 C4 = 262.0 Cs4 = 277.0 // C#4 / Db4 D4 = 294.0 Ds4 = 311.0 // D#4 Eb4 = 311.0 // Eb4 (enharmonic with D#4) E4 = 330.0 F4 = 349.0 Fs4 = 370.0 // F#4 G4 = 392.0 Gs4 = 415.0 // G#4 / Ab4 A4 = 440.0 As4 = 466.0 // A#4 Bb4 = 466.0 // Bb4 (enharmonic with A#4) B4 = 494.0 // Octave 5 C5 = 523.0 Cs5 = 554.0 // C#5 D5 = 587.0 Ds5 = 622.0 // D#5 Eb5 = 622.0 // Eb5 (enharmonic with D#5) E5 = 659.0 F5 = 698.0 Fs5 = 740.0 // F#5 G5 = 784.0 Gs5 = 831.0 // G#5 A5 = 880.0 As5 = 932.0 // A#5 / Bb5 B5 = 988.0 // Octave 6 C6 = 1047.0 Rest = 0.0 )
Note frequencies (Hz) - Extended range
const ( Whole = 4.0 // 全音符 Half = 2.0 // 二分音符 Quarter = 1.0 // 四分音符 Eighth = 0.5 // 八分音符 Sixteenth = 0.25 // 十六分音符 DotWhole = 6.0 // 附点全音符 DotHalf = 3.0 // 附点二分音符 DotQuarter = 1.5 // 附点四分音符 DotEighth = 0.75 // 附点八分音符 Triplet8 = 1.0 / 3 // 三连音八分音符 )
Note value constants (in terms of beats, quarter note = 1)
const Am = A3
Am is A minor root note (alias for readability)
const DefaultFormat = pcm.L16Mono16K
DefaultFormat is the default audio format for songs.
Variables ¶
var ( Time4_4 = TimeSignature{4, 4} // Common time (4/4) Time3_4 = TimeSignature{3, 4} // Waltz time (3/4) Time2_4 = TimeSignature{2, 4} // March time (2/4) Time6_8 = TimeSignature{6, 8} // Compound duple (6/8) )
Common time signatures
var All = []Song{ SongTwinkleStar, SongHappyBirthday, SongTwoTigers, SongDollAndBear, SongFurElise, SongCanon, SongCastleInTheSky, SongRiverFlowsInYou, SongDreamWedding, SongBachInvention1, SongBachMinuet, SongCanon3Voice, SongCzerny599No1, SongCzerny599No19, SongCzerny599No38, SongCzerny299No1, SongHanonNo1, SongBurgmullerArabesque, SongScaleC, SongScaleGMinor, SongSimpleWaltz, SongTarantella, }
All contains all built-in songs with tempo-based notation.
var SongBachInvention1 = Song{ ID: "bach_invention1", Name: "巴赫二部创意曲 No.1", Tempo: Tempo{BPM: 100, Signature: Time4_4}, Voices: func() []BeatVoice { soprano := BeatVoice{Notes: []BeatNote{ N(C4, Sixteenth), N(D4, Sixteenth), N(E4, Sixteenth), N(F4, Sixteenth), N(D4, Sixteenth), N(E4, Sixteenth), N(C4, Eighth), N(Rest, Eighth), N(G4, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(G4, Eighth), N(Rest, Eighth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(C5, Eighth), N(A4, Sixteenth), N(G4, Sixteenth), N(F4, Sixteenth), N(E4, Sixteenth), N(F4, Sixteenth), N(A4, Sixteenth), N(G4, Quarter), N(G4, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(G4, Eighth), N(Rest, Eighth), N(D5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(G5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(D5, Eighth), N(E5, Quarter), N(D5, Quarter), N(C5, Quarter), N(B4, Quarter), N(C5, Half), }} bass := BeatVoice{Notes: []BeatNote{ N(Rest, DotQuarter), N(C3, Sixteenth), N(D3, Sixteenth), N(E3, Sixteenth), N(F3, Sixteenth), N(D3, Sixteenth), N(E3, Sixteenth), N(C3, Eighth), N(Rest, Eighth), N(G3, Sixteenth), N(A3, Sixteenth), N(B3, Sixteenth), N(C4, Sixteenth), N(A3, Sixteenth), N(B3, Sixteenth), N(G3, Eighth), N(Rest, Eighth), N(E3, Sixteenth), N(F3, Sixteenth), N(G3, Sixteenth), N(A3, Sixteenth), N(F3, Sixteenth), N(G3, Sixteenth), N(E3, Eighth), N(F3, Sixteenth), N(E3, Sixteenth), N(D3, Sixteenth), N(C3, Sixteenth), N(D3, Sixteenth), N(F3, Sixteenth), N(E3, Quarter), N(E3, Sixteenth), N(F3, Sixteenth), N(G3, Sixteenth), N(A3, Sixteenth), N(F3, Sixteenth), N(G3, Sixteenth), N(E3, Eighth), N(Rest, Eighth), N(B3, Sixteenth), N(C4, Sixteenth), N(D4, Sixteenth), N(E4, Sixteenth), N(C4, Sixteenth), N(D4, Sixteenth), N(B3, Eighth), N(C4, Quarter), N(G3, Quarter), N(E3, Quarter), N(G3, Quarter), N(C3, Half), }} return []BeatVoice{soprano, bass} }, }
SongBachInvention1 - 巴赫二部创意曲 No.1 (BWV 772)
var SongBachMinuet = Song{ ID: "bach_minuet", Name: "巴赫小步舞曲", Tempo: Tempo{BPM: 110, Signature: Time3_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(D5, Quarter), N(G4, Quarter), N(A4, Quarter), N(B4, Quarter), N(C5, Quarter), N(D5, Quarter), N(G4, Half), N(G4, Quarter), N(E5, Quarter), N(C5, Quarter), N(D5, Quarter), N(E5, Quarter), N(Fs5, Quarter), N(G5, Quarter), N(G4, Half), N(G4, Quarter), N(C5, Quarter), N(D5, Quarter), N(C5, Quarter), N(B4, Quarter), N(A4, Quarter), N(B4, Quarter), N(A4, Half), N(D4, Quarter), N(D5, Quarter), N(G4, Quarter), N(A4, Quarter), N(B4, Quarter), N(C5, Quarter), N(D5, Quarter), N(G4, Half), N(G4, Quarter), N(E5, Quarter), N(C5, Quarter), N(D5, Quarter), N(E5, Quarter), N(Fs5, Quarter), N(G5, Quarter), N(G4, Half), N(G4, Quarter), N(B4, Quarter), N(G4, Quarter), N(A4, Quarter), N(B4, Quarter), N(G4, Quarter), N(Fs4, Quarter), N(G4, DotHalf), }} bass := BeatVoice{Notes: []BeatNote{ N(G3, Half), N(Rest, Quarter), N(G3, Half), N(Rest, Quarter), N(B3, Half), N(Rest, Quarter), N(C4, Half), N(Rest, Quarter), N(D4, Half), N(Rest, Quarter), N(B3, Half), N(Rest, Quarter), N(C4, Half), N(Rest, Quarter), N(D4, Half), N(Rest, Quarter), N(D3, DotHalf), N(G3, Half), N(Rest, Quarter), N(G3, Half), N(Rest, Quarter), N(E3, Half), N(Rest, Quarter), N(C4, Half), N(Rest, Quarter), N(D4, Half), N(Rest, Quarter), N(B3, Half), N(Rest, Quarter), N(E3, Half), N(Rest, Quarter), N(D3, Half), N(Rest, Quarter), N(G3, DotHalf), }} return []BeatVoice{melody, bass} }, }
SongBachMinuet - 巴赫小步舞曲 (BWV Anh. 114)
var SongBurgmullerArabesque = Song{ ID: "burgmuller_arabesque", Name: "阿拉伯风格曲", Tempo: Tempo{BPM: 130, Signature: Time2_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Eighth), N(Rest, Eighth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(A4, Eighth), N(Rest, Eighth), N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(A4, Sixteenth), N(Gs4, Sixteenth), N(A4, Quarter), N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Eighth), N(Rest, Eighth), N(E5, Sixteenth), N(F5, Sixteenth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Eighth), N(Rest, Eighth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(G5, Sixteenth), N(F5, Sixteenth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(A4, Quarter), }} accomp := BeatVoice{Notes: []BeatNote{ N(A3, Quarter), N(A3, Eighth), N(Rest, Eighth), N(A3, Quarter), N(A3, Eighth), N(Rest, Eighth), N(A3, Quarter), N(E3, Quarter), N(A3, Half), N(A3, Quarter), N(A3, Eighth), N(Rest, Eighth), N(C4, Quarter), N(C4, Eighth), N(Rest, Eighth), N(G3, Quarter), N(G3, Quarter), N(A3, Half), }} return []BeatVoice{melody, accomp} }, }
SongBurgmullerArabesque - 布格缪勒 阿拉伯风格曲 Op.100 No.2
var SongCanon = Song{ ID: "canon", Name: "卡农", Tempo: Tempo{BPM: 60, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(Fs5, Half), N(E5, Half), N(D5, Half), N(Cs5, Half), N(B4, Half), N(A4, Half), N(B4, Half), N(Cs5, Half), N(D5, Quarter), N(Fs5, Quarter), N(A5, Quarter), N(G5, Quarter), N(Fs5, Quarter), N(D5, Quarter), N(Fs5, Quarter), N(E5, Quarter), N(D5, Quarter), N(B4, Quarter), N(D5, Quarter), N(A4, Quarter), N(G4, Quarter), N(B4, Quarter), N(A4, Quarter), N(G4, Quarter), N(Fs4, Quarter), N(D4, Quarter), N(E4, Quarter), N(Fs4, Quarter), N(G4, Quarter), N(A4, Quarter), N(B4, Quarter), N(G4, Quarter), N(Fs4, Half), N(D5, Half), N(D5, Whole), }} bass := BeatVoice{Notes: []BeatNote{ N(D3, Half), N(A3, Half), N(B3, Half), N(Fs3, Half), N(G3, Half), N(D3, Half), N(G3, Half), N(A3, Half), N(D3, Half), N(A3, Half), N(B3, Half), N(Fs3, Half), N(G3, Half), N(D3, Half), N(G3, Half), N(A3, Half), N(D3, Half), N(A3, Half), N(B3, Half), N(Fs3, Half), N(G3, Half), N(D3, Half), N(D3, Whole), }} return []BeatVoice{melody, bass} }, }
SongCanon - 卡农 (Pachelbel's Canon in D)
var SongCanon3Voice = Song{ ID: "canon_3voice", Name: "卡农三声部", Tempo: Tempo{BPM: 60, Signature: Time4_4}, Voices: func() []BeatVoice { voice1 := BeatVoice{Notes: []BeatNote{ N(Fs5, Half), N(E5, Half), N(D5, Half), N(Cs5, Half), N(B4, Half), N(A4, Half), N(B4, Half), N(Cs5, Half), N(D5, Quarter), N(Fs5, Quarter), N(A5, Quarter), N(G5, Quarter), N(Fs5, Quarter), N(D5, Quarter), N(Fs5, Quarter), N(E5, Quarter), N(D5, Quarter), N(B4, Quarter), N(D5, Quarter), N(A4, Quarter), N(G4, Quarter), N(B4, Quarter), N(A4, Quarter), N(G4, Quarter), N(Fs4, Quarter), N(D4, Quarter), N(E4, Quarter), N(Fs4, Quarter), N(G4, Quarter), N(A4, Quarter), N(B4, Quarter), N(G4, Quarter), N(Fs4, Half), N(D5, Half), N(D5, Whole), }} voice2 := BeatVoice{Notes: []BeatNote{ N(Rest, Whole), N(Rest, Whole), N(Fs5, Half), N(E5, Half), N(D5, Half), N(Cs5, Half), N(B4, Half), N(A4, Half), N(B4, Half), N(Cs5, Half), N(D5, Quarter), N(Fs5, Quarter), N(A5, Quarter), N(G5, Quarter), N(Fs5, Quarter), N(D5, Quarter), N(Fs5, Quarter), N(E5, Quarter), N(D5, Half), N(A4, Half), N(A4, Whole), }} voice3 := BeatVoice{Notes: []BeatNote{ N(D3, Half), N(A3, Half), N(B3, Half), N(Fs3, Half), N(G3, Half), N(D3, Half), N(G3, Half), N(A3, Half), N(D3, Half), N(A3, Half), N(B3, Half), N(Fs3, Half), N(G3, Half), N(D3, Half), N(G3, Half), N(A3, Half), N(D3, Half), N(A3, Half), N(B3, Half), N(Fs3, Half), N(G3, Half), N(D3, Half), N(D3, Whole), }} return []BeatVoice{voice1, voice2, voice3} }, }
SongCanon3Voice - 卡农三声部
var SongCastleInTheSky = Song{ ID: "castle_in_sky", Name: "天空之城", Tempo: Tempo{BPM: 80, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(A4, Quarter), N(B4, Eighth), N(C5, DotQuarter), N(B4, Quarter), N(C5, Quarter), N(E5, Half), N(Rest, Eighth), N(G4, Eighth), N(A4, Quarter), N(G4, Eighth), N(A4, Eighth), N(C5, Half), N(Rest, Eighth), N(G4, Quarter), N(E4, Quarter), N(E4, Eighth), N(D4, Eighth), N(E4, DotHalf), N(Rest, Quarter), N(A4, Quarter), N(B4, Eighth), N(C5, DotQuarter), N(B4, Quarter), N(C5, Quarter), N(E5, Half), N(Rest, Eighth), N(G4, Eighth), N(A4, Quarter), N(G4, Eighth), N(A4, Eighth), N(C5, Half), N(Rest, Eighth), N(G4, Quarter), N(E4, Quarter), N(D4, Eighth), N(C4, Eighth), N(D4, DotHalf), N(Rest, Quarter), N(E5, Quarter), N(E5, Eighth), N(E5, Quarter), N(B4, Eighth), N(C5, Half), N(C5, Quarter), N(C5, Eighth), N(C5, Eighth), N(B4, Eighth), N(A4, Half), N(Rest, Eighth), N(A4, Quarter), N(C5, Quarter), N(B4, Eighth), N(B4, Eighth), N(E4, Half), N(A4, DotHalf), N(Rest, Quarter), }} accomp := BeatVoice{Notes: []BeatNote{ N(A3, Quarter), N(E4, Eighth), N(A4, Eighth), N(E4, Quarter), N(A3, Quarter), N(E4, Eighth), N(A4, Eighth), N(E4, Quarter), N(F3, Quarter), N(C4, Eighth), N(F4, Eighth), N(C4, Quarter), N(C3, Quarter), N(G3, Eighth), N(C4, Eighth), N(G3, Quarter), N(Am, Quarter), N(E4, Eighth), N(A4, Eighth), N(E4, Quarter), N(E3, Quarter), N(B3, Eighth), N(E4, Eighth), N(B3, Quarter), N(A3, Half), N(Rest, Half), N(A3, Quarter), N(E4, Eighth), N(A4, Eighth), N(E4, Quarter), N(A3, Quarter), N(E4, Eighth), N(A4, Eighth), N(E4, Quarter), N(F3, Quarter), N(C4, Eighth), N(F4, Eighth), N(C4, Quarter), N(C3, Quarter), N(G3, Eighth), N(C4, Eighth), N(G3, Quarter), N(G3, Quarter), N(D4, Eighth), N(G4, Eighth), N(D4, Quarter), N(G3, Quarter), N(D4, Eighth), N(G4, Eighth), N(D4, Quarter), N(Rest, Whole), N(A3, Half), N(E3, Half), N(F3, Half), N(C3, Half), N(A3, Half), N(E3, Half), N(A3, DotHalf), N(Rest, Quarter), }} return []BeatVoice{melody, accomp} }, }
SongCastleInTheSky - 天空之城 (Laputa: Castle in the Sky)
var SongCzerny299No1 = Song{ ID: "czerny_299_1", Name: "车尔尼 299-1", Tempo: Tempo{BPM: 140, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(G5, Sixteenth), N(F5, Sixteenth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(G5, Sixteenth), N(A5, Sixteenth), N(B5, Sixteenth), N(C6, Sixteenth), N(C6, Sixteenth), N(B5, Sixteenth), N(A5, Sixteenth), N(G5, Sixteenth), N(F5, Sixteenth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(F5, Sixteenth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(C5, Sixteenth), N(E5, Sixteenth), N(G5, Sixteenth), N(E5, Sixteenth), N(C5, Sixteenth), N(E5, Sixteenth), N(G5, Sixteenth), N(E5, Sixteenth), N(C5, Sixteenth), N(E5, Sixteenth), N(G5, Sixteenth), N(C6, Sixteenth), N(G5, Sixteenth), N(E5, Sixteenth), N(C5, Sixteenth), N(G4, Sixteenth), N(D5, Sixteenth), N(F5, Sixteenth), N(A5, Sixteenth), N(F5, Sixteenth), N(D5, Sixteenth), N(F5, Sixteenth), N(A5, Sixteenth), N(F5, Sixteenth), N(G4, Sixteenth), N(B4, Sixteenth), N(D5, Sixteenth), N(G5, Sixteenth), N(D5, Sixteenth), N(B4, Sixteenth), N(G4, Sixteenth), N(D4, Sixteenth), N(C5, Eighth), N(E5, Eighth), N(G5, Quarter), N(C6, Half), N(G5, Quarter), N(E5, Quarter), N(C5, Half), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Eighth), N(G3, Eighth), N(E3, Eighth), N(G3, Eighth), N(C3, Eighth), N(G3, Eighth), N(E3, Eighth), N(G3, Eighth), N(C3, Eighth), N(G3, Eighth), N(E3, Eighth), N(G3, Eighth), N(C3, Eighth), N(G3, Eighth), N(E3, Eighth), N(G3, Eighth), N(C3, Eighth), N(G3, Eighth), N(E3, Eighth), N(G3, Eighth), N(C3, Eighth), N(G3, Eighth), N(E3, Eighth), N(G3, Eighth), N(D3, Eighth), N(A3, Eighth), N(F3, Eighth), N(A3, Eighth), N(G3, Eighth), N(D4, Eighth), N(B3, Eighth), N(D4, Eighth), N(C3, Quarter), N(E3, Quarter), N(G3, Quarter), N(C4, Quarter), N(G3, Quarter), N(E3, Quarter), N(C3, Half), }} return []BeatVoice{melody, accomp} }, }
SongCzerny299No1 - 车尔尼 Op.299 No.1 (快速练习曲)
var SongCzerny599No1 = Song{ ID: "czerny_599_1", Name: "车尔尼 599-1", Tempo: Tempo{BPM: 100, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Quarter), N(D4, Quarter), N(E4, Quarter), N(F4, Quarter), N(G4, Quarter), N(A4, Quarter), N(B4, Quarter), N(C5, Quarter), N(C5, Quarter), N(B4, Quarter), N(A4, Quarter), N(G4, Quarter), N(F4, Quarter), N(E4, Quarter), N(D4, Quarter), N(C4, Quarter), N(C4, Eighth), N(E4, Eighth), N(D4, Eighth), N(F4, Eighth), N(E4, Eighth), N(G4, Eighth), N(F4, Eighth), N(A4, Eighth), N(G4, Eighth), N(B4, Eighth), N(A4, Eighth), N(C5, Eighth), N(B4, Eighth), N(D5, Eighth), N(C5, Quarter), N(G4, Quarter), N(E4, Quarter), N(D4, Quarter), N(B3, Quarter), N(C4, Whole), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Whole), N(C3, Whole), N(C3, Whole), N(C3, Whole), N(C3, Half), N(G3, Half), N(C3, Half), N(G3, Half), N(G3, Half), N(G3, Half), N(C3, Whole), }} return []BeatVoice{melody, accomp} }, }
SongCzerny599No1 - 车尔尼 Op.599 No.1 (初学者练习曲)
var SongCzerny599No19 = Song{ ID: "czerny_599_19", Name: "车尔尼 599-19", Tempo: Tempo{BPM: 120, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Eighth), N(D4, Eighth), N(E4, Eighth), N(F4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Eighth), N(D4, Eighth), N(C4, Eighth), N(E4, Eighth), N(G4, Eighth), N(E4, Eighth), N(C5, Eighth), N(G4, Eighth), N(E4, Eighth), N(C4, Eighth), N(D4, Eighth), N(E4, Eighth), N(F4, Eighth), N(G4, Eighth), N(A4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Eighth), N(D4, Eighth), N(F4, Eighth), N(A4, Eighth), N(F4, Eighth), N(D5, Eighth), N(A4, Eighth), N(F4, Eighth), N(D4, Eighth), N(E4, Eighth), N(F4, Eighth), N(G4, Eighth), N(A4, Eighth), N(B4, Eighth), N(A4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Eighth), N(G4, Eighth), N(B4, Eighth), N(G4, Eighth), N(E5, Eighth), N(B4, Eighth), N(G4, Eighth), N(E4, Eighth), N(F4, Eighth), N(A4, Eighth), N(C5, Eighth), N(A4, Eighth), N(G4, Eighth), N(B4, Eighth), N(D5, Eighth), N(B4, Eighth), N(C5, Half), N(C4, Half), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Quarter), N(E3, Quarter), N(G3, Quarter), N(E3, Quarter), N(C3, Quarter), N(E3, Quarter), N(G3, Quarter), N(E3, Quarter), N(D3, Quarter), N(F3, Quarter), N(A3, Quarter), N(F3, Quarter), N(D3, Quarter), N(F3, Quarter), N(A3, Quarter), N(F3, Quarter), N(E3, Quarter), N(G3, Quarter), N(B3, Quarter), N(G3, Quarter), N(E3, Quarter), N(G3, Quarter), N(B3, Quarter), N(G3, Quarter), N(F3, Quarter), N(A3, Quarter), N(G3, Quarter), N(B3, Quarter), N(C3, Half), N(C3, Half), }} return []BeatVoice{melody, accomp} }, }
SongCzerny599No19 - 车尔尼 Op.599 No.19 (八分音符练习)
var SongCzerny599No38 = Song{ ID: "czerny_599_38", Name: "车尔尼 599-38", Tempo: Tempo{BPM: 90, Signature: Time4_4}, Voices: func() []BeatVoice { t := 1.0 / 3.0 melody := BeatVoice{Notes: []BeatNote{ N(C4, t), N(E4, t), N(G4, t), N(C5, t), N(G4, t), N(E4, t), N(C4, t), N(E4, t), N(G4, t), N(C5, t), N(G4, t), N(E4, t), N(D4, t), N(F4, t), N(A4, t), N(D5, t), N(A4, t), N(F4, t), N(D4, t), N(F4, t), N(A4, t), N(D5, t), N(A4, t), N(F4, t), N(E4, t), N(G4, t), N(B4, t), N(E5, t), N(B4, t), N(G4, t), N(E4, t), N(G4, t), N(B4, t), N(E5, t), N(B4, t), N(G4, t), N(F4, t), N(A4, t), N(C5, t), N(F5, t), N(C5, t), N(A4, t), N(G4, t), N(B4, t), N(D5, t), N(G5, t), N(D5, t), N(B4, t), N(C5, t), N(G4, t), N(E4, t), N(C4, t), N(E4, t), N(G4, t), N(C5, t), N(G4, t), N(E4, t), N(C4, t), N(E4, t), N(G4, t), N(B4, t), N(G4, t), N(D4, t), N(B3, t), N(D4, t), N(G4, t), N(B4, t), N(G4, t), N(D4, t), N(B3, t), N(D4, t), N(G4, t), N(C4, t), N(E4, t), N(G4, t), N(C5, t), N(E5, t), N(G5, t), N(G4, t), N(B4, t), N(D5, t), N(G5, t), N(D5, t), N(B4, t), N(C5, Whole), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Whole), N(D3, Whole), N(E3, Whole), N(F3, Half), N(G3, Half), N(C3, Whole), N(G3, Whole), N(C3, Half), N(G3, Half), N(C3, Whole), }} return []BeatVoice{melody, accomp} }, }
SongCzerny599No38 - 车尔尼 Op.599 No.38 (三连音练习)
var SongDollAndBear = Song{ ID: "doll_and_bear", Name: "洋娃娃和小熊跳舞", Tempo: Tempo{BPM: 132, Signature: Time2_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Eighth), N(D4, Eighth), N(E4, Eighth), N(C4, Eighth), N(E4, Eighth), N(C4, Eighth), N(E4, Quarter), N(D4, Eighth), N(E4, Eighth), N(F4, Eighth), N(F4, Eighth), N(E4, Eighth), N(D4, Eighth), N(E4, Quarter), N(C4, Eighth), N(D4, Eighth), N(E4, Eighth), N(C4, Eighth), N(E4, Eighth), N(C4, Eighth), N(E4, Quarter), N(D4, Eighth), N(E4, Eighth), N(F4, Eighth), N(E4, Eighth), N(D4, Quarter), N(C4, Quarter), N(G4, Eighth), N(G4, Eighth), N(E4, Eighth), N(G4, Eighth), N(F4, Eighth), N(F4, Eighth), N(D4, Quarter), N(E4, Eighth), N(F4, Eighth), N(E4, Eighth), N(C4, Eighth), N(D4, Quarter), N(Rest, Quarter), N(G4, Eighth), N(G4, Eighth), N(E4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Eighth), N(D4, Quarter), N(C4, Eighth), N(D4, Eighth), N(E4, Eighth), N(D4, Eighth), N(C4, Half), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Quarter), N(G3, Quarter), N(C3, Quarter), N(G3, Quarter), N(G3, Quarter), N(D3, Quarter), N(C3, Quarter), N(G3, Quarter), N(C3, Quarter), N(G3, Quarter), N(C3, Quarter), N(G3, Quarter), N(G3, Quarter), N(D3, Quarter), N(C3, Half), N(C3, Quarter), N(G3, Quarter), N(D3, Quarter), N(G3, Quarter), N(C3, Quarter), N(G3, Quarter), N(G3, Half), N(C3, Quarter), N(G3, Quarter), N(G3, Quarter), N(D3, Quarter), N(C3, Quarter), N(G3, Quarter), N(C3, Half), }} return []BeatVoice{melody, accomp} }, }
SongDollAndBear - 洋娃娃和小熊跳舞 (Doll and Bear Dancing)
var SongDreamWedding = Song{ ID: "dream_wedding", Name: "梦中的婚礼", Tempo: Tempo{BPM: 70, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(E5, Quarter), N(E5, Eighth), N(D5, Eighth), N(E5, Half), N(E5, Quarter), N(E5, Eighth), N(F5, Eighth), N(E5, Quarter), N(D5, Quarter), N(C5, Quarter), N(B4, Eighth), N(A4, Eighth), N(B4, Half), N(Rest, Whole), N(E5, Quarter), N(E5, Eighth), N(D5, Eighth), N(E5, Half), N(E5, Quarter), N(E5, Eighth), N(F5, Eighth), N(E5, Quarter), N(D5, Quarter), N(C5, Quarter), N(D5, Quarter), N(E5, Quarter), N(C5, Quarter), N(A4, Whole), }} accomp := BeatVoice{Notes: []BeatNote{ N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(G3, Eighth), N(D4, Eighth), N(G4, Eighth), N(D4, Eighth), N(G3, Eighth), N(D4, Eighth), N(G4, Eighth), N(D4, Eighth), N(F3, Eighth), N(C4, Eighth), N(F4, Eighth), N(C4, Eighth), N(F3, Eighth), N(C4, Eighth), N(F4, Eighth), N(C4, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(G3, Eighth), N(D4, Eighth), N(G4, Eighth), N(D4, Eighth), N(G3, Eighth), N(D4, Eighth), N(G4, Eighth), N(D4, Eighth), N(F3, Eighth), N(C4, Eighth), N(F4, Eighth), N(C4, Eighth), N(G3, Eighth), N(D4, Eighth), N(G4, Eighth), N(D4, Eighth), N(A3, Whole), }} return []BeatVoice{melody, accomp} }, }
SongDreamWedding - 梦中的婚礼 (Mariage d'Amour)
var SongFurElise = Song{ ID: "fur_elise", Name: "献给爱丽丝", Tempo: Tempo{BPM: 140, Signature: Time3_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(E5, Eighth), N(Ds5, Eighth), N(E5, Eighth), N(Ds5, Eighth), N(E5, Eighth), N(B4, Eighth), N(D5, Eighth), N(C5, Eighth), N(A4, Quarter), N(Rest, Eighth), N(C4, Eighth), N(E4, Eighth), N(A4, Eighth), N(B4, Quarter), N(Rest, Eighth), N(E4, Eighth), N(Gs4, Eighth), N(B4, Eighth), N(C5, Quarter), N(Rest, Eighth), N(E4, Eighth), N(E5, Eighth), N(Ds5, Eighth), N(E5, Eighth), N(Ds5, Eighth), N(E5, Eighth), N(B4, Eighth), N(D5, Eighth), N(C5, Eighth), N(A4, Quarter), N(Rest, Eighth), N(C4, Eighth), N(E4, Eighth), N(A4, Eighth), N(B4, Quarter), N(Rest, Eighth), N(E4, Eighth), N(C5, Eighth), N(B4, Eighth), N(A4, DotQuarter), N(Rest, DotQuarter), }} accomp := BeatVoice{Notes: []BeatNote{ N(Rest, DotHalf), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(Rest, DotQuarter), N(E3, Eighth), N(E4, Eighth), N(Gs4, Eighth), N(Rest, DotQuarter), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(Rest, DotQuarter), N(Rest, DotHalf), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(Rest, DotQuarter), N(E3, Eighth), N(E4, Eighth), N(Gs4, Eighth), N(Rest, DotQuarter), N(A3, DotQuarter), N(Rest, DotQuarter), }} return []BeatVoice{melody, accomp} }, }
SongFurElise - 献给爱丽丝 (Für Elise)
var SongHanonNo1 = Song{ ID: "hanon_1", Name: "哈农练习 1", Tempo: Tempo{BPM: 100, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Sixteenth), N(E4, Sixteenth), N(F4, Sixteenth), N(G4, Sixteenth), N(A4, Sixteenth), N(G4, Sixteenth), N(F4, Sixteenth), N(E4, Sixteenth), N(D4, Sixteenth), N(F4, Sixteenth), N(G4, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(A4, Sixteenth), N(G4, Sixteenth), N(F4, Sixteenth), N(E4, Sixteenth), N(G4, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(A4, Sixteenth), N(G4, Sixteenth), N(F4, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(A4, Sixteenth), N(G4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(D5, Sixteenth), N(E5, Sixteenth), N(D5, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(A4, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(A4, Sixteenth), N(G4, Sixteenth), N(A4, Sixteenth), N(B4, Sixteenth), N(C5, Sixteenth), N(B4, Sixteenth), N(G4, Sixteenth), N(F4, Sixteenth), N(E4, Sixteenth), N(D4, Sixteenth), N(E4, Sixteenth), N(F4, Sixteenth), N(G4, Sixteenth), N(A4, Sixteenth), N(F4, Sixteenth), N(E4, Sixteenth), N(D4, Sixteenth), N(C4, Quarter), N(Rest, Quarter), N(C4, Half), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Sixteenth), N(E3, Sixteenth), N(F3, Sixteenth), N(G3, Sixteenth), N(A3, Sixteenth), N(G3, Sixteenth), N(F3, Sixteenth), N(E3, Sixteenth), N(D3, Sixteenth), N(F3, Sixteenth), N(G3, Sixteenth), N(A3, Sixteenth), N(B3, Sixteenth), N(A3, Sixteenth), N(G3, Sixteenth), N(F3, Sixteenth), N(E3, Sixteenth), N(G3, Sixteenth), N(A3, Sixteenth), N(B3, Sixteenth), N(C4, Sixteenth), N(B3, Sixteenth), N(A3, Sixteenth), N(G3, Sixteenth), N(F3, Sixteenth), N(A3, Sixteenth), N(B3, Sixteenth), N(C4, Sixteenth), N(D4, Sixteenth), N(C4, Sixteenth), N(B3, Sixteenth), N(A3, Sixteenth), N(G3, Sixteenth), N(B3, Sixteenth), N(C4, Sixteenth), N(D4, Sixteenth), N(E4, Sixteenth), N(D4, Sixteenth), N(C4, Sixteenth), N(B3, Sixteenth), N(A3, Sixteenth), N(C4, Sixteenth), N(B3, Sixteenth), N(A3, Sixteenth), N(G3, Sixteenth), N(A3, Sixteenth), N(B3, Sixteenth), N(C4, Sixteenth), N(B3, Sixteenth), N(G3, Sixteenth), N(F3, Sixteenth), N(E3, Sixteenth), N(D3, Sixteenth), N(E3, Sixteenth), N(F3, Sixteenth), N(G3, Sixteenth), N(A3, Sixteenth), N(F3, Sixteenth), N(E3, Sixteenth), N(D3, Sixteenth), N(C3, Quarter), N(Rest, Quarter), N(C3, Half), }} return []BeatVoice{melody, accomp} }, }
SongHanonNo1 - 哈农指法练习 No.1
var SongHappyBirthday = Song{ ID: "happy_birthday", Name: "生日快乐", Tempo: Tempo{BPM: 120, Signature: Time3_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Eighth), N(C4, Eighth), N(D4, Quarter), N(C4, Quarter), N(F4, Quarter), N(E4, Half), N(C4, Eighth), N(C4, Eighth), N(D4, Quarter), N(C4, Quarter), N(G4, Quarter), N(F4, Half), N(C4, Eighth), N(C4, Eighth), N(C5, Quarter), N(A4, Quarter), N(F4, Quarter), N(E4, Quarter), N(D4, Half), N(As4, Eighth), N(As4, Eighth), N(A4, Quarter), N(F4, Quarter), N(G4, Quarter), N(F4, DotHalf), }} accomp := BeatVoice{Notes: []BeatNote{ N(Rest, Quarter), N(F3, Quarter), N(A3, Quarter), N(C4, Quarter), N(C3, Quarter), N(G3, Quarter), N(C4, Quarter), N(Rest, Quarter), N(F3, Quarter), N(A3, Quarter), N(C4, Quarter), N(C3, Quarter), N(G3, Quarter), N(C4, Quarter), N(Rest, Quarter), N(F3, Quarter), N(A3, Quarter), N(C4, Quarter), N(E3, Quarter), N(G3, Quarter), N(C4, Quarter), N(D3, Quarter), N(F3, Quarter), N(A3, Quarter), N(Rest, Quarter), N(As3, Quarter), N(D4, Quarter), N(F4, Quarter), N(F3, Quarter), N(A3, Quarter), N(C4, Quarter), N(F3, DotHalf), }} return []BeatVoice{melody, accomp} }, }
SongHappyBirthday - 生日快乐 (Happy Birthday)
var SongRiverFlowsInYou = Song{ ID: "river_flows", Name: "River Flows in You", Tempo: Tempo{BPM: 70, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(A4, Quarter), N(E5, Quarter), N(Fs5, Quarter), N(E5, Quarter), N(A4, Quarter), N(E5, Quarter), N(Fs5, Quarter), N(E5, Quarter), N(Gs4, Quarter), N(E5, Quarter), N(Fs5, Quarter), N(E5, Quarter), N(Gs4, Quarter), N(E5, Quarter), N(Fs5, Quarter), N(E5, Quarter), N(Fs5, DotQuarter), N(E5, Eighth), N(Cs5, Eighth), N(E5, DotQuarter), N(Fs5, Eighth), N(E5, Eighth), N(Cs5, DotQuarter), N(B4, Eighth), N(A4, Eighth), N(B4, DotQuarter), N(Cs5, Eighth), N(B4, Eighth), N(A4, Half), N(Gs4, Quarter), N(A4, Quarter), N(B4, Half), N(Cs5, DotQuarter), N(B4, Eighth), N(A4, Eighth), N(B4, DotQuarter), N(Cs5, Eighth), N(B4, Eighth), N(A4, DotQuarter), N(Gs4, Eighth), N(A4, Eighth), N(B4, DotQuarter), N(A4, Eighth), N(Gs4, Eighth), N(Fs4, Half), N(E4, Half), N(Fs4, Whole), }} accomp := BeatVoice{Notes: []BeatNote{ N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(Fs3, Eighth), N(Cs4, Eighth), N(Fs4, Eighth), N(Cs4, Eighth), N(Fs3, Eighth), N(Cs4, Eighth), N(Fs4, Eighth), N(Cs4, Eighth), N(Fs3, Eighth), N(Cs4, Eighth), N(Fs4, Eighth), N(Cs4, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(Fs3, Eighth), N(Cs4, Eighth), N(Fs4, Eighth), N(Cs4, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(A3, Eighth), N(E4, Eighth), N(A4, Eighth), N(E4, Eighth), N(E3, Eighth), N(B3, Eighth), N(E4, Eighth), N(B3, Eighth), N(A3, Whole), N(A3, Whole), }} return []BeatVoice{melody, accomp} }, }
SongRiverFlowsInYou - River Flows in You (Yiruma)
var SongScaleC = Song{ ID: "scale_c_major", Name: "C大调音阶", Tempo: Tempo{BPM: 120, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Eighth), N(D4, Eighth), N(E4, Eighth), N(F4, Eighth), N(G4, Eighth), N(A4, Eighth), N(B4, Eighth), N(C5, Eighth), N(D5, Eighth), N(E5, Eighth), N(F5, Eighth), N(G5, Eighth), N(A5, Eighth), N(B5, Eighth), N(C6, Quarter), N(C6, Eighth), N(B5, Eighth), N(A5, Eighth), N(G5, Eighth), N(F5, Eighth), N(E5, Eighth), N(D5, Eighth), N(C5, Eighth), N(B4, Eighth), N(A4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Eighth), N(D4, Eighth), N(C4, Quarter), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Eighth), N(D3, Eighth), N(E3, Eighth), N(F3, Eighth), N(G3, Eighth), N(A3, Eighth), N(B3, Eighth), N(C4, Eighth), N(D4, Eighth), N(E4, Eighth), N(F4, Eighth), N(G4, Eighth), N(A4, Eighth), N(B4, Eighth), N(C5, Quarter), N(C5, Eighth), N(B4, Eighth), N(A4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Eighth), N(D4, Eighth), N(C4, Eighth), N(B3, Eighth), N(A3, Eighth), N(G3, Eighth), N(F3, Eighth), N(E3, Eighth), N(D3, Eighth), N(C3, Quarter), }} return []BeatVoice{melody, accomp} }, }
SongScaleC - C大调音阶练习
var SongScaleGMinor = Song{ ID: "scale_g_minor", Name: "G小调音阶", Tempo: Tempo{BPM: 110, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(G4, Eighth), N(A4, Eighth), N(Bb4, Eighth), N(C5, Eighth), N(D5, Eighth), N(Eb5, Eighth), N(Fs5, Eighth), N(G5, Eighth), N(G5, Quarter), N(Rest, Quarter), N(G5, Eighth), N(Fs5, Eighth), N(Eb5, Eighth), N(D5, Eighth), N(C5, Eighth), N(Bb4, Eighth), N(A4, Eighth), N(G4, Eighth), N(G4, Half), }} accomp := BeatVoice{Notes: []BeatNote{ N(G3, Eighth), N(A3, Eighth), N(Bb3, Eighth), N(C4, Eighth), N(D4, Eighth), N(Eb4, Eighth), N(Fs4, Eighth), N(G4, Eighth), N(G4, Quarter), N(Rest, Quarter), N(G4, Eighth), N(Fs4, Eighth), N(Eb4, Eighth), N(D4, Eighth), N(C4, Eighth), N(Bb3, Eighth), N(A3, Eighth), N(G3, Eighth), N(G3, Half), }} return []BeatVoice{melody, accomp} }, }
SongScaleGMinor - G小调音阶练习 (harmonic minor)
var SongSimpleWaltz = Song{ ID: "simple_waltz", Name: "简单圆舞曲", Tempo: Tempo{BPM: 120, Signature: Time3_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(E5, DotQuarter), N(D5, Eighth), N(C5, Quarter), N(D5, DotQuarter), N(E5, Eighth), N(D5, Quarter), N(C5, DotQuarter), N(B4, Eighth), N(A4, Quarter), N(B4, Half), N(Rest, Quarter), N(E5, DotQuarter), N(D5, Eighth), N(C5, Quarter), N(D5, DotQuarter), N(E5, Eighth), N(D5, Quarter), N(C5, Half), N(B4, Quarter), N(C5, DotHalf), }} bass := BeatVoice{Notes: []BeatNote{ N(C3, Quarter), N(E4, Quarter), N(G4, Quarter), N(G3, Quarter), N(D4, Quarter), N(G4, Quarter), N(A3, Quarter), N(E4, Quarter), N(A4, Quarter), N(E3, Quarter), N(Gs3, Quarter), N(B3, Quarter), N(C3, Quarter), N(E4, Quarter), N(G4, Quarter), N(G3, Quarter), N(D4, Quarter), N(G4, Quarter), N(F3, Quarter), N(A3, Quarter), N(C4, Quarter), N(C3, DotHalf), }} return []BeatVoice{melody, bass} }, }
SongSimpleWaltz - 简单圆舞曲
var SongTarantella = Song{ ID: "tarantella", Name: "塔兰泰拉舞曲", Tempo: Tempo{BPM: 140, Signature: Time6_8}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(A4, Eighth), N(C5, Eighth), N(E5, Eighth), N(A5, Eighth), N(E5, Eighth), N(C5, Eighth), N(A4, Eighth), N(C5, Eighth), N(E5, Eighth), N(A5, Eighth), N(E5, Eighth), N(C5, Eighth), N(B4, Eighth), N(D5, Eighth), N(F5, Eighth), N(B5, Eighth), N(F5, Eighth), N(D5, Eighth), N(E5, Quarter+Eighth), N(E5, Quarter+Eighth), N(E5, Eighth), N(F5, Eighth), N(E5, Eighth), N(D5, Eighth), N(C5, Eighth), N(B4, Eighth), N(A4, Eighth), N(B4, Eighth), N(C5, Eighth), N(D5, Eighth), N(E5, Eighth), N(F5, Eighth), N(E5, Eighth), N(D5, Eighth), N(C5, Eighth), N(B4, Eighth), N(A4, Eighth), N(Gs4, Eighth), N(A4, Quarter+Eighth), N(A4, Quarter+Eighth), }} accomp := BeatVoice{Notes: []BeatNote{ N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(E3, Eighth), N(B2, Eighth), N(E3, Eighth), N(B2, Eighth), N(E3, Eighth), N(B2, Eighth), N(A3, Quarter+Eighth), N(E3, Quarter+Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(A3, Eighth), N(E3, Eighth), N(E3, Eighth), N(B2, Eighth), N(E3, Eighth), N(B2, Eighth), N(E3, Eighth), N(B2, Eighth), N(A3, Quarter+Eighth), N(A2, Quarter+Eighth), }} return []BeatVoice{melody, accomp} }, }
SongTarantella - 塔兰泰拉舞曲 (6/8拍示例)
var SongTwinkleStar = Song{ ID: "twinkle_star", Name: "小星星", Tempo: Tempo{BPM: 100, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Quarter), N(C4, Quarter), N(G4, Quarter), N(G4, Quarter), N(A4, Quarter), N(A4, Quarter), N(G4, Half), N(F4, Quarter), N(F4, Quarter), N(E4, Quarter), N(E4, Quarter), N(D4, Quarter), N(D4, Quarter), N(C4, Half), N(G4, Quarter), N(G4, Quarter), N(F4, Quarter), N(F4, Quarter), N(E4, Quarter), N(E4, Quarter), N(D4, Half), N(G4, Quarter), N(G4, Quarter), N(F4, Quarter), N(F4, Quarter), N(E4, Quarter), N(E4, Quarter), N(D4, Half), N(C4, Quarter), N(C4, Quarter), N(G4, Quarter), N(G4, Quarter), N(A4, Quarter), N(A4, Quarter), N(G4, Half), N(F4, Quarter), N(F4, Quarter), N(E4, Quarter), N(E4, Quarter), N(D4, Quarter), N(D4, Quarter), N(C4, Half), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Quarter), N(E3, Quarter), N(G3, Quarter), N(E3, Quarter), N(F3, Quarter), N(A3, Quarter), N(C3, Half), N(F3, Quarter), N(A3, Quarter), N(C3, Quarter), N(E3, Quarter), N(G3, Quarter), N(B3, Quarter), N(C3, Half), N(C3, Quarter), N(E3, Quarter), N(F3, Quarter), N(A3, Quarter), N(C3, Quarter), N(E3, Quarter), N(G3, Half), N(C3, Quarter), N(E3, Quarter), N(F3, Quarter), N(A3, Quarter), N(C3, Quarter), N(E3, Quarter), N(G3, Half), N(C3, Quarter), N(E3, Quarter), N(G3, Quarter), N(E3, Quarter), N(F3, Quarter), N(A3, Quarter), N(C3, Half), N(F3, Quarter), N(A3, Quarter), N(C3, Quarter), N(E3, Quarter), N(G3, Quarter), N(B3, Quarter), N(C3, Half), }} return []BeatVoice{melody, accomp} }, }
SongTwinkleStar - 小星星 (Twinkle Twinkle Little Star)
var SongTwoTigers = Song{ ID: "two_tigers", Name: "两只老虎", Tempo: Tempo{BPM: 120, Signature: Time4_4}, Voices: func() []BeatVoice { melody := BeatVoice{Notes: []BeatNote{ N(C4, Quarter), N(D4, Quarter), N(E4, Quarter), N(C4, Quarter), N(C4, Quarter), N(D4, Quarter), N(E4, Quarter), N(C4, Quarter), N(E4, Quarter), N(F4, Quarter), N(G4, Half), N(E4, Quarter), N(F4, Quarter), N(G4, Half), N(G4, Eighth), N(A4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Quarter), N(C4, Quarter), N(G4, Eighth), N(A4, Eighth), N(G4, Eighth), N(F4, Eighth), N(E4, Quarter), N(C4, Quarter), N(C4, Quarter), N(G3, Quarter), N(C4, Half), N(C4, Quarter), N(G3, Quarter), N(C4, Half), }} accomp := BeatVoice{Notes: []BeatNote{ N(C3, Half), N(E3, Half), N(A3, Half), N(E3, Half), N(C3, Half), N(G3, Half), N(C3, Half), N(G3, Half), N(C3, Half), N(G3, Half), N(C3, Half), N(G3, Half), N(C3, Quarter), N(G3, Quarter), N(C3, Half), N(C3, Quarter), N(G3, Quarter), N(C3, Half), }} return []BeatVoice{melody, accomp} }, }
SongTwoTigers - 两只老虎 (Two Tigers / Frère Jacques)
Functions ¶
func DurationSamples ¶
DurationSamples calculates the number of samples for a given duration in ms.
func DurationSamplesFormat ¶
DurationSamplesFormat calculates samples for a duration using pcm.Format.
func GenerateChord ¶
GenerateChord generates a chord with piano-like sound.
func GenerateRichNote ¶
GenerateRichNote generates a piano-like note with realistic harmonics and envelope.
func GenerateSineWave ¶
GenerateSineWave generates a pure sine wave as 16-bit PCM data (little-endian).
func Int16ToBytes ¶
Int16ToBytes converts []int16 samples to raw PCM bytes (little-endian).
func TotalDuration ¶
TotalDuration returns the total duration of a melody in milliseconds.
Types ¶
type BeatVoice ¶
type BeatVoice struct {
Notes []BeatNote
}
BeatVoice represents a voice with beat-based notes.
func (BeatVoice) TotalBeats ¶
TotalBeats calculates the total number of beats in a BeatVoice.
type Metronome ¶
type Metronome struct {
Tempo Tempo
TotalBeats int // Total number of beats to generate
HighFreq float64 // Frequency for downbeat (first beat of bar)
LowFreq float64 // Frequency for other beats
ClickDur int // Duration of each click in ms
}
Metronome generates a metronome click track.
func DefaultMetronome ¶
DefaultMetronome creates a metronome with sensible defaults.
type Note ¶
type Note struct {
Freq float64 // Frequency in Hz (use Rest for silence)
Dur int // Duration in milliseconds
}
Note represents a single musical note with frequency and duration.
type RenderOptions ¶
type RenderOptions struct {
Format pcm.Format // Audio format (default: L16Mono16K)
Volume float64 // Volume 0.0-1.0; 0 means mute
Metronome bool // Include metronome track
RichSound bool // true: rich harmonics, false: sine tone
}
RenderOptions configures song rendering.
func DefaultRenderOptions ¶
func DefaultRenderOptions() RenderOptions
DefaultRenderOptions returns default rendering options.
type Song ¶
type Song struct {
ID string // Unique identifier
Name string // Display name
Tempo Tempo // Tempo configuration
Voices func() []BeatVoice // Function that returns all voices (melody + accompaniment)
}
Song represents a complete song with tempo and multiple voices.
func (Song) Render ¶
func (s Song) Render(opts RenderOptions) io.Reader
Render renders a song to mixed PCM audio using pcm.Mixer. It creates a track for each voice and mixes them together. Returns an io.Reader that reads the mixed audio data.
func (Song) RenderBytes ¶
func (s Song) RenderBytes(opts RenderOptions) ([]byte, error)
RenderBytes renders a song to a byte slice.
type Tempo ¶
type Tempo struct {
BPM int // Beats per minute
Signature TimeSignature // Time signature
}
Tempo represents the tempo configuration for a song.
func (Tempo) BarDuration ¶
BarDuration returns the duration of one full bar/measure in milliseconds.
func (Tempo) BeatDuration ¶
BeatDuration converts beat count to milliseconds.
type TimeSignature ¶
type TimeSignature struct {
BeatsPerBar int // Numerator: how many beats per measure (e.g., 4 for 4/4)
BeatUnit int // Denominator: note value that gets one beat (e.g., 4 for quarter note)
}
TimeSignature represents the time signature of a song.