Audio Distortion After About One Second #7
-
@pschatzmann , I am experiencing a problem with audio distortion occurring after about one second of transmitting data. My code is below:
I first saw this in quisk, an SDR software I use, set for audio frequency. This is shown in the first video. Then I verified it in Audacity. This is shown in the second video below. I have my Ubuntu box set to use the default pulse source. I start out with my microphone (the little squiggle). Then I go to the Pico sending a sinusoid over USB by plugging it in the USB port. You cannot see the distortion looking at the wave in the time domain, but if you look at it in the frequency domain, you can. The distortion does not appear immediately. See the first spectrum and the good results. But after about a second, it starts. See the second spectrum. Note I am making the spectrum so it starts exactly on one cycle and stops ready for the next cycle to avoid spectral leakage. The distortion remains roughly constant after the first second. https://github.com/user-attachments/assets/bc371b39-4ec3-4747-90a9-f78a8347c44d I think this is a problem with the Audio part of the TinyUSB library, but it might be something I don't understand in my code. Can anyone see a bug in my code? |
Beta Was this translation helpful? Give feedback.
Replies: 9 comments 7 replies
-
Hi @frohro you a doing a lot of processing (the M0 in the RP2040 has very weak float performance, you might get better results using a Sin() lookup table, also using fixed point maths is a trick I used to use back in my MC68000 days) in the USB callback, my suggestion is to render the audio to a separate buffer using the second core, and then use the callback to just copy the buffer to the USB stack. I believe the readCB() function is called somewhat sporadically (whenever time is allocated on the bus) so the amount of time available to process it is unpredictable. I can't get Serial and USB Audio functionality to work at the same time, so I have no idea how big the USB stack buffer is at the moment. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Are you sure that the issue is not coming from your sine implementation ? I was using my AudioTools library to generate the sine: #include "Adafruit_TinyUSB.h"
#include "AudioTools.h"
AudioInfo info(48000, 2, 16);
SineWaveGenerator<int16_t> sineWave(32000); // subclass of SoundGenerator with max amplitude of 32000
GeneratedSoundStream<int16_t> sound(sineWave); // Stream generated from sine wave
Adafruit_USBD_Audio usb;
size_t readCB(uint8_t* data, size_t len, Adafruit_USBD_Audio& ref) {
return sound.readBytes(data, len);
}
void setup() {
Serial.begin(115200);
// Setup sine wave
sineWave.begin(info, 12000.0);
// Start USB device as Audio Source
usb.setReadCallback(readCB);
usb.begin(info.sample_rate, info.channels, info.bits_per_sample);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}
void loop() {
// use LED do display status
usb.updateLED();
}
|
Beta Was this translation helpful? Give feedback.
-
In case it helps, I zipped my PlatformIO project up and put it here. |
Beta Was this translation helpful? Give feedback.
-
I am testing on the Ubuntu 24.04 machine recently installed now, building, etc. on it. The results are the same. With the Audacity preference->Recoroding-Detect Dropout on here is what it looks like for the first few seconds after plugging in the Pico. After this, it continues detecting dropouts. Zoomed out: |
Beta Was this translation helpful? Give feedback.
-
Strange: did you set the Project Rate in Audacity at the bottom to the same rate as in the Arduino Sketch ? I was testing with Audacity 2.4.2 which comes with Mint. |
Beta Was this translation helpful? Give feedback.
-
@pschatzmann Okay, so I got it to work okay with AudioTools after messing with the platformio.ini. Your code from AudioTools works well, but mine above has some problem. Thanks for providing me the example in AudioTools. In case it is useful to someone trying to get Audio_Tools going with the Pico as a USB sound card, here is my platformio.ini.
|
Beta Was this translation helpful? Give feedback.
-
Okay, I found the problem with my code by using a different generator made for finding an off by one error. It is here:
The problem was the line:
I needed the -1. @pschatzmann I suspect your original code with the random numbers needs this too, so if someone like me uses it it will work. The example is in your blog here. Perhaps a more accurate way to fix it is to say the for loop goes to samples -1 or maybe in the variable len. In any case it works perfectly with the -1, but there is one point missing on right and left without it. It seems like it might be in len. Here is what it looks like if I make len two less. USB buffer frames are usually 4 bytes. When I print len, it is 194 bytes, and that is not evenly divisible by 4. Here is what my graph looks like with a 1000 Hz sine wave, sampling at 48 kHz with the samples -1. |
Beta Was this translation helpful? Give feedback.
-
Hmm, that's strange: I would not see why size_t samples = len / sizeof(int16_t) should be wrong. |
Beta Was this translation helpful? Give feedback.
I was testing with a Macbook Air running Mint Linux: Your test sketch with a Pico 2 W gives the following for me
And I am getting the same with a regular Pico
So I can't reproduce your issue: Maybe it is related to your Desktop!