I'm trying to use a TDA1543 DAC in order to generate an analog audio signal.
The samples are generated with a bytebeat formula.
The fact is, when I set the sample rate of the DAC at 8Khz (the frequency that generate classic bytebeat melodies) I get very loud high frequencies.
But when I increase the sample rate to 24000 or 32000, the high frequencies disappear. It's great, but it is not classic bytebeat anymore. ( bytebeat need to be sampled at 8khz. With an 8-bit variable, it increases to 255 and generate an 8000/255=~31.30Hz sawtooth).
It is because the sampling rate is inside the audio range ?
Here is my code:
#include <I2S.h>
// Create the I2S port using a PIO state machine
I2S i2s(OUTPUT);
// GPIO pin numbers
#define pBCLK 1
#define pWS 2
#define pDOUT 3
const int sampleRate = 24000;
void setup() {
Serial.begin(115200);
Serial.println("I2S simple tone");
i2s.setBCLK(pBCLK);
i2s.setDATA(pDOUT);
i2s.setBitsPerSample(16);
if (!i2s.begin(sampleRate)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
}
void loop() {
static int t = 0;
long value = ((t >> 10) & 42) * t;
Serial.println(value);
// write the same sample twice, once for left and once for the right channel
i2s.write(value);
i2s.write(value);
t++;
}
It's probably due to aliasing. If you sample at 8kHz you have to put the input to the ADC through a low pass filter to remove any frequencies > 0.5 * 8kHz.
When you sample at 24kHz or 32kHz you don't hear a problem because either the original input doesn't contain much above 12 kHz or 16 kHz and / or the spurious high frequencies can't be reproduced by your speaker or heard by you.
See Nyquist frequency - Wikipedia
A closer look reveals a stair output, not a sawtooth. Each step introduces harmonic frequencies which have to be reduced/eliminated by a discrete low pass filter.
If you are sampling at 8 kHz, then you need a very good low pass filter for the output signal, such that any component with frequency above about 4 kHz becomes insignificant.
This site gives some background and examples of bytebeat.
In any case, this loop does NOT create samples at 8 kHz sample rate. It does not even have a fixed or well defined sample rate, because the serial print can take variable amounts of time to execute.
void loop() {
static int t = 0;
long value = ((t >> 10) & 42) * t;
Serial.println(value);
// write the same sample twice, once for left and once for the right channel
i2s.write(value);
i2s.write(value);
t++;
}
If you are sampling at 8 kHz, then you need a very good low pass filter for the output signal, such that any component with frequency above about 4 kHz becomes insignificant.
Ok, so it joins what DrDiettrich says.
This site gives some background and examples of bytebeat.
I know dollchan. My aim is to get roughly the same audio quality as the website output with a DAC.
In any case, this loop does NOT create samples at 8 kHz sample rate. It does not even have a fixed or well defined sample rate, because the serial print can take variable amounts of time to execute.
Hum. The sample rate is set in the setup
if (!i2s.begin(sampleRate)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
with sampleRate = 8000 for exemple
You can guess that I didn't leave the Serial.println on all my tests and I had almost the same results
So the best way I can follow is the discrete low pass filter in order to get rid of these unwanted frequencies.
That has nothing to do with how often the loop executes, unless the function I2s.write() blocks, which won't happen if the loop is slower than the sample rate.
I removed it. It might be a little better, but it's so imperceptible that I'm not sure.
There's still a hiss in the background.
Maybe putting a low pass filter will finish the job