32
32
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RTTTL"
33
33
34
34
import time
35
- from adafruit_waveform import sine
36
- import audioio
37
-
38
- PIANO = {"4a#" : 466.16 ,
39
- "4b" : 493.88 ,
40
- "5c" : 523.25 ,
41
- "5c#" : 554.37 ,
42
- "5d" : 587.33 ,
43
- "5d#" : 622.25 ,
44
- "5e" : 659.26 ,
45
- "5f" : 698.46 ,
46
- "5f#" : 739.99 ,
47
- "5g" : 783.99 ,
48
- "5g#" : 830.61 ,
35
+ import pulseio
36
+
37
+ AUDIOIO_AVAILABLE = False
38
+ try :
39
+ import audioio
40
+ from adafruit_waveform import sine
41
+ AUDIOIO_AVAILABLE = True
42
+ except ImportError :
43
+ pass
44
+
45
+ PIANO = {"4c" : 261.626 ,
46
+ "4c#" : 277.183 ,
47
+ "4d" : 293.665 ,
48
+ "4d#" : 311.127 ,
49
+ "4e" : 329.628 ,
50
+ "4f" : 349.228 ,
51
+ "4f#" : 369.994 ,
52
+ "4g" : 391.995 ,
53
+ "4g#" : 415.305 ,
54
+ "4a" : 440 ,
55
+ "4a#" : 466.164 ,
56
+ "4b" : 493.883 ,
57
+ "5c" : 523.251 ,
58
+ "5c#" : 554.365 ,
59
+ "5d" : 587.330 ,
60
+ "5d#" : 622.254 ,
61
+ "5e" : 659.255 ,
62
+ "5f" : 698.456 ,
63
+ "5f#" : 739.989 ,
64
+ "5g" : 783.991 ,
65
+ "5g#" : 830.609 ,
49
66
"5a" : 880 ,
50
- "5a#" : 932.33 ,
51
- "5b" : 987.77 ,
52
- "6c" : 1046.5 ,
53
- "6c#" : 1108.7 ,
54
- "6d" : 1174.7 ,
55
- "6d#" : 1244.5 ,
56
- "6e" : 1318.5 ,
57
- "6f" : 1396.9 ,
58
- "6f#" : 1480 ,
59
- "6g" : 1568 ,
60
- "6g#" : 1661.2 ,
67
+ "5a#" : 932.328 ,
68
+ "5b" : 987.767 ,
69
+ "6c" : 1046.50 ,
70
+ "6c#" : 1108.73 ,
71
+ "6d" : 1174.66 ,
72
+ "6d#" : 1244.51 ,
73
+ "6e" : 1318.51 ,
74
+ "6f" : 1396.91 ,
75
+ "6f#" : 1479.98 ,
76
+ "6g" : 1567.98 ,
77
+ "6g#" : 1661.22 ,
61
78
"6a" : 1760 ,
62
- "6a#" : 1864.7 ,
63
- "6b" : 1975.5 ,
79
+ "6a#" : 1864.66 ,
80
+ "6b" : 1975.53 ,
64
81
"7c" : 2093 ,
65
- "7c#" : 2217.5 }
82
+ "7c#" : 2217.46 }
83
+
84
+ def _parse_note (note , duration = 2 , octave = "6" ):
85
+ note = note .strip ()
86
+ piano_note = None
87
+ note_duration = duration
88
+ if note [0 ].isdigit () and note [1 ].isdigit ():
89
+ note_duration = int (note [:2 ])
90
+ piano_note = note [2 ]
91
+ elif note [0 ].isdigit ():
92
+ note_duration = int (note [0 ])
93
+ piano_note = note [1 ]
94
+ else :
95
+ piano_note = note [0 ]
96
+ if "." in note :
97
+ note_duration *= 1.5
98
+ if "#" in note :
99
+ piano_note += "#"
100
+ note_octave = octave
101
+ if note [- 1 ].isdigit ():
102
+ note_octave = note [- 1 ]
103
+ piano_note = note_octave + piano_note
104
+ return piano_note , note_duration
66
105
67
106
def _get_wave (tune , octave ):
68
107
"""Returns the proper waveform to play the song along with the minimum
@@ -71,17 +110,7 @@ def _get_wave(tune, octave):
71
110
min_freq = 13000
72
111
73
112
for note in tune .split ("," ):
74
- piano_note = None
75
- if note [0 ].isdigit ():
76
- piano_note = note [1 ]
77
- else :
78
- piano_note = note [0 ]
79
- if "#" in note :
80
- piano_note += "#"
81
- note_octave = octave
82
- if note [- 1 ].isdigit ():
83
- note_octave = note [- 1 ]
84
- piano_note = note_octave + piano_note
113
+ piano_note , _ = _parse_note (note , octave = octave )
85
114
if piano_note [- 1 ] != "p" and PIANO [piano_note ] < min_freq :
86
115
min_freq = PIANO [piano_note ]
87
116
return sine .sine_wave (16000 , min_freq ), min_freq
@@ -91,28 +120,22 @@ def _get_wave(tune, octave):
91
120
def _play_to_pin (tune , base_tone , min_freq , duration , octave , tempo ):
92
121
"""Using the prepared input send the notes to the pin
93
122
"""
123
+ pwm = isinstance (base_tone , pulseio .PWMOut )
94
124
for note in tune .split ("," ):
95
- piano_note = None
96
- note_duration = duration
97
- if note [0 ].isdigit ():
98
- note_duration = int (note [0 ])
99
- piano_note = note [1 ]
100
- else :
101
- piano_note = note [0 ]
102
- if "." in note :
103
- note_duration *= 1.5
104
- if "#" in note :
105
- piano_note += "#"
106
- note_octave = octave
107
- if note [- 1 ].isdigit ():
108
- note_octave = note [- 1 ]
109
- piano_note = note_octave + piano_note
125
+ piano_note , note_duration = _parse_note (note , duration , octave )
110
126
if piano_note in PIANO :
111
- base_tone .frequency = int (16000 * (PIANO [piano_note ] / min_freq ))
112
- base_tone .play (loop = True )
127
+ if pwm :
128
+ base_tone .frequency = int (PIANO [piano_note ])
129
+ base_tone .duty_cycle = 2 ** 15
130
+ else :
131
+ base_tone .frequency = int (16000 * (PIANO [piano_note ] / min_freq ))
132
+ base_tone .play (loop = True )
113
133
print (piano_note , note_duration )
114
134
time .sleep (4 / note_duration * 60 / tempo )
115
- base_tone .stop ()
135
+ if pwm :
136
+ base_tone .duty_cycle = 0
137
+ else :
138
+ base_tone .stop ()
116
139
time .sleep (0.02 )
117
140
118
141
#pylint: disable-msg=too-many-arguments
@@ -124,7 +147,7 @@ def play(pin, rtttl, octave=None, duration=None, tempo=None):
124
147
:param int duration: length of notes (default 4 quarter note)
125
148
:param int tempo: how fast (default 63 beats per minute)
126
149
"""
127
- _ , defaults , tune = rtttl .split (":" )
150
+ _ , defaults , tune = rtttl .lower (). split (":" )
128
151
for default in defaults .split ("," ):
129
152
if default [0 ] == "d" and not duration :
130
153
duration = int (default [2 :])
@@ -141,8 +164,18 @@ def play(pin, rtttl, octave=None, duration=None, tempo=None):
141
164
142
165
print ("tempo" , tempo , "octave" , octave , "duration" , duration )
143
166
144
- wave , min_freq = _get_wave (tune , octave )
167
+ base_tone = None
168
+ min_freq = 440
169
+ if AUDIOIO_AVAILABLE :
170
+ wave , min_freq = _get_wave (tune , octave )
171
+ try :
172
+ base_tone = audioio .AudioOut (pin , wave )
173
+ except ValueError :
174
+ # No DAC on the pin so use PWM.
175
+ pass
145
176
146
- base_tone = audioio .AudioOut (pin , wave )
177
+ # Fall back to PWM
178
+ if not base_tone :
179
+ base_tone = pulseio .PWMOut (pin , duty_cycle = 0 , variable_frequency = True )
147
180
148
181
_play_to_pin (tune , base_tone , min_freq , duration , octave , tempo )
0 commit comments