#I2S Audio
1 messages · Page 1 of 1 (latest)
So I tried to shorten your code so that I could just test its functionality. The audio is still blasting at full strength, and it appears to only output one voice. If the voice level is set to 0 it turns it off, but otherwise, it's on full blast, and it appears that 0 supersedes 1 when both are on:
# audiomixer_demo_i2s.py -- show how to fade up and down playing loops
# 30 Nov 2022 - @todbot / Tod Kurt
import time
import board
import audiocore
import audiomixer
import audiobusio
import audiomp3
i2s_bclk = board.GP0 # BCK on PCM5102 I2S DAC (SCK pin to Gnd)
i2s_wsel = board.GP1 # LCLK on PCM5102
i2s_data = board.GP2 # DIN on PCM5102
num_voices = 2
audio = audiobusio.I2SOut(bit_clock=i2s_bclk, word_select=i2s_wsel, data=i2s_data)
mixer = audiomixer.Mixer(voice_count=num_voices, sample_rate=16000, channel_count=1,
bits_per_sample=16, samples_signed=True)
audio.play(mixer) # attach mixer to audio playback
print("audio is now playing")
# set some initial levels
mixer.voice[0].level = 0.1 # drums on
mixer.voice[1].level = 0.1 # synth off
# load wav and start drum loop playing
wave0 = audiocore.WaveFile(open("StreetChicken1600.wav","rb"))
mixer.voice[0].play( wave0, loop=True )
# load wav and start synth loop playing
wave1 = audiocore.WaveFile(open("test1600-low-volume.wav","rb"))
mixer.voice[1].play( wave1, loop=True )
time.sleep(1.0) # let drums play a bit
while True:
print("voice 0 level=%1.2f" % mixer.voice[0].level)
print("voice 1 level=%1.2f" % mixer.voice[1].level)
time.sleep(0.1)
What's even more curious/frustrating is that the voice levels display as they should in the shell.
One clue though is that I'm using an Adafruit MAX98357A amplifier breakout: https://www.adafruit.com/product/3006 which is set up to a 9dB gain, and can be set to lower with a resistor. I'll have to try putting a resistor in to change the behavior, but I'm surprised that the I2C volume control seems to have no effect.
@lilac sedge LMK what you think about that code, perhaps I've omitted something important.
code looks okay to me. perhaps that I2S amp is doing something funky with its stereo->mono conversion. Try setting its "SD" pin to 3.3V. That should set it to Left channel only
do you have another I2S board to try?
is the wav file mono or stereo?
good point. @steep pollen try using the WAVs (and sample rate settings) I've prepared to see if you can at least recreate my sketch
Thx - I believe these are the correct files: https://github.com/todbot/circuitpython-tricks/tree/main/larger-tricks/wav ?
Also, your button is simply acting as a reset? Clever.
@lilac sedge Got your code to run, thanks so much! The SD jumper to 3.3V seems to improve the sound.
One small note, on your Gist I believe you have a typo on line 46 - "incq" = "inc"?
Hey progress! And oops sorry about that. Looks like I fat-fingered the file on upload to gist
Oh and yes that button in the video is on the RESET pin since Pico’s don’t have a reset button
@lilac sedge Looking at this again with a PAM302 amp from Adafruit - https://www.adafruit.com/product/2130 I tried putting in a max_audio_level as shown to your code: https://github.com/todbot/circuitpython-tricks/blob/main/larger-tricks/audiomixer_demo.py. Seems to kind of work, but hisses a bit and not nearly as quiet as I would suspect for .05.
# Write your code here :-)
# audiomixer_demo.py -- show how to fade up and down playing loops
# note this causes glitches and crashes on RP2040
# 9 Feb 2022 - @todbot / Tod Kurt
c
import time
import board
import audiocore
import audiomixer
from audiopwmio import PWMAudioOut as AudioOut # for RP2040 etc
#from audioio import AudioOut as AudioOut # for SAMD51/M4 etc
num_voices = 2
max_audio_level = .05
# audio pin is almost any pin on RP2040, let's do A0 (RP2040 GPIO226) or RX (RP2040 GPIO1)
# audio pin is A0 on SAMD51 (Trelllis M4, Itsy M4, etc)
audio = AudioOut(board.A0)
mixer = audiomixer.Mixer(voice_count=num_voices, sample_rate=22050, channel_count=1,
bits_per_sample=16, samples_signed=True)
# attach mixer to audio playback
audio.play(mixer)
mixer.voice[0].level = max_audio_level
mixer.voice[1].level = 0.0
# start drum loop playing
wave0 = audiocore.WaveFile(open("wav/drumsacuff_22k_s16.wav","rb"))
mixer.voice[0].play( wave0, loop=True )
# start synth loop playing
wave1 = audiocore.WaveFile(open("wav/snowpeaks_22k_s16.wav","rb"))
mixer.voice[1].play( wave1, loop=True )
time.sleep(1.0) # let drums play a bit
# fade each channel up and down
up_down_inc = 0.01
while True:
mixer.voice[1].level = min(max(mixer.voice[1].level + up_down_inc, 0), max_audio_level)
mixer.voice[0].level = min(max(mixer.voice[0].level - up_down_inc, 0), max_audio_level)
if mixer.voice[0].level == 0 or mixer.voice[1].level == 0:
up_down_inc = -up_down_inc
time.sleep(0.1)
Is this simply a result of the fact that it's doing a PWM out and not actually an ADC? Better to simply use a variable resistor? The I2S board seems to give me much better results in testing, which would make sense if my assumptions here are correct. Thx!
Also, I tied the SD to 3.3V, though I'm not sure what, if anything, that will do.
Actually, more experimentation here, and it seems to hiss at any volume.
With the audio level so low, you're fighting inherent noise in the entire system. I was expecting you to only need to reduce it a few percent. Seems like you need to lower the gain on the amp so you can increase that max_audio_level
but yes there is a hiss with PWM audio. You generally use a small RC filter to remove it. can be as simple as this: https://gregchadwick.co.uk/blog/playing-with-the-pico-pt3/ with the values being not too critical. I usually use around 1k for the resistor and 100n (0.1uF) for the cap
Turned the pot a bit, and hissing either way. Ah, OK, that makes sense... The rabbit hole never ends it seems! Thx!
yes. audio stuff is always kind of a nightmare
but if you can swing it, I2S seems to be the better way to go (but I prefer the ones that do stereo line out (then use a separate amp)
Ah, makes sense. Well I appreciate it!
Taking a look at this again and the I2S documentation https://learn.adafruit.com/mp3-playback-rp2040/pico-i2s-mp3, it states:
As I2S is digital, why does it matter what the PWM output is? Or is it still related somehow?
This is a copy pasta mistake; I'll fix it.
thanks for noting!
Sounds good! Glad to help and to hear my confusion isn't of my own doing!
ahah I thought it was just shade against PWM 😀
@lilac sedge I made a couple more examples modified on your code here: https://github.com/JeremySCook/circuitpython-tricks/tree/main/larger-tricks - I'm not exactly a GitHub aficionado, but once I have things cleaned up you're welcome to integrate it (or not to) to yours in any way you see fit.
I'll likely link it in an article at some point, so I'd be happy for it to reside in one place - whether that's my account or yours!
awesome! I wanted to merge them in but that link seems to be gone now
I can link to this instead if you'd like: https://github.com/JeremySCook/circuitpython-experiments
I really need to get better with GitHub.
Anyway, I hadn't heard back for a few days, so as you noticed I decided to start from scratch on my own experiments repository. I suppose I didn't have to delete the other one, but wanted to keep things clean.
You are welcome to link or even copy my code/files relating to this I2S audio experimentation into your repository as you see fit. Thanks for your help!
BTW, I wrote up this article on the subject, and made sure to credit you there: https://embeddedcomputing.com/technology/open-source/i2s-volume-control-with-raspberry-pi-pico-and-circuitpython
In a recent article, I outlined how to play MP3 files on the Raspberry Pi Pico with no extra components, just a small speaker. I also talked about doing this with the addition of an amplifier. While either is fine for many applications, the Pico does not have a true ADC, meaning it instead uses less-than-perfect PWM to simulate an analog output....
Nice! Thanks for the reference! I gotta get me some of those I2S amps to play with