summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2018-10-09 19:26:50 -0400
committerGitHub <noreply@github.com>2018-10-09 19:26:50 -0400
commit3206d9a5da5e5018ecf3a5878924a202885e0864 (patch)
tree79e6a9ad0c7cb721482ba786162ae621f64a7a0f
parente9aefccdb5a280a7b510cf2a85837d0ea9ebd5df (diff)
parent570ac05145cecc2e1c61cc0ba710e6db9b2af5d2 (diff)
Merge pull request #1242 from tannewt/mixer
Introduce audioio.Mixer to allow for multiple sample playback
-rw-r--r--locale/circuitpython.pot56
-rw-r--r--locale/de_DE.po57
-rw-r--r--locale/en_US.po54
-rw-r--r--locale/es.po58
-rw-r--r--locale/fil.po58
-rw-r--r--locale/fr.po68
-rw-r--r--locale/it_IT.po60
-rw-r--r--locale/pt_BR.po57
-rw-r--r--ports/atmel-samd/Makefile2
-rw-r--r--ports/atmel-samd/audio_dma.c76
-rw-r--r--ports/atmel-samd/mpconfigport.h2
-rw-r--r--shared-bindings/audioio/Mixer.c249
-rw-r--r--shared-bindings/audioio/Mixer.h52
-rw-r--r--shared-bindings/audioio/__init__.c4
-rw-r--r--shared-module/audioio/Mixer.c341
-rw-r--r--shared-module/audioio/Mixer.h75
-rw-r--r--shared-module/audioio/WaveFile.c18
-rw-r--r--shared-module/audioio/__init__.c125
-rw-r--r--shared-module/audioio/__init__.h17
-rw-r--r--shared-module/displayio/Sprite.c2
-rwxr-xr-xtools/preprocess_frozen_modules.py2
21 files changed, 1274 insertions, 159 deletions
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index dca0801c8..04f16be3b 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-10-07 02:07+0300\n"
+"POT-Creation-Date: 2018-10-09 13:56-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -218,7 +218,7 @@ msgstr ""
msgid "soft reboot\n"
msgstr ""
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr ""
@@ -2026,6 +2026,22 @@ msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
msgstr ""
+#: shared-bindings/audioio/Mixer.c:94
+msgid "Invalid voice count"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:99
+msgid "Invalid channel count"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:103
+msgid "Sample rate must be positive"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:107
+msgid "bits_per_sample must be 8 or 16"
+msgstr ""
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2316,6 +2332,34 @@ msgid ""
"Object has been deinitialized and can no longer be used. Create a new object."
msgstr ""
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr ""
@@ -2336,14 +2380,6 @@ msgstr ""
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr ""
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr ""
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 58cc33331..51c3c4504 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -227,7 +227,7 @@ msgstr ""
msgid "soft reboot\n"
msgstr "weicher reboot\n"
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr "Alle sync event Kanäle werden benutzt"
@@ -2040,6 +2040,25 @@ msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
msgstr ""
+#: shared-bindings/audioio/Mixer.c:94
+#, fuzzy
+msgid "Invalid voice count"
+msgstr "Ungültiger clock pin"
+
+#: shared-bindings/audioio/Mixer.c:99
+#, fuzzy
+msgid "Invalid channel count"
+msgstr "Ungültiger clock pin"
+
+#: shared-bindings/audioio/Mixer.c:103
+msgid "Sample rate must be positive"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:107
+#, fuzzy
+msgid "bits_per_sample must be 8 or 16"
+msgstr "bits müssen 8 sein"
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2331,6 +2350,34 @@ msgid ""
"Object has been deinitialized and can no longer be used. Create a new object."
msgstr ""
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr ""
@@ -2351,14 +2398,6 @@ msgstr ""
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr ""
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr ""
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr ""
diff --git a/locale/en_US.po b/locale/en_US.po
index 6491f2f27..4b4ee2415 100644
--- a/locale/en_US.po
+++ b/locale/en_US.po
@@ -218,7 +218,7 @@ msgstr ""
msgid "soft reboot\n"
msgstr ""
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr ""
@@ -2026,6 +2026,22 @@ msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
msgstr ""
+#: shared-bindings/audioio/Mixer.c:94
+msgid "Invalid voice count"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:99
+msgid "Invalid channel count"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:103
+msgid "Sample rate must be positive"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:107
+msgid "bits_per_sample must be 8 or 16"
+msgstr ""
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2316,6 +2332,34 @@ msgid ""
"Object has been deinitialized and can no longer be used. Create a new object."
msgstr ""
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr ""
@@ -2336,14 +2380,6 @@ msgstr ""
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr ""
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr ""
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index 28d68a013..bc70f1d81 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -233,7 +233,7 @@ msgstr ""
msgid "soft reboot\n"
msgstr "reinicio suave\n"
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr "Todos los sync event channels están siendo utilizados"
@@ -2067,6 +2067,26 @@ msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
msgstr ""
+#: shared-bindings/audioio/Mixer.c:94
+#, fuzzy
+msgid "Invalid voice count"
+msgstr "Dirección inválida."
+
+#: shared-bindings/audioio/Mixer.c:99
+#, fuzzy
+msgid "Invalid channel count"
+msgstr "argumentos inválidos"
+
+#: shared-bindings/audioio/Mixer.c:103
+#, fuzzy
+msgid "Sample rate must be positive"
+msgstr "STA debe estar activo"
+
+#: shared-bindings/audioio/Mixer.c:107
+#, fuzzy
+msgid "bits_per_sample must be 8 or 16"
+msgstr "bits debe ser 8"
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2359,6 +2379,34 @@ msgid ""
"Object has been deinitialized and can no longer be used. Create a new object."
msgstr ""
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr ""
@@ -2379,14 +2427,6 @@ msgstr ""
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr ""
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr ""
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr ""
diff --git a/locale/fil.po b/locale/fil.po
index d34e1b9f0..192ec58a5 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -230,7 +230,7 @@ msgstr ""
msgid "soft reboot\n"
msgstr "malambot na reboot\n"
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr "Lahat ng sync event channels ay ginagamit"
@@ -2069,6 +2069,26 @@ msgstr ""
"ang destination buffer ay dapat na isang bytearray o array ng uri na 'B' "
"para sa bit_depth = 8"
+#: shared-bindings/audioio/Mixer.c:94
+#, fuzzy
+msgid "Invalid voice count"
+msgstr "Mali ang tipo ng serbisyo"
+
+#: shared-bindings/audioio/Mixer.c:99
+#, fuzzy
+msgid "Invalid channel count"
+msgstr "Maling argumento"
+
+#: shared-bindings/audioio/Mixer.c:103
+#, fuzzy
+msgid "Sample rate must be positive"
+msgstr "Dapat aktibo ang STA"
+
+#: shared-bindings/audioio/Mixer.c:107
+#, fuzzy
+msgid "bits_per_sample must be 8 or 16"
+msgstr "bits ay dapat 7, 8 o 9"
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2378,6 +2398,34 @@ msgstr ""
"Object ay deinitialized at hindi na magagamit. Lumikha ng isang bagong "
"Object."
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr "Hindi ma-iallocate ang first buffer"
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr "Hindi ma-iallocate ang second buffer"
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr "May hindi tama sa wave file"
@@ -2398,14 +2446,6 @@ msgstr "Dapat sunurin ng Data chunk ang fmt chunk"
msgid "Invalid file"
msgstr "Mali ang file"
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr "Hindi ma-iallocate ang first buffer"
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr "Hindi ma-iallocate ang second buffer"
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr "Masyadong mahaba ang Clock stretch"
diff --git a/locale/fr.po b/locale/fr.po
index 4d5e126ad..1a5af3fef 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-10-07 02:07+0300\n"
+"POT-Creation-Date: 2018-10-09 13:56-0700\n"
"PO-Revision-Date: 2018-08-14 11:01+0200\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n"
@@ -225,7 +225,7 @@ msgstr "Appuyez sur une touche pour entrer sur REPL ou CTRL-D pour recharger."
msgid "soft reboot\n"
msgstr "redémarrage logiciel\n"
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr "Tous les canaux d'événements de synchro sont utilisés"
@@ -2060,6 +2060,26 @@ msgid ""
msgstr ""
"le tampon de destination doit être un tableau de type 'B' pour bit_depth = 8"
+#: shared-bindings/audioio/Mixer.c:94
+#, fuzzy
+msgid "Invalid voice count"
+msgstr "Type de service invalide"
+
+#: shared-bindings/audioio/Mixer.c:99
+#, fuzzy
+msgid "Invalid channel count"
+msgstr "Argument invalide"
+
+#: shared-bindings/audioio/Mixer.c:103
+#, fuzzy
+msgid "Sample rate must be positive"
+msgstr "'STA' doit être actif"
+
+#: shared-bindings/audioio/Mixer.c:107
+#, fuzzy
+msgid "bits_per_sample must be 8 or 16"
+msgstr "bits doivent être 7, 8 ou 9"
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2374,6 +2394,34 @@ msgstr ""
"L'objet a été désinitialisé et ne peut plus être utilisé. Créez un nouvel "
"objet."
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr "Impossible d'allouer le 1er tampon"
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr "Impossible d'allouer le 2e tampon"
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr "Fichier WAVE invalide"
@@ -2394,14 +2442,6 @@ msgstr "Un bloc de données doit suivre un bloc de format"
msgid "Invalid file"
msgstr "Fichier invalide"
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr "Impossible d'allouer le 1er tampon"
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr "Impossible d'allouer le 2e tampon"
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr "Période de l'horloge trop longue"
@@ -2471,9 +2511,9 @@ msgid "too many arguments provided with the given format"
msgstr "trop d'arguments fournis avec ce format"
#, fuzzy
-#~ msgid "palette must be displayio.Palette"
-#~ msgstr "la palette doit être longue de 32 octets"
-
-#, fuzzy
#~ msgid "value_size must be power of two"
#~ msgstr "'len' doit être un multiple de 4"
+
+#, fuzzy
+#~ msgid "palette must be displayio.Palette"
+#~ msgstr "la palette doit être longue de 32 octets"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index dd8b41f76..9318952c2 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-10-07 10:54+0200\n"
+"POT-Creation-Date: 2018-10-09 13:56-0700\n"
"PO-Revision-Date: 2018-10-02 16:27+0200\n"
"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n"
"Language-Team: \n"
@@ -231,7 +231,7 @@ msgstr ""
msgid "soft reboot\n"
msgstr "soft reboot\n"
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr "Tutti i canali di eventi sincronizzati in uso"
@@ -2064,6 +2064,26 @@ msgstr ""
"il buffer di destinazione deve essere un bytearray o un array di tipo 'B' "
"con bit_depth = 8"
+#: shared-bindings/audioio/Mixer.c:94
+#, fuzzy
+msgid "Invalid voice count"
+msgstr "Tipo di servizio non valido"
+
+#: shared-bindings/audioio/Mixer.c:99
+#, fuzzy
+msgid "Invalid channel count"
+msgstr "Argomento non valido"
+
+#: shared-bindings/audioio/Mixer.c:103
+#, fuzzy
+msgid "Sample rate must be positive"
+msgstr "STA deve essere attiva"
+
+#: shared-bindings/audioio/Mixer.c:107
+#, fuzzy
+msgid "bits_per_sample must be 8 or 16"
+msgstr "i bit devono essere 7, 8 o 9"
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2364,6 +2384,34 @@ msgstr ""
"L'oggetto è stato deinizializzato e non può essere più usato. Crea un nuovo "
"oggetto."
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr "Impossibile allocare il primo buffer"
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr "Impossibile allocare il secondo buffer"
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr "File wave non valido"
@@ -2384,14 +2432,6 @@ msgstr ""
msgid "Invalid file"
msgstr "File non valido"
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr "Impossibile allocare il primo buffer"
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr "Impossibile allocare il secondo buffer"
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr ""
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 190c2a93d..9b92333fc 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -218,7 +218,7 @@ msgstr ""
msgid "soft reboot\n"
msgstr ""
-#: ports/atmel-samd/audio_dma.c:285
+#: ports/atmel-samd/audio_dma.c:209
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
msgid "All sync event channels in use"
msgstr ""
@@ -2029,6 +2029,25 @@ msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
msgstr ""
+#: shared-bindings/audioio/Mixer.c:94
+#, fuzzy
+msgid "Invalid voice count"
+msgstr "certificado inválido"
+
+#: shared-bindings/audioio/Mixer.c:99
+#, fuzzy
+msgid "Invalid channel count"
+msgstr "certificado inválido"
+
+#: shared-bindings/audioio/Mixer.c:103
+msgid "Sample rate must be positive"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:107
+#, fuzzy
+msgid "bits_per_sample must be 8 or 16"
+msgstr "bits devem ser 8"
+
#: shared-bindings/audioio/RawSample.c:98
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
@@ -2320,6 +2339,34 @@ msgid ""
msgstr ""
"Objeto foi desinicializado e não pode ser mais usaado. Crie um novo objeto."
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr "Não pôde alocar primeiro buffer"
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr "Não pôde alocar segundo buffer"
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
#: shared-module/audioio/WaveFile.c:61
msgid "Invalid wave file"
msgstr "Aqruivo de ondas inválido"
@@ -2340,14 +2387,6 @@ msgstr "Pedaço de dados deve seguir o pedaço de cortes"
msgid "Invalid file"
msgstr "Arquivo inválido"
-#: shared-module/audioio/WaveFile.c:117
-msgid "Couldn't allocate first buffer"
-msgstr "Não pôde alocar primeiro buffer"
-
-#: shared-module/audioio/WaveFile.c:123
-msgid "Couldn't allocate second buffer"
-msgstr "Não pôde alocar segundo buffer"
-
#: shared-module/bitbangio/I2C.c:58
msgid "Clock stretch too long"
msgstr "Clock se estendeu por tempo demais"
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index f8e5051c2..c8ade987d 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -407,6 +407,8 @@ ifneq ($(CHIP_VARIANT),SAMR21G18A)
audioio/__init__.c \
audioio/AudioOut.c
SRC_SHARED_MODULE += \
+ audioio/__init__.c \
+ audioio/Mixer.c \
audioio/RawSample.c \
audioio/WaveFile.c
endif
diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c
index 45d698c17..68d6f182d 100644
--- a/ports/atmel-samd/audio_dma.c
+++ b/ports/atmel-samd/audio_dma.c
@@ -40,82 +40,6 @@ static audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT];
// This cannot be in audio_dma_state because it's volatile.
static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT];
-uint32_t audiosample_sample_rate(mp_obj_t sample_obj) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return sample->sample_rate;
- }
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return file->sample_rate;
- }
- return 16000;
-}
-
-uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return sample->bits_per_sample;
- }
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return file->bits_per_sample;
- }
- return 8;
-}
-
-uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return sample->channel_count;
- }
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return file->channel_count;
- }
- return 1;
-}
-
-static void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- audioio_rawsample_reset_buffer(sample, single_channel, audio_channel);
- }
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- audioio_wavefile_reset_buffer(file, single_channel, audio_channel);
- }
-}
-
-static audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
- bool single_channel,
- uint8_t channel,
- uint8_t** buffer, uint32_t* buffer_length) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length);
- }
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length);
- }
- return GET_BUFFER_DONE;
-}
-
-static void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
- bool* single_buffer, bool* samples_signed,
- uint32_t* max_buffer_length, uint8_t* spacing) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer,
- samples_signed, max_buffer_length, spacing);
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
- max_buffer_length, spacing);
- }
-}
-
uint8_t find_free_audio_dma_channel(void) {
uint8_t channel;
for (channel = 0; channel < AUDIO_DMA_CHANNEL_COUNT; channel++) {
diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h
index 14f72ccfb..69a146c1f 100644
--- a/ports/atmel-samd/mpconfigport.h
+++ b/ports/atmel-samd/mpconfigport.h
@@ -207,7 +207,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
#define MICROPY_PY_URE (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#ifndef MICROPY_PY_FRAMEBUF
- #define MICROPY_PY_FRAMEBUF (1)
+ #define MICROPY_PY_FRAMEBUF (0)
#endif
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1)
diff --git a/shared-bindings/audioio/Mixer.c b/shared-bindings/audioio/Mixer.c
new file mode 100644
index 000000000..dc7a12ebc
--- /dev/null
+++ b/shared-bindings/audioio/Mixer.c
@@ -0,0 +1,249 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "shared-bindings/audioio/Mixer.h"
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: audioio
+//|
+//| :class:`Mixer` -- Mixes one or more audio samples together
+//| ===========================================================
+//|
+//| Mixer mixes multiple samples into one sample.
+//|
+//| .. class:: Mixer(channel_count=2, buffer_size=1024)
+//|
+//| Create a Mixer object that can mix multiple channels with the same sample rate.
+//|
+//| :param int channel_count: The maximum number of samples to mix at once
+//| :param int buffer_size: The total size in bytes of the buffers to mix into
+//|
+//| Playing a wave file from flash::
+//|
+//| import board
+//| import audioio
+//| import digitalio
+//|
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
+//|
+//| music = audioio.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb"))
+//| drum = audioio.WaveFile(open("drum.wav", "rb"))
+//| mixer = audioio.Mixer(voice_count=2, sample_rate=16000, channel_count=1, bits_per_sample=16, samples_signed=True)
+//| a = audioio.AudioOut(board.A0)
+//|
+//| print("playing")
+//| a.play(mixer)
+//| mixer.play(music, voice=0)
+//| while mixer.playing:
+//| mixer.play(drum, voice=1)
+//| time.sleep(1)
+//| print("stopped")
+//|
+STATIC mp_obj_t audioio_mixer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 0, 2, true);
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+ enum { ARG_voice_count, ARG_buffer_size, ARG_channel_count, ARG_bits_per_sample, ARG_samples_signed, ARG_sample_rate };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_voice_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 2} },
+ { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1024} },
+ { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 2} },
+ { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} },
+ { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
+ { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_int_t voice_count = args[ARG_voice_count].u_int;
+ if (voice_count < 1 || voice_count > 255) {
+ mp_raise_ValueError(translate("Invalid voice count"));
+ }
+
+ mp_int_t channel_count = args[ARG_channel_count].u_int;
+ if (channel_count < 1 || channel_count > 2) {
+ mp_raise_ValueError(translate("Invalid channel count"));
+ }
+ mp_int_t sample_rate = args[ARG_sample_rate].u_int;
+ if (sample_rate < 1) {
+ mp_raise_ValueError(translate("Sample rate must be positive"));
+ }
+ mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int;
+ if (bits_per_sample != 8 && bits_per_sample != 16) {
+ mp_raise_ValueError(translate("bits_per_sample must be 8 or 16"));
+ }
+ audioio_mixer_obj_t *self = m_new_obj_var(audioio_mixer_obj_t, audioio_mixer_voice_t, voice_count);
+ self->base.type = &audioio_mixer_type;
+ common_hal_audioio_mixer_construct(self, voice_count, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitialises the Mixer and releases any hardware resources for reuse.
+//|
+STATIC mp_obj_t audioio_mixer_deinit(mp_obj_t self_in) {
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_audioio_mixer_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_deinit_obj, audioio_mixer_deinit);
+
+//| .. method:: __enter__()
+//|
+//| No-op used by Context Managers.
+//|
+// Provided by context manager helper.
+
+//| .. method:: __exit__()
+//|
+//| Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+STATIC mp_obj_t audioio_mixer_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_audioio_mixer_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_mixer___exit___obj, 4, 4, audioio_mixer_obj___exit__);
+
+
+//| .. method:: play(sample, *, voice=0, loop=False)
+//|
+//| Plays the sample once when loop=False and continuously when loop=True.
+//| Does not block. Use `playing` to block.
+//|
+//| Sample must be an `audioio.WaveFile`, `audioio.Mixer` or `audioio.RawSample`.
+//|
+//| The sample must match the Mixer's encoding settings given in the constructor.
+//|
+STATIC mp_obj_t audioio_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_sample, ARG_voice, ARG_loop };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_voice, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ };
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t sample = args[ARG_sample].u_obj;
+ common_hal_audioio_mixer_play(self, sample, args[ARG_voice].u_int, args[ARG_loop].u_bool);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_play_obj, 1, audioio_mixer_obj_play);
+
+//| .. method:: stop_voice(voice=0)
+//|
+//| Stops playback of the sample on the given voice.
+//|
+STATIC mp_obj_t audioio_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_voice };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_voice, MP_ARG_INT, {.u_int = 0} },
+ };
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ common_hal_audioio_mixer_stop_voice(self, args[ARG_voice].u_int);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_stop_voice_obj, 1, audioio_mixer_obj_stop_voice);
+
+//| .. attribute:: playing
+//|
+//| True when any voice is being output. (read-only)
+//|
+STATIC mp_obj_t audioio_mixer_obj_get_playing(mp_obj_t self_in) {
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ return mp_obj_new_bool(common_hal_audioio_mixer_get_playing(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_playing_obj, audioio_mixer_obj_get_playing);
+
+const mp_obj_property_t audioio_mixer_playing_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audioio_mixer_get_playing_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: sample_rate
+//|
+//| 32 bit value that dictates how quickly samples are played in Hertz (cycles per second).
+//|
+STATIC mp_obj_t audioio_mixer_obj_get_sample_rate(mp_obj_t self_in) {
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_mixer_get_sample_rate(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_sample_rate_obj, audioio_mixer_obj_get_sample_rate);
+
+
+const mp_obj_property_t audioio_mixer_sample_rate_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audioio_mixer_get_sample_rate_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t audioio_mixer_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_mixer_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_mixer___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audioio_mixer_play_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_voice), MP_ROM_PTR(&audioio_mixer_stop_voice_obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audioio_mixer_playing_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_mixer_sample_rate_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(audioio_mixer_locals_dict, audioio_mixer_locals_dict_table);
+
+const mp_obj_type_t audioio_mixer_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Mixer,
+ .make_new = audioio_mixer_make_new,
+ .locals_dict = (mp_obj_dict_t*)&audioio_mixer_locals_dict,
+};
diff --git a/shared-bindings/audioio/Mixer.h b/shared-bindings/audioio/Mixer.h
new file mode 100644
index 000000000..832072b8f
--- /dev/null
+++ b/shared-bindings/audioio/Mixer.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "shared-module/audioio/Mixer.h"
+#include "shared-bindings/audioio/RawSample.h"
+
+extern const mp_obj_type_t audioio_mixer_type;
+
+void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
+ uint8_t voice_count,
+ uint32_t buffer_size,
+ uint8_t bits_per_sample,
+ bool samples_signed,
+ uint8_t channel_count,
+ uint32_t sample_rate);
+
+void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self);
+bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self);
+void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t voice, bool loop);
+void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice);
+
+bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self);
+uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c
index 8a00b43d8..4786b6425 100644
--- a/shared-bindings/audioio/__init__.c
+++ b/shared-bindings/audioio/__init__.c
@@ -32,6 +32,8 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/audioio/__init__.h"
#include "shared-bindings/audioio/AudioOut.h"
+#include "shared-bindings/audioio/Mixer.h"
+#include "shared-bindings/audioio/RawSample.h"
#include "shared-bindings/audioio/WaveFile.h"
//| :mod:`audioio` --- Support for audio input and output
@@ -49,6 +51,7 @@
//| :maxdepth: 3
//|
//| AudioOut
+//| Mixer
//| RawSample
//| WaveFile
//|
@@ -61,6 +64,7 @@
STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audioio) },
{ MP_ROM_QSTR(MP_QSTR_AudioOut), MP_ROM_PTR(&audioio_audioout_type) },
+ { MP_ROM_QSTR(MP_QSTR_Mixer), MP_ROM_PTR(&audioio_mixer_type) },
{ MP_ROM_QSTR(MP_QSTR_RawSample), MP_ROM_PTR(&audioio_rawsample_type) },
{ MP_ROM_QSTR(MP_QSTR_WaveFile), MP_ROM_PTR(&audioio_wavefile_type) },
};
diff --git a/shared-module/audioio/Mixer.c b/shared-module/audioio/Mixer.c
new file mode 100644
index 000000000..8020a621e
--- /dev/null
+++ b/shared-module/audioio/Mixer.c
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/audioio/Mixer.h"
+
+#include <stdint.h>
+
+#include "py/runtime.h"
+#include "shared-module/audioio/__init__.h"
+#include "shared-module/audioio/RawSample.h"
+
+void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
+ uint8_t voice_count,
+ uint32_t buffer_size,
+ uint8_t bits_per_sample,
+ bool samples_signed,
+ uint8_t channel_count,
+ uint32_t sample_rate) {
+ self->len = buffer_size / 2 / sizeof(uint32_t) * sizeof(uint32_t);
+
+ self->first_buffer = m_malloc(self->len, false);
+ if (self->first_buffer == NULL) {
+ common_hal_audioio_mixer_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer"));
+ }
+
+ self->second_buffer = m_malloc(self->len, false);
+ if (self->second_buffer == NULL) {
+ common_hal_audioio_mixer_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer"));
+ }
+
+ self->bits_per_sample = bits_per_sample;
+ self->samples_signed = samples_signed;
+ self->channel_count = channel_count;
+ self->sample_rate = sample_rate;
+ self->voice_count = voice_count;
+
+ for (uint8_t i = 0; i < self->voice_count; i++) {
+ self->voice[i].sample = NULL;
+ }
+}
+
+void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self) {
+ self->first_buffer = NULL;
+ self->second_buffer = NULL;
+}
+
+bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self) {
+ return self->first_buffer == NULL;
+}
+
+uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self) {
+ return self->sample_rate;
+}
+
+void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t v, bool loop) {
+ if (v >= self->voice_count) {
+ mp_raise_ValueError(translate("Voice index too high"));
+ }
+ if (audiosample_sample_rate(sample) != self->sample_rate) {
+ mp_raise_ValueError(translate("The sample's sample rate does not match the mixer's"));
+ }
+ if (audiosample_channel_count(sample) != self->channel_count) {
+ mp_raise_ValueError(translate("The sample's channel count does not match the mixer's"));
+ }
+ if (audiosample_bits_per_sample(sample) != self->bits_per_sample) {
+ mp_raise_ValueError(translate("The sample's bits_per_sample does not match the mixer's"));
+ }
+ bool single_buffer;
+ bool samples_signed;
+ uint32_t max_buffer_length;
+ uint8_t spacing;
+ audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed,
+ &max_buffer_length, &spacing);
+ if (samples_signed != self->samples_signed) {
+ mp_raise_ValueError(translate("The sample's signedness does not match the mixer's"));
+ }
+ audioio_mixer_voice_t* voice = &self->voice[v];
+ voice->sample = sample;
+ voice->loop = loop;
+
+ audiosample_reset_buffer(sample, false, 0);
+ audioio_get_buffer_result_t result = audiosample_get_buffer(sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length);
+ // Track length in terms of words.
+ voice->buffer_length /= sizeof(uint32_t);
+ voice->more_data = result == GET_BUFFER_MORE_DATA;
+}
+
+void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice) {
+ self->voice[voice].sample = NULL;
+}
+
+bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self) {
+ for (int32_t v = 0; v < self->voice_count; v++) {
+ if (self->voice[v].sample != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel) {
+ for (int32_t i = 0; i < self->voice_count; i++) {
+ self->voice[i].sample = NULL;
+ }
+}
+
+uint32_t add8signed(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ return __QADD8(a, b);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 4; i++) {
+ int8_t ai = a >> (sizeof(int8_t) * 8 * i);
+ int8_t bi = b >> (sizeof(int8_t) * 8 * i);
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > CHAR_MAX) {
+ intermediate = CHAR_MAX;
+ } else if (intermediate < CHAR_MIN) {
+ //intermediate = CHAR_MIN;
+ }
+ result |= (((uint32_t) intermediate) & 0xff) << (sizeof(int8_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+uint32_t add8unsigned(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ // Subtract out the DC offset, add and then shift back.
+ a = __USUB8(a, 0x80808080);
+ b = __USUB8(b, 0x80808080);
+ uint32_t sum = __QADD8(a, b);
+ return __UADD8(sum, 0x80808080);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 4; i++) {
+ int8_t ai = (a >> (sizeof(uint8_t) * 8 * i)) - 128;
+ int8_t bi = (b >> (sizeof(uint8_t) * 8 * i)) - 128;
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > UCHAR_MAX) {
+ intermediate = UCHAR_MAX;
+ }
+ result |= ((uint8_t) intermediate + 128) << (sizeof(uint8_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+uint32_t add16signed(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ return __QADD16(a, b);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 2; i++) {
+ int16_t ai = a >> (sizeof(int16_t) * 8 * i);
+ int16_t bi = b >> (sizeof(int16_t) * 8 * i);
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > SHRT_MAX) {
+ intermediate = SHRT_MAX;
+ } else if (intermediate < SHRT_MIN) {
+ intermediate = SHRT_MIN;
+ }
+ result |= (((uint32_t) intermediate) & 0xffff) << (sizeof(int16_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+uint32_t add16unsigned(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ // Subtract out the DC offset, add and then shift back.
+ a = __USUB16(a, 0x80008000);
+ b = __USUB16(b, 0x80008000);
+ uint32_t sum = __QADD16(a, b);
+ return __UADD16(sum, 0x80008000);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 2; i++) {
+ int16_t ai = (a >> (sizeof(uint16_t) * 8 * i)) - 0x8000;
+ int16_t bi = (b >> (sizeof(uint16_t) * 8 * i)) - 0x8000;
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > USHRT_MAX) {
+ intermediate = USHRT_MAX;
+ }
+ result |= ((uint16_t) intermediate + 0x8000) << (sizeof(int16_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer,
+ uint32_t* buffer_length) {
+ if (!single_channel) {
+ channel = 0;
+ }
+
+ uint32_t channel_read_count = self->left_read_count;
+ if (channel == 1) {
+ channel_read_count = self->right_read_count;
+ }
+ *buffer_length = self->len;
+
+ bool need_more_data = self->read_count == channel_read_count;
+ if (need_more_data) {
+ uint32_t* word_buffer;
+ if (self->use_first_buffer) {
+ *buffer = (uint8_t*) self->first_buffer;
+ word_buffer = self->first_buffer;
+ } else {
+ *buffer = (uint8_t*) self->second_buffer;
+ word_buffer = self->second_buffer;
+ }
+ self->use_first_buffer = !self->use_first_buffer;
+ bool voices_active = false;
+ for (int32_t v = 0; v < self->voice_count; v++) {
+ audioio_mixer_voice_t* voice = &self->voice[v];
+
+ uint32_t j = 0;
+ bool voice_done = voice->sample == NULL;
+ for (uint32_t i = 0; i < self->len / sizeof(uint32_t); i++) {
+ if (!voice_done && j >= voice->buffer_length) {
+ if (!voice->more_data) {
+ if (voice->loop) {
+ audiosample_reset_buffer(voice->sample, false, 0);
+ } else {
+ voice->sample = NULL;
+ voice_done = true;
+ }
+ }
+ if (!voice_done) {
+ // Load another buffer
+ audioio_get_buffer_result_t result = audiosample_get_buffer(voice->sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length);
+ // Track length in terms of words.
+ voice->buffer_length /= sizeof(uint32_t);
+ voice->more_data = result == GET_BUFFER_MORE_DATA;
+ j = 0;
+ }
+ }
+ // First active voice gets copied over verbatim.
+ uint32_t sample_value;
+ if (voice_done) {
+ // Exit early if another voice already set all samples once.
+ if (voices_active) {
+ continue;
+ }
+ sample_value = 0;
+ if (!self->samples_signed) {
+ if (self->bits_per_sample == 8) {
+ sample_value = 0x7f7f7f7f;
+ } else {
+ sample_value = 0x7fff7fff;
+ }
+ }
+ } else {
+ sample_value = voice->remaining_buffer[j];
+ }
+
+ if (!voices_active) {
+ word_buffer[i] = sample_value;
+ } else {
+ if (self->bits_per_sample == 8) {
+ if (self->samples_signed) {
+ word_buffer[i] = add8signed(word_buffer[i], sample_value);
+ } else {
+ word_buffer[i] = add8unsigned(word_buffer[i], sample_value);
+ }
+ } else {
+ if (self->samples_signed) {
+ word_buffer[i] = add16signed(word_buffer[i], sample_value);
+ } else {
+ word_buffer[i] = add16unsigned(word_buffer[i], sample_value);
+ }
+ }
+ }
+ j++;
+ }
+ voice->buffer_length -= j;
+ voice->remaining_buffer += j;
+
+ voices_active = true;
+ }
+
+ self->read_count += 1;
+ } else if (!self->use_first_buffer) {
+ *buffer = (uint8_t*) self->first_buffer;
+ } else {
+ *buffer = (uint8_t*) self->second_buffer;
+ }
+
+
+ if (channel == 0) {
+ self->left_read_count += 1;
+ } else if (channel == 1) {
+ self->right_read_count += 1;
+ *buffer = *buffer + self->bits_per_sample / 8;
+ }
+ return GET_BUFFER_MORE_DATA;
+}
+
+void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing) {
+ *single_buffer = false;
+ *samples_signed = self->samples_signed;
+ *max_buffer_length = self->len;
+ if (single_channel) {
+ *spacing = self->channel_count;
+ } else {
+ *spacing = 1;
+ }
+}
diff --git a/shared-module/audioio/Mixer.h b/shared-module/audioio/Mixer.h
new file mode 100644
index 000000000..6a88fe0bd
--- /dev/null
+++ b/shared-module/audioio/Mixer.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
+
+#include "py/obj.h"
+
+#include "shared-module/audioio/__init__.h"
+
+typedef struct {
+ mp_obj_t sample;
+ bool loop;
+ bool more_data;
+ uint32_t* remaining_buffer;
+ uint32_t buffer_length;
+} audioio_mixer_voice_t;
+
+typedef struct {
+ mp_obj_base_t base;
+ uint32_t* first_buffer;
+ uint32_t* second_buffer;
+ uint32_t len; // in words
+ uint8_t bits_per_sample;
+ bool use_first_buffer;
+ bool samples_signed;
+ uint8_t channel_count;
+ uint32_t sample_rate;
+
+ uint32_t read_count;
+ uint32_t left_read_count;
+ uint32_t right_read_count;
+
+ uint8_t voice_count;
+ audioio_mixer_voice_t voice[];
+} audioio_mixer_obj_t;
+
+
+// These are not available from Python because it may be called in an interrupt.
+void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel);
+audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer,
+ uint32_t* buffer_length); // length in bytes
+void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
diff --git a/shared-module/audioio/WaveFile.c b/shared-module/audioio/WaveFile.c
index 7efad05e0..e5a7b1a3b 100644
--- a/shared-module/audioio/WaveFile.c
+++ b/shared-module/audioio/WaveFile.c
@@ -200,13 +200,29 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t*
if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK) {
return GET_BUFFER_ERROR;
}
+ self->bytes_remaining -= length_read;
+ // Pad the last buffer to word align it.
+ if (self->bytes_remaining == 0 && length_read % sizeof(uint32_t) != 0) {
+ uint32_t pad = length_read % sizeof(uint32_t);
+ length_read += pad;
+ if (self->bits_per_sample == 8) {
+ for (uint32_t i = 0; i < pad; i++) {
+ ((uint8_t*) (*buffer))[length_read / sizeof(uint8_t) - i - 1] = 0x80;
+ }
+ } else if (self->bits_per_sample == 16) {
+ // We know the buffer is aligned because we allocated it onto the heap ourselves.
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ ((int16_t*) (*buffer))[length_read / sizeof(int16_t) - 1] = 0;
+ #pragma GCC diagnostic pop
+ }
+ }
*buffer_length = length_read;
if (self->buffer_index % 2 == 1) {
self->second_buffer_length = length_read;
} else {
self->buffer_length = length_read;
}
- self->bytes_remaining -= length_read;
self->buffer_index += 1;
self->read_count += 1;
}
diff --git a/shared-module/audioio/__init__.c b/shared-module/audioio/__init__.c
new file mode 100644
index 000000000..b87b06a83
--- /dev/null
+++ b/shared-module/audioio/__init__.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-module/audioio/__init__.h"
+
+#include "py/obj.h"
+#include "shared-bindings/audioio/Mixer.h"
+#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/audioio/WaveFile.h"
+#include "shared-module/audioio/Mixer.h"
+#include "shared-module/audioio/RawSample.h"
+#include "shared-module/audioio/WaveFile.h"
+
+uint32_t audiosample_sample_rate(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->sample_rate;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->sample_rate;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->sample_rate;
+ }
+ return 16000;
+}
+
+uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->bits_per_sample;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->bits_per_sample;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->bits_per_sample;
+ }
+ return 8;
+}
+
+uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->channel_count;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->channel_count;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->channel_count;
+ }
+ return 1;
+}
+
+void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ audioio_rawsample_reset_buffer(sample, single_channel, audio_channel);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_wavefile_reset_buffer(file, single_channel, audio_channel);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_mixer_reset_buffer(file, single_channel, audio_channel);
+ }
+}
+
+audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer, uint32_t* buffer_length) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_mixer_get_buffer(file, single_channel, channel, buffer, buffer_length);
+ }
+ return GET_BUFFER_DONE;
+}
+
+void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer,
+ samples_signed, max_buffer_length, spacing);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
+ max_buffer_length, spacing);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_mixer_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
+ max_buffer_length, spacing);
+ }
+}
diff --git a/shared-module/audioio/__init__.h b/shared-module/audioio/__init__.h
index 2491beb12..c805f3116 100644
--- a/shared-module/audioio/__init__.h
+++ b/shared-module/audioio/__init__.h
@@ -27,10 +27,27 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/obj.h"
+
typedef enum {
GET_BUFFER_DONE, // No more data to read
GET_BUFFER_MORE_DATA, // More data to read.
GET_BUFFER_ERROR, // Error while reading data.
} audioio_get_buffer_result_t;
+uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
+uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
+uint8_t audiosample_channel_count(mp_obj_t sample_obj);
+void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel);
+audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer, uint32_t* buffer_length);
+void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing);
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
diff --git a/shared-module/displayio/Sprite.c b/shared-module/displayio/Sprite.c
index 4fe8d1ff6..87600f721 100644
--- a/shared-module/displayio/Sprite.c
+++ b/shared-module/displayio/Sprite.c
@@ -68,7 +68,7 @@ bool displayio_sprite_get_pixel(displayio_sprite_t *self, int16_t x, int16_t y,
if (y < 0 || y >= self->height || x >= self->width || x < 0) {
return false;
}
- uint32_t value;
+ uint32_t value = 0;
if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
value = common_hal_displayio_bitmap_get_pixel(self->bitmap, x, y);
} else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
diff --git a/tools/preprocess_frozen_modules.py b/tools/preprocess_frozen_modules.py
index d157deeee..bb6959f0d 100755
--- a/tools/preprocess_frozen_modules.py
+++ b/tools/preprocess_frozen_modules.py
@@ -33,7 +33,7 @@ def copy_and_process(in_dir, out_dir):
for root, subdirs, files in os.walk(in_dir):
# Skip library examples directories.
- if Path(root).name in ['examples', 'docs']:
+ if Path(root).name in ['examples', 'docs', 'tests']:
continue
for file in files: