|
36 | 36 | * Author(s): Kattni Rembor, Scott Shawcroft
|
37 | 37 | """
|
38 | 38 |
|
| 39 | +import math |
| 40 | +import array |
| 41 | +import time |
| 42 | +try: |
| 43 | + import audiocore |
| 44 | +except ImportError: |
| 45 | + audiocore = audioio |
39 | 46 | import adafruit_lis3dh
|
40 | 47 | import adafruit_thermistor
|
41 | 48 | import analogio
|
@@ -66,6 +73,9 @@ def light(self):
|
66 | 73 |
|
67 | 74 | class CircuitPlaygroundBase: # pylint: disable=too-many-public-methods
|
68 | 75 | """Circuit Playground base class."""
|
| 76 | + |
| 77 | + _audio_out = None |
| 78 | + |
69 | 79 | def __init__(self):
|
70 | 80 | self._a = digitalio.DigitalInOut(board.BUTTON_A)
|
71 | 81 | self._a.switch_to_input(pull=digitalio.Pull.DOWN)
|
@@ -102,6 +112,13 @@ def __init__(self):
|
102 | 112 | self._lis3dh = adafruit_lis3dh.LIS3DH_I2C(self._i2c, address=0x19, int1=self._int1)
|
103 | 113 | self._lis3dh.range = adafruit_lis3dh.RANGE_8_G
|
104 | 114 |
|
| 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 | + |
105 | 122 | # Initialise tap:
|
106 | 123 | self._detect_taps = 1
|
107 | 124 | self.detect_taps = 1
|
@@ -811,3 +828,178 @@ def red_led(self):
|
811 | 828 | @red_led.setter
|
812 | 829 | def red_led(self, value):
|
813 | 830 | 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