-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mimxrt10xx: Add PWMAudioOut #7785
Conversation
.. via a peripheral known as the "MQS" (medium quality sound). It uses an ~192kHz PWM signal to generate audio. It sounds OK on a small speaker with no amplifier. There's a small pop when starting/stopping audio, as is typical.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I use my test program (see below), and then ctrl-C it, then when I restart it, I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "play.py", line 14, in <module>
ValueError: I2SOut in use
This is confusing, because it's not known to the user that I2S is in use, and something is not being reset when the VM starts up (or shuts down).
import array
import board
import os
import time
from audiocore import RawSample, WaveFile
from audiopwmio import PWMAudioOut
def print_filenames(filenames):
for num, filename in enumerate(filenames):
print(f"{num:2d} {filename}")
pwm_out = PWMAudioOut(left_channel=board.A1, right_channel=board.A0)
wavs = []
for filename in (os.listdir()):
if filename.endswith(".wav"):
wavs.append(filename)
wavs.sort()
print_filenames(wavs)
while True:
inp = input("play: ").split()
try:
filenum = int(inp[0])
except (IndexError, ValueError):
print_filenames(wavs)
continue
if filenum >= len(wavs):
print_filenames(wavs)
continue
if len(inp) > 1:
try:
mode = modes[inp[1]]
except:
print_filenames(wavs)
continue
filename = wavs[filenum]
wav = WaveFile(open(filename, "rb"))
print(f" playing {filename}")
pwm_out.play(wav)
time.sleep(1.2)
Also the "." debugging printout continued to run after the playing was finished. Maybe that's just how the I2S hw is working, but it seems like the interrupt continues even when play is done:
|
Yes, we keep feeding the peripheral with zeros (only signed 16-bit samples are ever output, so this is the "quiescent value"; the value specified by the user is always ignored) because otherwise the hardware signals FIFO underruns and gets grumpy. There may be a clever way to turn the FIFO off exactly when it empties, but it was easier to just keep giving it zeroed data. |
OK I think I've fixed the problem with the |
.. for reasons stated in the comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the previous problems seem gone. One thing I notice is that if I play samples recorded at certain rates, the pitch changes. For instance a 440 Hz 11k .wav is not the same pitch as 8k,16k, or 32k, all of which are at the same pitch. Is this inherent in the way the MQS works? Should we forbid files whose sample rates are not evenly divisible into 192k, or just add a **Limitations**:
warning?
sine-samples.zip
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Approving with caveat of i.MX I2SOut and PWMAudioOut: sample rates not evenly divisible into 192kHz are off pitch #7800, which I will release note.
.. via a peripheral known as the "MQS" (medium quality sound). It uses an ~192kHz PWM signal to generate audio. It sounds OK on a small speaker with no amplifier. There's a small pop when starting/stopping audio, as is typical.
tested with wave files & audiomixer on metro m7. Only these specific pins may be used (not that A1 has to be left channel and A0 has to be right channel):