Closed jwktje closed 3 weeks ago
I suggest that you use the I2SCodecStream setVolume() API which uses values between 0 and 1.0.
However this does not have any impact on your issue.
The volume in the I2SCodecStream/AudioBoard is managed by the audio driver and the es8388 API. I am not aware of any issues and I never noticed any, so I tend to think that it might be a hardware problem (e.g. a noisy power supply)? How can I reproduce this ? with what sound ? Can you reproduce this with the sine output test case ?
You could also try to manage the volume as described in the WIKI.
@pschatzmann Thanks for the quick reply. I will test soon with the I2SCodecStream.setVolume() and report back if that changes the behaviour.
In the meantime, I have the schematic for the ES8388 module. The only meaningful difference I can find between this and the "TYPICAL APPLICATION CIRCUIT" from the datasheet is that the capacitors on VMID, ADCVREF and VREF are unpolarized rather than polarized.
Apart from that, I couldn't really find any issues. I tested with 3 different ESP32's and 2 different ES8388 and checked all my wiring. So I'm not sure what the issue could be.
The noise is a little better on battery when compared to USB power. But it definitely is there in both scenarios. Regardless of if I'm playing or not playing audio.
Based on what you were saying, I was testing with an AudioKit and this minimal sketch
#include "AudioTools.h"
#include "AudioLibs/AudioBoardStream.h"
AudioInfo info(44100, 2, 16);
AudioBoardStream out(AudioKitEs8388V1);
void setup(void) {
// Open Serial
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
// start Codec & I2S
Serial.println("starting I2S...");
auto config = out.defaultConfig(TX_MODE);
config.copyFrom(info);
out.begin(config);
// set volume with max noise
out.setVolume(0.88);
}
void loop() {
out.writeSilence(1024);
}
I could not hear any noise via the earphones! I was powering the device via the UART usb cable of my notebook.
ps. just some more comments to your code:
my_pins.begin();
audio_board.begin();
are not necessary since they will be executed by i2s_out_stream.begin
Maybe you can compare it with this
I have done a bunch more testing, and I think 2 things are happing at the same time.
See my reduced test-case below.
There is some noticeable hiss, especially at 0.25 volume, on my board, that I don't hear on an Olimex ESP-ADF. So that part may very well be hardware related. So I'm gonna thoroughly compare the schematics in hopes of figuring out the cause.
But secondly, when the file finishes playing, I hear a looped glitch. Which seems to me like it could be because I should be handling this differently. When the file is done copying, should copier.copy() just keep running? Or do I need to catch that it ran through the entire file, write silence, and stop copying?
Because I think that the hiss (possibly HW related) and the looped glitch (probably firmware related) together might be what I'm hearing.
#include "AudioTools.h"
#include "AudioLibs/AudioSourceSD.h"
#include "AudioLibs/I2SCodecStream.h"
#include "AudioCodecs/CodecWAV.h"
// I2C
#define SDAPIN 18 // I2C Data
#define SCLPIN 23 // I2C Clock
#define I2CSPEED 100000 // Clock Rate
#define ES8388ADDR 0x10 // Address of ES8388 I2C port
// I2S, your configuration for the ES8388 board
#define MCLKPIN 0 // Master Clock
#define BCLKPIN 5 // Bit Clock
#define WSPIN 25 // Word select
#define DOPIN 26 // This is connected to DI on ES8388 (MISO)
#define DIPIN 35 // This is connected to DO on ES8388 (MOSI)
// SD
#define SD_CS 21
#define SD_SCK 14
#define SD_MISO 12
#define SD_MOSI 13
#define SD_SS 15
DriverPins my_pins; // board pins
AudioBoard audio_board(AudioDriverES8388, my_pins); // audio board
I2SCodecStream i2s_out_stream(audio_board); // i2s codec
TwoWire myWire = TwoWire(0);
WAVDecoder decoder;
File file;
StreamCopy copier(i2s_out_stream, file); // copies data
void setup() {
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
LOGLEVEL_AUDIODRIVER = AudioDriverWarning;
Serial.println("Setup starting...");
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_SS);
if (!SD.begin(SD_CS)) {
Serial.println("Card Mount Failed");
return;
}
my_pins.addI2C(PinFunction::CODEC, SCLPIN, SDAPIN, ES8388ADDR, I2CSPEED, myWire);
my_pins.addI2S(PinFunction::CODEC, MCLKPIN, BCLKPIN, WSPIN, DOPIN, DIPIN);
auto i2s_config = i2s_out_stream.defaultConfig();
i2s_out_stream.begin(i2s_config);
i2s_out_stream.setVolume(0.25); //The most problematic level in my full firmware.
Serial.println("Playing audio file...");
file = SD.open("/test.wav", FILE_READ);
}
void loop() {
copier.copy();
}
Check if your installed version supports i2s_config.auto_clear = true. If not you might need to upgrade to have the latest corrections: the default value is set to true...
Okay that did improve most of the issue I have!
I added i2s_config.auto_clear = true;
Now it (I assume) autodetects when the file is finished, and it mutes the DAC probably.
What I observe now is that the glitchy loop at the end of the playback is gone. But strangely the white noise hissing is gone when the file ends, but not during playback.
So there still is some remaining problem. Which may or may not be hardware related. So I will do further testing on different boards, with different WAV files, with different volume levels. Just so I know what the real remaining issue is.
The complete silence between playback after auto_clear
was added is throwing me for a loop. Because this tells me that the hiss isn't passively coming from my PCB through analog interference. It really is produced by the ES8388 at certain set volumes.
EDIT: Just so I know we're testing with the same parameters; what is the best WAV file format to use? I'm testing with 44.1 kHz 16 bit stereo PCM WAV.
hi jwktje, first i wanted to thank you for your info's, it made me to respond too! i have tested the ES8388 too. funny thing is, i get a lot more noise. i am using Bluetooth, when it gets connected, it just get so jittery, and it is not even playing. but as i understand, the ES8388 is a very bad DAC. it has a very high distortion and the quality is very bad at high volumes like over 0.6 . i am moving on to other DAC's . by the way, i am using hi-fi system, so i hear everything on the line. but if you are using class D amps, you wont get so many jitter.
I'm still testing a bunch, ruling out variables. Just so we don't waste Phil's time with issues that are not his problem. I have excluded some things. The issue is not due to:
By which I can mostly conclude there must be a faulty hardware design. But I have not found any difference yet between my design and the ESP-ADF board by Olimex. Luckily they also publish their schematics, so I can compare. And I haven't found differences in the schematic. Maybe the exact routing of the traces on the board could introduce some noise like I'm getting? I'm not sure.
I will continue testing to further narrow it down
i am not sure if it helps or not, but i have seen few things in them.
first, the quality of the chips.
second, can you check the Vcc line that goes to esp8388? usually there is a resistor in series for it. it is supposedly there to remove noise, but it is 100 ohm and i don't like it! but i would like to know which board has it and how it is.
next, do you use the inside amp or not? because if you do enable and use it, then it is normal to get hissss! get the output sound lower by resistors. specially if you use external amp.
and if possible, move the conversation to discussions, since it is not related to the software anymore. at least i don't think so.
but, if you really want quality, you have to move away from esp8388. one easy and fine and cheap option is UPD6379A
. but then you have to get the original Japanese. its inexpensive with a very good sound. and it uses Resistor string conversion method. and it is 16 bit. it has a S/N ratio 100 dB . that is believable! it is from NEC.
but if you are going to use external DAC, you have to know few things! it is going to be hard. the code has to be specified for that chip, the board has to be separated from IF parts (esp32), and the hi-fi DAC's dont have ADC. meaning no microphone. unless you are going for high end, then they start from at least 80$ DAC's. personally, i love Resistor string conversion. and do know that in that method the resolution is max 16 bit. no more. because it doesn't need any more. and for PCB, it is best to separate the boards, the ground and Vcc from Esp32 (or what ever you use) is going to be extremely noisy.
but if you like to be simple, just use a class D low power amp like PAM8403. in the input put a resistor divider like a 10 to 1 so the hiss and noise will be gone.
hope it helps.
Short update for anyone that might be following this issue. I have completely redesigned my board and ordered it yesterday. The reason being that I found some design choices in my old design that might cause interference and noise.
So just to fully exclude if my issue is caused by this, I did a thorough revision. Once I'm able to test with this board I will report back.
Short update for anyone that might be following this issue. I have completely redesigned my board and ordered it yesterday. The reason being that I found some design choices in my old design that might cause interference and noise.
So just to fully exclude if my issue is caused by this, I did a thorough revision. Once I'm able to test with this board I will report back.
good. i am interested!
Update. Completely revised the board and received it today. Flashed my reduced test case. It somewhat improved but still between 0.2 and 0.3 volume it starts being very glitchy and noisy. My board almost exactly matches the Olimex ESP-ADF when it comes to the DAC side. So I'm very confused. The behaviour did change a bit with my current HW rev.
Its very noisy and glitchy between 0.21 and 0.29. At 0.20 it's fine and at 0.3 it's fine. It also happens from 0.51 to 0.59. Then it's fine again at 0.61, not 0.6. There must be some reason for this, surely.
I'm not fully sure it's hardware related still. Is there some ES8388 fuse/config that I need to set at boot that Olimex has already done in the factory or something?
Below is my current test sketch.
#include "AudioTools.h"
#include "AudioLibs/AudioSourceSD.h"
#include "AudioLibs/I2SCodecStream.h"
#include "AudioCodecs/CodecWAV.h"
// I2C
#define SDAPIN 18 // I2C Data
#define SCLPIN 23 // I2C Clock
#define I2CSPEED 100000 // Clock Rate
#define ES8388ADDR 0x10 // Address of ES8388 I2C port
// I2S, your configuration for the ES8388 board
#define MCLKPIN 0 // Master Clock
#define BCLKPIN 5 // Bit Clock
#define WSPIN 25 // Word select
#define DOPIN 26 // This is connected to DI on ES8388 (MISO)
#define DIPIN 35 // This is connected to DO on ES8388 (MOSI)
// SD
#define SD_CS 21
#define SD_SCK 14
#define SD_MISO 12
#define SD_MOSI 13
#define SD_SS 15
DriverPins my_pins; // board pins
AudioBoard audio_board(AudioDriverES8388, my_pins); // audio board
I2SCodecStream i2s_out_stream(audio_board); // i2s codec
TwoWire myWire = TwoWire(0);
WAVDecoder decoder;
File file;
StreamCopy copier(i2s_out_stream, file); // copies data
float volume = 0.0;
bool testingForwards = true;
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
LOGLEVEL_AUDIODRIVER = AudioDriverWarning;
Serial.println("Setup starting...");
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_SS);
if (!SD.begin(SD_CS)) {
Serial.println("Card Mount Failed");
return;
}
my_pins.addI2C(PinFunction::CODEC, SCLPIN, SDAPIN, ES8388ADDR, I2CSPEED, myWire);
my_pins.addI2S(PinFunction::CODEC, MCLKPIN, BCLKPIN, WSPIN, DOPIN, DIPIN);
auto i2s_config = i2s_out_stream.defaultConfig();
i2s_config.auto_clear = false;
i2s_out_stream.begin(i2s_config);
Serial.println("Playing audio file...");
file = SD.open("/test.wav", FILE_READ);
}
void changeVolume() {
static const unsigned long REFRESH_INTERVAL = 500; // ms
static unsigned long lastRefreshTime = 0;
if(millis() - lastRefreshTime >= REFRESH_INTERVAL) {
lastRefreshTime += REFRESH_INTERVAL;
if(testingForwards) {
volume += 0.01;
} else {
volume -= 0.01;
}
if(volume >= 1 && testingForwards) {
Serial.println("Going back down");
testingForwards = false;
}
if(volume <= 0 && !testingForwards) {
Serial.println("Going back up");
testingForwards = true;
}
i2s_out_stream.setVolume(volume);
Serial.println("Volume: " + String(volume));
}
}
void loop() {
copier.copy();
changeVolume();
}
Can you reproduce this issue if you replace the file with a sine ? Using a file makes it not reproducible for me.
In any case you could instead rely on the VolumeStream to control the volume via software and not via hardware.... You can also try different AI_THINKER_ES8388_VOLUME_HACK settings in the config. E.g AI_THINKER_ES8388_VOLUME_HACK 2 is using a shelfing filter.
@pschatzmann Thanks a bunch! That greatly improved things. I now have the hardware volume set at the max of 1.0 and I'm controlling the volume via pot input via VolumeStream.
The annoying glitches are gone! Makes sense because I can keep the digital volume of the DAC fixed on a non-problematic value.
One final thing I noticed that you might be able to shed some light on.
With the ES8388 internal volume set to 1.0
I hear some background hiss/noise when the VolumeStream volume is in the lower 1/3rd.
As a test I set the HW volume to 0.9 and it greatly improved. Is this just an inherent limitation of the hardware? If I push the internal headphone amp it will introduce some noise?
I would not know: I am using it with the AudioKit whch has an amplifier: 0.9 and 1.0 are just too loud and I am usually using it around 0.4.
Did you check if the option with the filter makes a difference ?
Not sure which options in the filter you mean. But after more testing I’m happy with the results I’m getting. So I consider this resolved. Thanks for the support. Really appreciate it
There were quite some people, which submitted different alternatives how to resolve their volume problems. If you check the AudioDriverConfig you can select different options:
Ah you meant the AI_THINKER_ES8388_VOLUME_HACK? I should test that on different settings, thanks for the tip!
Problem Description
I'm using a board with an ES8388. Mostly works well. Relevant code is below. Randomly I noticed that some volumes introduced some hiss. So I experimented and notices initially volumes above 70 started to slowly add noise. No worries, just stay below 70 I thought.
But randomly lower values do the same. Here are some of my findings testing with intervals of 5.
I'm confused as to why in the lower values suddenly noise is introduced on a spectrum. Is there any firmware reason or configuration error that might cause this?
Really want to resolve this. I'll do whatever is needed on my end to figure this out.
Device Description
ES32 with ES8388 module
Sketch