Skip to content

Commit 8b43d6f

Browse files
authored
Add rest notes to sound.Sound.play_song() (#701)
1 parent 77cbf55 commit 8b43d6f

File tree

2 files changed

+37
-28
lines changed

2 files changed

+37
-28
lines changed

debian/changelog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
python-ev3dev2 (2.1.0) UNRELEASED; urgency=medium
22

3+
[Matěj Volf]
4+
* Add rest notes to sound.Sound.play_song()
5+
36
[Kaelin Laundry]
47
* Add "value_secs" and "is_elapsed_*" methods to StopWatch
58
* Rename "value_hms" to "hms_str". New "value_hms" returns original tuple.

ev3dev2/sound.py

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from ev3dev2 import is_micropython
3232
import os
3333
import re
34+
from time import sleep
3435

3536
if not is_micropython():
3637
import shlex
@@ -43,7 +44,7 @@ def _make_scales(notes):
4344
for note, freq in notes:
4445
freq = round(freq)
4546
for n in note.split('/'):
46-
res[n] = freq
47+
res[n.upper()] = freq
4748
return res
4849

4950

@@ -77,14 +78,18 @@ class Sound(object):
7778
7879
Examples::
7980
81+
from ev3dev2.sound import Sound
82+
83+
spkr = Sound()
84+
8085
# Play 'bark.wav':
81-
Sound.play_file('bark.wav')
86+
spkr.play_file('bark.wav')
8287
8388
# Introduce yourself:
84-
Sound.speak('Hello, I am Robot')
89+
spkr.speak('Hello, I am Robot')
8590
8691
# Play a small song
87-
Sound.play_song((
92+
spkr.play_song((
8893
('D4', 'e3'),
8994
('D4', 'e3'),
9095
('D4', 'e3'),
@@ -406,6 +411,7 @@ def play_song(self, song, tempo=120, delay=0.05):
406411
and duration.
407412
408413
It supports symbolic notes (e.g. ``A4``, ``D#3``, ``Gb5``) and durations (e.g. ``q``, ``h``).
414+
You can also specify rests by using ``R`` instead of note pitch.
409415
410416
For an exhaustive list of accepted note symbols and values, have a look at the ``_NOTE_FREQUENCIES``
411417
and ``_NOTE_VALUES`` private dictionaries in the source code.
@@ -429,7 +435,9 @@ def play_song(self, song, tempo=120, delay=0.05):
429435
430436
>>> # A long time ago in a galaxy far,
431437
>>> # far away...
432-
>>> Sound.play_song((
438+
>>> from ev3dev2.sound import Sound
439+
>>> spkr = Sound()
440+
>>> spkr.play_song((
433441
>>> ('D4', 'e3'), # intro anacrouse
434442
>>> ('D4', 'e3'),
435443
>>> ('D4', 'e3'),
@@ -471,41 +479,39 @@ def play_song(self, song, tempo=120, delay=0.05):
471479
delay_ms = int(delay * 1000)
472480
meas_duration_ms = 60000 / tempo * 4 # we only support 4/4 bars, hence "* 4"
473481

474-
def beep_args(note, value):
475-
""" Builds the arguments string for producing a beep matching
476-
the requested note and value.
477-
478-
Args:
479-
note (str): the note note and octave
480-
value (str): the note value expression
481-
Returns:
482-
str: the arguments to be passed to the beep command
483-
"""
484-
freq = self._NOTE_FREQUENCIES.get(note.upper(), self._NOTE_FREQUENCIES[note])
482+
for (note, value) in song:
483+
value = value.lower()
485484

486485
if '/' in value:
487486
base, factor = value.split('/')
488-
duration_ms = meas_duration_ms * self._NOTE_VALUES[base] / float(factor)
487+
factor = float(factor)
488+
489489
elif '*' in value:
490490
base, factor = value.split('*')
491-
duration_ms = meas_duration_ms * self._NOTE_VALUES[base] * float(factor)
491+
factor = float(factor)
492+
492493
elif value.endswith('.'):
493494
base = value[:-1]
494-
duration_ms = meas_duration_ms * self._NOTE_VALUES[base] * 1.5
495+
factor = 1.5
496+
495497
elif value.endswith('3'):
496498
base = value[:-1]
497-
duration_ms = meas_duration_ms * self._NOTE_VALUES[base] * 2 / 3
499+
factor = float(2/3)
500+
498501
else:
499-
duration_ms = meas_duration_ms * self._NOTE_VALUES[value]
502+
base = value
503+
factor = 1.0
500504

501-
return '-f %d -l %d -D %d' % (freq, duration_ms, delay_ms)
505+
try:
506+
duration_ms = meas_duration_ms * self._NOTE_VALUES[base] * factor
507+
except KeyError:
508+
raise ValueError('invalid note (%s)' % base)
502509

503-
try:
504-
return self.beep(' -n '.join(
505-
[beep_args(note, value) for (note, value) in song]
506-
))
507-
except KeyError as e:
508-
raise ValueError('invalid note (%s)' % e)
510+
if note == "R":
511+
sleep(duration_ms / 1000 + delay)
512+
else:
513+
freq = self._NOTE_FREQUENCIES[note.upper()]
514+
self.beep('-f %d -l %d -D %d' % (freq, duration_ms, delay_ms))
509515

510516
#: Note frequencies.
511517
#:

0 commit comments

Comments
 (0)