3232__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RTTTL"
3333
3434import 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 ,
4966 "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 ,
6178 "6a" : 1760 ,
62- "6a#" : 1864.7 ,
63- "6b" : 1975.5 ,
79+ "6a#" : 1864.66 ,
80+ "6b" : 1975.53 ,
6481 "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
66105
67106def _get_wave (tune , octave ):
68107 """Returns the proper waveform to play the song along with the minimum
@@ -71,17 +110,7 @@ def _get_wave(tune, octave):
71110 min_freq = 13000
72111
73112 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 )
85114 if piano_note [- 1 ] != "p" and PIANO [piano_note ] < min_freq :
86115 min_freq = PIANO [piano_note ]
87116 return sine .sine_wave (16000 , min_freq ), min_freq
@@ -91,28 +120,22 @@ def _get_wave(tune, octave):
91120def _play_to_pin (tune , base_tone , min_freq , duration , octave , tempo ):
92121 """Using the prepared input send the notes to the pin
93122 """
123+ pwm = isinstance (base_tone , pulseio .PWMOut )
94124 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 )
110126 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 )
113133 print (piano_note , note_duration )
114134 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 ()
116139 time .sleep (0.02 )
117140
118141#pylint: disable-msg=too-many-arguments
@@ -124,7 +147,7 @@ def play(pin, rtttl, octave=None, duration=None, tempo=None):
124147 :param int duration: length of notes (default 4 quarter note)
125148 :param int tempo: how fast (default 63 beats per minute)
126149 """
127- _ , defaults , tune = rtttl .split (":" )
150+ _ , defaults , tune = rtttl .lower (). split (":" )
128151 for default in defaults .split ("," ):
129152 if default [0 ] == "d" and not duration :
130153 duration = int (default [2 :])
@@ -141,8 +164,18 @@ def play(pin, rtttl, octave=None, duration=None, tempo=None):
141164
142165 print ("tempo" , tempo , "octave" , octave , "duration" , duration )
143166
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
145176
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 )
147180
148181 _play_to_pin (tune , base_tone , min_freq , duration , octave , tempo )
0 commit comments