Sound¶
Play sounds from your script.
What you get¶
class Bell
def on_button(btn)
if btn == "select" && !sound.playing()
sound.play({'rtttl': 'bell:d=4,o=5,b=100:e,c'})
end
end
def draw()
clear()
text(1, 6, "Bell", 0xFFFFFF)
end
end
return Bell()
Press select while the app is shown, and the clock plays a short melody. sound.playing() keeps
a quick double press from playing it twice.
How it behaves¶
sound.play()returns at once, and the sound plays while your script goes on.truemeans the clock took the sound, not that you hear it. A name that is not stored plays nothing, and the volume may be0.falsemeans this clock can play none of it. What the answer means lists every case.- Your script plays one sound at a time. Another sound replaces it.
- An alert is never cut off by a script. The sound of a notification plays over your script's sounds.
- Start sounds in a button handler or in
loop(), never indraw(), which runs about 40 times a second.
What to play¶
sound.play(x) takes a sound, the same one /api/v1/audio/play
takes. In Berry it is a string, a map or a list:
sound.play("doorbell") # a stored sound, by name
sound.play({'rtttl': 'beep:d=16,o=6,b=200:c'}) # a melody in the call
sound.play({'track': 3}) # a DFPlayer track
sound.play({'file': 'siren', 'loop': true}) # repeats until you stop it
A map has exactly one of these keys. The key says what plays:
| Key | Value | Plays |
|---|---|---|
'file' |
a name such as 'doorbell' |
a stored melody |
'rtttl' |
an RTTTL melody | the melody |
'track' |
a whole number from 1 to 2999 | a track from the DFPlayer |
Next to the key, a map may have:
'loop': trueto repeat the sound until it is stopped.
A plain name is short for {'file': name}. A list holds 1 to 4 sounds, and the clock plays the
first one it can play.
One sound after another¶
sound.playing() lets you wait for one sound to finish before you start the next. A button that
plays a sound needs this, or a quick double press plays it twice. See
What you get.
Play sounds one after another in loop(), never in draw():
var queue
def init()
self.queue = ["chime", "alarm"] # sounds waiting to play
end
def loop()
if size(self.queue) > 0 && !sound.playing()
sound.play(self.queue.pop(0))
end
end
Use notify() when the sound belongs to an event that should also interrupt the rotation and show
something. Use sound when you only want the sound. A notify() sound is an alert, so it plays
over your script's sounds. See Notifications.
Different clocks¶
Clocks have different sound hardware. Ask sound.can() before you play something only some clocks
have:
def on_button(btn)
if btn == "select" && !sound.playing()
if sound.can('track') sound.play({'track': 1})
else sound.play({'rtttl': 'bell:d=4,o=5,b=100:e,c'}) end
end
end
A list does the same in one call. The clock plays the first entry it can play:
sound.can() answers these keys, among others. They are the audio flags of
GET /api/v1/capabilities:
| Key | true when the clock can |
|---|---|
'rtttl' |
play melodies |
'track' |
play DFPlayer tracks |
A script that cannot work without one of them says so in its header, for example
# @needs audio.rtttl. See Sharing.
A sound that repeats¶
Your script plays one sound at a time. A sound with 'loop': true repeats until it is stopped or
another sound replaces it, an alert too.
Good to know¶
- A quick double press plays a sound twice. Check
!sound.playing()before you play, as in What you get. - Start sounds in a button handler or in
loop(), never indraw().draw()runs about 40 times a second. - A sound that repeats keeps playing when your app leaves. Stop it in
on_hide()when it belongs to what your app shows.
Details¶
Calls¶
| Call | Does | Returns |
|---|---|---|
sound.play(x) |
plays a sound once. With 'loop': true it repeats until it is stopped |
true when the clock took it, false when it can play none of it |
sound.stop() |
stops every sound your script plays | nil |
sound.stop('loop') |
stops your script's sound that repeats with 'loop': true |
nil |
sound.playing() |
whether a sound from your script plays right now | true or false |
sound.can() |
what this clock can play | a map such as {'mp3': true, 'rtttl': true, ...} |
sound.can(key) |
one entry of that map, for example sound.can('track') |
true or false |
What the answer means¶
true means the clock took the request, and the sound starts right away. true does not mean
you hear it:
- A name that is not stored plays nothing.
- While an alert plays, for example the sound of a notification, a single sound from your script is not played. An alert is never cut off by a script.
- The volume may be
0.
false means this clock cannot play any of it, for example
{'track': 3} on a clock without a DFPlayer.
It never stops your script.
A mistake in the sound raises a value_error at the call, with the key and the reason:
A map with two sound keys, an unknown key, a bad name or a track out of range raise the same way. The reasons are listed in When it goes wrong.
Every sound limit is in Limits.
Related¶
- Sound: stored sounds, melodies, the volume and what each clock can play
- Controlling the device: a sound together with a notification