Hi,
First let me preface this with a quick apology for the lengthy post as I wanted to be thorough. I am a bit over my head with a lot of this audio stuff and have been stuck on this problem for about 3 weeks so really appreciate any guidance anyone has to offer.
I am hoping to resolve a buzzing issue I am experiencing when sending audio from Raspberry Pi 4 to Teensy 4.0. I am sending audio over via I2S which is 16 bit at 48 kHz. I am aware the Audio library supports 16 bit at 44.1 kHz, so I suspect this frequency misalignment is causing the buzzing issues. The Raspberry Pi 4 is supposed to be the master generating the clocks and sending over the audio data via I2S and then the Teensy is supposed to be a slave which receives the audio via I2S and outputs the audio via USB.
Below is how I am sending over a sample wav file from the pi to the teensy.
"sndrpirpidac" is the i2s enabled via "dtoverlay=i2s-dac" in the boot config of the Raspberry Pi 4 for anyone curious.
The below command sends over a sine wav on 2 channels over i2s using 48 kHz where "hw:0,0" is the is2. This sends sine wav on left channel for about 3 seconds and then right channel, constantly alternating until stopped.
When I send a sine wave at 44.1 like this:
Then the sound does not have the buzzing. I have attached this audio sample in the zip file below by the way. Since this test did not have buzzing, this leads me to believe the frequency misalignment is the source of my problems so I have attempted to make some changes to the Audio library to get 48 kHz to work which has led to a bunch of rabbit holes.
Testing Audio Library Changes Steps
When I modify the Audio library source (cloned repo from here), these are the steps I was always doing during my tests:
Make test changes to Audio library source files. Close Arduino IDE, reopen Arduino IDE, compile the same Arduino code again, unplug Teensy, then uninstalling Teensy from Device Manager, and then plug Teensy back into computer USB.
What I Have Tried:
Changed my I2S wires from 20 cm to 8 cm wires (which are what are shown in the wiring picture below). I have read that long wires can cause I2S issues so early on I thought this was the issue but this was quickly disproven as the 44.1 sine test explained earlier works fine.
Setting "AUDIO_SAMPLE_RATE_EXACT" in "AudioStream.h" to 48000. Then sending over 48 kHz sine wav.
Setting "AUDIO_SAMPLE_RATE_EXACT" in "AudioStream.h" to 48000. Updating "usb_desc.c" by changing all "LSB(44100), MSB(44100), 0," lines to "LSB(48000), MSB(48000), 0," Then sending over 48 kHz sine wav and Front_Center.wav file. Audio samples for both of what was received from these 2 tests are in the zip file below. Note: These 2 changes alone make the device appear as 48 kHz in windows (screenshot later).
Considered sending audio out of Raspberry Pi via headphone jack to audio shield here which would then connect to Teensy over I2S. However, I run into the same problem where this shield accepts 44.1 kHz audio and not 48 kHz as it uses the same audio library when incorporating with the Teensy.
Explored using Teensy4i2s library since it supports 48 kHz over I2S but found out quickly this library does not have usb output implemented.
Using OpenAudio_ArduinoLibrary which has support for 48 kHz. However, this currently does not have I2S slave input implemented. I attempted to add the functionality (pr is here if curious) which unfortunately still resulted in the same buzzing/audio distortion issues.
Researched connecting Raspberry Pi 4 to Teensy 4.0 as slave using 48 kHz. I cannot find any examples of this done.
Researched lots of PJRC threads for converting the Audio library to 48 kHz. I have attempted a bunch of other small minor changes to the source library as well (files input_i2s.cpp, AudioStream.cpp, usb_audio.cpp). I lost track of all of these changes as the more I did the worse the audio got. It got to a point where it was just static white noise coming through so I reverted everything.
Extra Context:
You may ask why not send audio from Raspberry Pi 4 at 44.1 kHz. Yes I have considered this and did attempt this at first but ran into more problems. The board defaults to 48 kHz and trying to override this is not easy especially since 48 kHz seems hardcoded for dmix. Plus, I would prefer to keep it all working in 48 kHz as I have other stuff on the Pi I am trying not to break.
In Arduino IDE, I am selecting Teensy 4.0 board and USB Type Audio. See screenshot below:
Teensy Code used in Arduino IDE:
Raspberry Pi 4 to Teensy 4.0 I2S wiring:
Note: I don't currently have an oscilloscope so hard for me to confirm the clock data is being sent over correctly, but open to getting one to research/investigate this further if that's what it takes.
I would have thought that only setting "AUDIO_SAMPLE_RATE_EXACT" in "AudioStream.h" to 48000 was the main change that was needed from the software side and updating usb descriptors in "usb_desc.c". Doing these 2 tweaks makes Windows think the Teensy device is 48 kHz as shown below:
However, I still have the buzzing problem so I think there are other places in the code that need updating as well. My best guess is that "AUDIO_SAMPLE_RATE_EXACT" is needing implemented in more places like constants or some other math formulas. For example when looking through the Audio library I found the below in "usb_audio.cpp":
feedback_accumulator = 739875226; // 44.1 * 2^24
Which makes me think it should be updated to something like this:
feedback_accumulator = AUDIO_SAMPLE_RATE_EXACT * 2^24;
With only needing I2S slave input and usb audio output, I don't think there are a lot files that would need modified. I was looking specifically at these
input_i2s.cpp, AudioStream.cpp, usb_audio.cpp, output_i2s.cpp, usb_desc.h, usb_desc.c
Does anyone else have any ideas on what to try modifying or think I am missing other files to look at? Let me know if you have any ideas or modifications to files that I should try. Thanks in advance!
Zip file link, sorry I tried to upload the zip file here in the thread but got a file too large for processing which is weird because it is less than 3 mb. Check out the "Front_Center" wav file examples too to hear normal audio, you will hear the buzzing at the end of each word.
drive.google.com
First let me preface this with a quick apology for the lengthy post as I wanted to be thorough. I am a bit over my head with a lot of this audio stuff and have been stuck on this problem for about 3 weeks so really appreciate any guidance anyone has to offer.
I am hoping to resolve a buzzing issue I am experiencing when sending audio from Raspberry Pi 4 to Teensy 4.0. I am sending audio over via I2S which is 16 bit at 48 kHz. I am aware the Audio library supports 16 bit at 44.1 kHz, so I suspect this frequency misalignment is causing the buzzing issues. The Raspberry Pi 4 is supposed to be the master generating the clocks and sending over the audio data via I2S and then the Teensy is supposed to be a slave which receives the audio via I2S and outputs the audio via USB.
Below is how I am sending over a sample wav file from the pi to the teensy.
Code:
aplay -D plughw:CARD=sndrpirpidac,DEV=0 /usr/share/sounds/alsa/Front_Center.wav
"sndrpirpidac" is the i2s enabled via "dtoverlay=i2s-dac" in the boot config of the Raspberry Pi 4 for anyone curious.
The below command sends over a sine wav on 2 channels over i2s using 48 kHz where "hw:0,0" is the is2. This sends sine wav on left channel for about 3 seconds and then right channel, constantly alternating until stopped.
Code:
speaker-test -D hw:0,0 -c 2 -t sine -f 1000 -r 48000
When I send a sine wave at 44.1 like this:
Code:
speaker-test -D hw:0,0 -c 2 -t sine -f 1000 -r 44100
Then the sound does not have the buzzing. I have attached this audio sample in the zip file below by the way. Since this test did not have buzzing, this leads me to believe the frequency misalignment is the source of my problems so I have attempted to make some changes to the Audio library to get 48 kHz to work which has led to a bunch of rabbit holes.
Testing Audio Library Changes Steps
When I modify the Audio library source (cloned repo from here), these are the steps I was always doing during my tests:
Make test changes to Audio library source files. Close Arduino IDE, reopen Arduino IDE, compile the same Arduino code again, unplug Teensy, then uninstalling Teensy from Device Manager, and then plug Teensy back into computer USB.
What I Have Tried:
Changed my I2S wires from 20 cm to 8 cm wires (which are what are shown in the wiring picture below). I have read that long wires can cause I2S issues so early on I thought this was the issue but this was quickly disproven as the 44.1 sine test explained earlier works fine.
Setting "AUDIO_SAMPLE_RATE_EXACT" in "AudioStream.h" to 48000. Then sending over 48 kHz sine wav.
Setting "AUDIO_SAMPLE_RATE_EXACT" in "AudioStream.h" to 48000. Updating "usb_desc.c" by changing all "LSB(44100), MSB(44100), 0," lines to "LSB(48000), MSB(48000), 0," Then sending over 48 kHz sine wav and Front_Center.wav file. Audio samples for both of what was received from these 2 tests are in the zip file below. Note: These 2 changes alone make the device appear as 48 kHz in windows (screenshot later).
Considered sending audio out of Raspberry Pi via headphone jack to audio shield here which would then connect to Teensy over I2S. However, I run into the same problem where this shield accepts 44.1 kHz audio and not 48 kHz as it uses the same audio library when incorporating with the Teensy.
Explored using Teensy4i2s library since it supports 48 kHz over I2S but found out quickly this library does not have usb output implemented.
Using OpenAudio_ArduinoLibrary which has support for 48 kHz. However, this currently does not have I2S slave input implemented. I attempted to add the functionality (pr is here if curious) which unfortunately still resulted in the same buzzing/audio distortion issues.
Researched connecting Raspberry Pi 4 to Teensy 4.0 as slave using 48 kHz. I cannot find any examples of this done.
Researched lots of PJRC threads for converting the Audio library to 48 kHz. I have attempted a bunch of other small minor changes to the source library as well (files input_i2s.cpp, AudioStream.cpp, usb_audio.cpp). I lost track of all of these changes as the more I did the worse the audio got. It got to a point where it was just static white noise coming through so I reverted everything.
Extra Context:
You may ask why not send audio from Raspberry Pi 4 at 44.1 kHz. Yes I have considered this and did attempt this at first but ran into more problems. The board defaults to 48 kHz and trying to override this is not easy especially since 48 kHz seems hardcoded for dmix. Plus, I would prefer to keep it all working in 48 kHz as I have other stuff on the Pi I am trying not to break.
In Arduino IDE, I am selecting Teensy 4.0 board and USB Type Audio. See screenshot below:
Teensy Code used in Arduino IDE:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// --------- AUDIO OBJECTS ----------
AudioInputI2Sslave i2s_in;
AudioOutputUSB usb_out;
AudioConnection patchCord1(i2s_in, 0, usb_out, 0);
AudioConnection patchCord2(i2s_in, 1, usb_out, 1);
void setup() {
AudioMemory(20);
}
void loop() {
}
Raspberry Pi 4 to Teensy 4.0 I2S wiring:
Note: I don't currently have an oscilloscope so hard for me to confirm the clock data is being sent over correctly, but open to getting one to research/investigate this further if that's what it takes.
I would have thought that only setting "AUDIO_SAMPLE_RATE_EXACT" in "AudioStream.h" to 48000 was the main change that was needed from the software side and updating usb descriptors in "usb_desc.c". Doing these 2 tweaks makes Windows think the Teensy device is 48 kHz as shown below:
However, I still have the buzzing problem so I think there are other places in the code that need updating as well. My best guess is that "AUDIO_SAMPLE_RATE_EXACT" is needing implemented in more places like constants or some other math formulas. For example when looking through the Audio library I found the below in "usb_audio.cpp":
feedback_accumulator = 739875226; // 44.1 * 2^24
Which makes me think it should be updated to something like this:
feedback_accumulator = AUDIO_SAMPLE_RATE_EXACT * 2^24;
With only needing I2S slave input and usb audio output, I don't think there are a lot files that would need modified. I was looking specifically at these
input_i2s.cpp, AudioStream.cpp, usb_audio.cpp, output_i2s.cpp, usb_desc.h, usb_desc.c
Does anyone else have any ideas on what to try modifying or think I am missing other files to look at? Let me know if you have any ideas or modifications to files that I should try. Thanks in advance!
Zip file link, sorry I tried to upload the zip file here in the thread but got a file too large for processing which is weird because it is less than 3 mb. Check out the "Front_Center" wav file examples too to hear normal audio, you will hear the buzzing at the end of each word.
PJRC Audio Samples.zip
drive.google.com