Skip to content

Commit d693e4c

Browse files
committed
Move common audio code into base class.
1 parent b9d77f1 commit d693e4c

File tree

3 files changed

+199
-263
lines changed

3 files changed

+199
-263
lines changed

adafruit_circuitplayground/bluefruit.py

Lines changed: 5 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@
3939

4040
import array
4141
import math
42-
import time
43-
import audiocore
4442
import digitalio
4543
import board
4644
import audiopwmio
@@ -54,145 +52,24 @@
5452

5553
class Bluefruit(CircuitPlaygroundBase):
5654
"""Represents a single CircuitPlayground Bluefruit."""
55+
56+
_audio_out = audiopwmio.PWMAudioOut
57+
5758
def __init__(self):
5859
# Only create the cpb module member when we aren't being imported by Sphinx
5960
if ("__module__" in dir(digitalio.DigitalInOut) and
6061
digitalio.DigitalInOut.__module__ == "sphinx.ext.autodoc"):
6162
return
6263

63-
# Define audio:
64-
self._speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
65-
self._speaker_enable.switch_to_output(value=False)
64+
super().__init__()
65+
6666
self._sample = None
67-
self._sine_wave = None
68-
self._sine_wave_sample = None
6967

7068
# Define mic/sound sensor:
7169
self._mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA,
7270
sample_rate=16000, bit_depth=16)
7371
self._samples = None
7472

75-
super().__init__()
76-
77-
@staticmethod
78-
def _sine_sample(length):
79-
tone_volume = (2 ** 15) - 1
80-
shift = 2 ** 15
81-
for i in range(length):
82-
yield int(tone_volume * math.sin(2*math.pi*(i / length)) + shift)
83-
84-
def _generate_sample(self, length=100):
85-
if self._sample is not None:
86-
return
87-
self._sine_wave = array.array("H", Bluefruit._sine_sample(length))
88-
self._sample = audiopwmio.PWMAudioOut(board.SPEAKER)
89-
self._sine_wave_sample = audiocore.RawSample(self._sine_wave)
90-
91-
def play_tone(self, frequency, duration):
92-
""" Produce a tone using the speaker. Try changing frequency to change
93-
the pitch of the tone.
94-
95-
:param int frequency: The frequency of the tone in Hz
96-
:param float duration: The duration of the tone in seconds
97-
98-
.. image :: ../docs/_static/speaker.jpg
99-
:alt: Onboard speaker
100-
101-
.. code-block:: python
102-
103-
from adafruit_circuitplayground.bluefruit import cpb
104-
105-
cpb.play_tone(440, 1)
106-
"""
107-
# Play a tone of the specified frequency (hz).
108-
self.start_tone(frequency)
109-
time.sleep(duration)
110-
self.stop_tone()
111-
112-
def start_tone(self, frequency):
113-
""" Produce a tone using the speaker. Try changing frequency to change
114-
the pitch of the tone.
115-
116-
:param int frequency: The frequency of the tone in Hz
117-
118-
.. image :: ../docs/_static/speaker.jpg
119-
:alt: Onboard speaker
120-
121-
.. code-block:: python
122-
123-
from adafruit_circuitplayground.bluefruit import cpb
124-
125-
while True:
126-
if cpb.button_a:
127-
cpb.start_tone(262)
128-
elif cpb.button_b:
129-
cpb.start_tone(294)
130-
else:
131-
cpb.stop_tone()
132-
"""
133-
self._speaker_enable.value = True
134-
length = 100
135-
if length * frequency > 350000:
136-
length = 350000 // frequency
137-
self._generate_sample(length)
138-
# Start playing a tone of the specified frequency (hz).
139-
self._sine_wave_sample.sample_rate = int(len(self._sine_wave) * frequency)
140-
if not self._sample.playing:
141-
self._sample.play(self._sine_wave_sample, loop=True)
142-
143-
def stop_tone(self):
144-
""" Use with start_tone to stop the tone produced.
145-
146-
.. image :: ../docs/_static/speaker.jpg
147-
:alt: Onboard speaker
148-
149-
.. code-block:: python
150-
151-
from adafruit_circuitplayground.bluefruit import cpb
152-
153-
while True:
154-
if cpb.button_a:
155-
cpb.start_tone(262)
156-
elif cpb.button_b:
157-
cpb.start_tone(294)
158-
else:
159-
cpb.stop_tone()
160-
"""
161-
# Stop playing any tones.
162-
if self._sample is not None and self._sample.playing:
163-
self._sample.stop()
164-
self._sample.deinit()
165-
self._sample = None
166-
self._speaker_enable.value = False
167-
168-
def play_file(self, file_name):
169-
""" Play a .wav file using the onboard speaker.
170-
171-
:param file_name: The name of your .wav file in quotation marks including .wav
172-
173-
.. image :: ../docs/_static/speaker.jpg
174-
:alt: Onboard speaker
175-
176-
.. code-block:: python
177-
178-
from adafruit_circuitplayground.bluefruit import cpb
179-
180-
while True:
181-
if cpb.button_a:
182-
cpb.play_file("laugh.wav")
183-
elif cpb.button_b:
184-
cpb.play_file("rimshot.wav")
185-
"""
186-
# Play a specified file.
187-
self.stop_tone()
188-
self._speaker_enable.value = True
189-
with audiopwmio.PWMAudioOut(board.SPEAKER) as audio:
190-
wavefile = audiocore.WaveFile(open(file_name, "rb"))
191-
audio.play(wavefile)
192-
while audio.playing:
193-
pass
194-
self._speaker_enable.value = False
195-
19673
@staticmethod
19774
def _normalized_rms(values):
19875
mean_values = int(sum(values) / len(values))

adafruit_circuitplayground/circuit_playground_base.py

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
* Author(s): Kattni Rembor, Scott Shawcroft
3737
"""
3838

39+
import math
40+
import array
41+
import time
42+
try:
43+
import audiocore
44+
except ImportError:
45+
audiocore = audioio
3946
import adafruit_lis3dh
4047
import adafruit_thermistor
4148
import analogio
@@ -66,6 +73,9 @@ def light(self):
6673

6774
class CircuitPlaygroundBase: # pylint: disable=too-many-public-methods
6875
"""Circuit Playground base class."""
76+
77+
_audio_out = None
78+
6979
def __init__(self):
7080
self._a = digitalio.DigitalInOut(board.BUTTON_A)
7181
self._a.switch_to_input(pull=digitalio.Pull.DOWN)
@@ -102,6 +112,13 @@ def __init__(self):
102112
self._lis3dh = adafruit_lis3dh.LIS3DH_I2C(self._i2c, address=0x19, int1=self._int1)
103113
self._lis3dh.range = adafruit_lis3dh.RANGE_8_G
104114

115+
# Define audio:
116+
self._speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
117+
self._speaker_enable.switch_to_output(value=False)
118+
self._sample = None
119+
self._sine_wave = None
120+
self._sine_wave_sample = None
121+
105122
# Initialise tap:
106123
self._detect_taps = 1
107124
self.detect_taps = 1
@@ -811,3 +828,178 @@ def red_led(self):
811828
@red_led.setter
812829
def red_led(self, value):
813830
self._led.value = value
831+
832+
@staticmethod
833+
def _sine_sample(length):
834+
tone_volume = (2 ** 15) - 1
835+
shift = 2 ** 15
836+
for i in range(length):
837+
yield int(tone_volume * math.sin(2*math.pi*(i / length)) + shift)
838+
839+
def _generate_sample(self, length=100):
840+
if self._sample is not None:
841+
return
842+
self._sine_wave = array.array("H", self._sine_sample(length))
843+
self._sample = self._audio_out(board.SPEAKER)
844+
self._sine_wave_sample = audiocore.RawSample(self._sine_wave)
845+
846+
def play_tone(self, frequency, duration):
847+
""" Produce a tone using the speaker. Try changing frequency to change
848+
the pitch of the tone.
849+
850+
:param int frequency: The frequency of the tone in Hz
851+
:param float duration: The duration of the tone in seconds
852+
853+
.. image :: ../docs/_static/speaker.jpg
854+
:alt: Onboard speaker
855+
856+
To use with the Circuit Playground Express:
857+
858+
.. code-block:: python
859+
860+
from adafruit_circuitplayground.express import cpx
861+
862+
cpx.play_tone(440, 1)
863+
864+
To use with the Circuit Playground Bluefruit:
865+
866+
.. code-block:: python
867+
868+
from adafruit_circuitplayground.bluefruit import cpb
869+
870+
cpb.play_tone(440, 1)
871+
"""
872+
# Play a tone of the specified frequency (hz).
873+
self.start_tone(frequency)
874+
time.sleep(duration)
875+
self.stop_tone()
876+
877+
def start_tone(self, frequency):
878+
""" Produce a tone using the speaker. Try changing frequency to change
879+
the pitch of the tone.
880+
881+
:param int frequency: The frequency of the tone in Hz
882+
883+
.. image :: ../docs/_static/speaker.jpg
884+
:alt: Onboard speaker
885+
886+
To use with the Circuit Playground Express:
887+
888+
.. code-block:: python
889+
890+
from adafruit_circuitplayground.express import cpx
891+
892+
while True:
893+
if cpx.button_a:
894+
cpx.start_tone(262)
895+
elif cpx.button_b:
896+
cpx.start_tone(294)
897+
else:
898+
cpx.stop_tone()
899+
900+
To use with the Circuit Playground Bluefruit:
901+
902+
.. code-block:: python
903+
904+
from adafruit_circuitplayground.bluefruit import cpb
905+
906+
while True:
907+
if cpb.button_a:
908+
cpb.start_tone(262)
909+
elif cpb.button_b:
910+
cpb.start_tone(294)
911+
else:
912+
cpb.stop_tone()
913+
"""
914+
self._speaker_enable.value = True
915+
length = 100
916+
if length * frequency > 350000:
917+
length = 350000 // frequency
918+
self._generate_sample(length)
919+
# Start playing a tone of the specified frequency (hz).
920+
self._sine_wave_sample.sample_rate = int(len(self._sine_wave) * frequency)
921+
if not self._sample.playing:
922+
self._sample.play(self._sine_wave_sample, loop=True)
923+
924+
def stop_tone(self):
925+
""" Use with start_tone to stop the tone produced.
926+
927+
.. image :: ../docs/_static/speaker.jpg
928+
:alt: Onboard speaker
929+
930+
To use with the Circuit Playground Express:
931+
932+
.. code-block:: python
933+
934+
from adafruit_circuitplayground.express import cpx
935+
936+
while True:
937+
if cpx.button_a:
938+
cpx.start_tone(262)
939+
elif cpx.button_b:
940+
cpx.start_tone(294)
941+
else:
942+
cpx.stop_tone()
943+
944+
To use with the Circuit Playground Bluefruit:
945+
946+
.. code-block:: python
947+
948+
from adafruit_circuitplayground.bluefruit import cpb
949+
950+
while True:
951+
if cpb.button_a:
952+
cpb.start_tone(262)
953+
elif cpb.button_b:
954+
cpb.start_tone(294)
955+
else:
956+
cpb.stop_tone()
957+
"""
958+
# Stop playing any tones.
959+
if self._sample is not None and self._sample.playing:
960+
self._sample.stop()
961+
self._sample.deinit()
962+
self._sample = None
963+
self._speaker_enable.value = False
964+
965+
def play_file(self, file_name):
966+
""" Play a .wav file using the onboard speaker.
967+
968+
:param file_name: The name of your .wav file in quotation marks including .wav
969+
970+
.. image :: ../docs/_static/speaker.jpg
971+
:alt: Onboard speaker
972+
973+
To use with the Circuit Playground Express:
974+
975+
.. code-block:: python
976+
977+
from adafruit_circuitplayground.express import cpx
978+
979+
while True:
980+
if cpx.button_a:
981+
cpx.play_file("laugh.wav")
982+
elif cpx.button_b:
983+
cpx.play_file("rimshot.wav")
984+
985+
To use with the Circuit Playground Bluefruit:
986+
987+
.. code-block:: python
988+
989+
from adafruit_circuitplayground.bluefruit import cpb
990+
991+
while True:
992+
if cpb.button_a:
993+
cpb.play_file("laugh.wav")
994+
elif cpb.button_b:
995+
cpb.play_file("rimshot.wav")
996+
"""
997+
# Play a specified file.
998+
self.stop_tone()
999+
self._speaker_enable.value = True
1000+
with self._audio_out(board.SPEAKER) as audio:
1001+
wavefile = audiocore.WaveFile(open(file_name, "rb"))
1002+
audio.play(wavefile)
1003+
while audio.playing:
1004+
pass
1005+
self._speaker_enable.value = False

0 commit comments

Comments
 (0)