Files
drivers/tone/notes.go

148 lines
1.6 KiB
Go

package tone
// Note represents a MIDI note number. For example, Note(69) is A4 or 440Hz.
type Note uint8
// Define all the notes in a format similar to the Tone library in the Arduino
// IDE.
const (
A0 Note = iota + 21 // 27.5Hz
AS0
B0
C1
CS1
D1
DS1
E1
F1
FS1
G1
GS1
A1 // 55Hz
AS1
B1
C2
CS2
D2
DS2
E2
F2
FS2
G2
GS2
A2 // 110Hz
AS2
B2
C3
CS3
D3
DS3
E3
F3
FS3
G3
GS3
A3 // 220Hz
AS3
B3
C4
CS4
D4
DS4
E4
F4
FS4
G4
GS4
A4 // 440Hz
AS4
B4
C5
CS5
D5
DS5
E5
F5
FS5
G5
GS5
A5 // 880Hz
AS5
B5
C6
CS6
D6
DS6
E6
F6
FS6
G6
GS6
A6 // 1760Hz
AS6
B6
C7
CS7
D7
DS7
E7
F7
FS7
G7
GS7
A7 // 3520Hz
AS7
B7
C8
CS8
D8
DS8
E8
F8
FS8
G8
GS8
A8 // 7040Hz
AS8
B8
)
// Period returns the period in nanoseconds of a single wave.
func (n Note) Period() uint64 {
if n == 0 {
// Assume that a zero note means no sound.
return 0
}
octave := (n - 9) / 12
note := (n - 9) - octave*12
// Start with a base period (in nanoseconds) of 6.875Hz (quarter the
// frequency of A0) and shift it right with the octave to get the base
// period of this note.
// 145454545 = 1e9 / 6.875
basePeriod := uint32(145454545) >> octave
// Make the pitch higher based on the note within the octave.
period := uint64(basePeriod) * uint64(tones[note]) / 32768
return period
}
// Constants to calculate the pitch within an octave. Python oneliner:
// [round(1e9/(440*(2**(n/12))) / (1e9/440) * 0x8000) for n in range(12)]
var tones = [12]uint16{
32768,
30929,
29193,
27554,
26008,
24548,
23170,
21870,
20643,
19484,
18390,
17358,
}