Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

How to use converter to play 8-bit wav files using AudioPlayer? #2153

Answered by pschatzmann
dingetje asked this question in Q&A
Discussion options

Problem Description

I don't understand how to use the format converter to play 8-bit wav files over I2C.
I've found an old closed issue where converter streams were mentioned, and I looked at an example. But failed to understand how to inject such a converter in the AudioPlayer (I'm using play WAV file from SD_MMC card).

Device Description

ESP32S3 with ES8311 DAC

Sketch

AudioBoard board{AudioDriverES8311, NoPins};
AudioBoardStream out(board);
AudioInfo info(16000,1,16);
AudioSourceIdxSDMMC source("/Audio", "wav", true);
MultiDecoder multi;
WAVDecoder wav;
AudioPlayer player(source, out, multi);
bool play_file(char *filename, float volume)
{
 if (!SD_MMC.exists(filename)) {
 Serial.println("play_file: '" + String(filename) + "' does not exist");
 return false;
 }
 player.end(); // stop previous if any
 player.setAutoNext(false);
 player.setPath(filename);
 return player.begin();
}
void setup()
{
 Serial.begin(115200); 
 // wait for Serial to be ready
 while (! Serial); 
 Serial.println();
 DriverPins pins; // no pin definition
 pins.addI2C(PinFunction::CODEC, Wire, true);
 pins.addPin(PinFunction::PA, PAPIN, PinLogic::Output); // Power Amplifier
 PinsI2S PinsI2S(PinFunction::CODEC, MCLKPIN, BCLKPIN, WSPIN, DOPIN, DIPIN);
 pins.addSPI(PinFunction::SD, SDMMC_CLK, SDMMC_CMD, SDMMC_DATA, -1, SPI);
 pins.addI2S(PinsI2S);
 board.setPins(pins);
 // start I2S & codec
 Serial.println("starting I2S...");
 auto config = out.defaultConfig();
 config.copyFrom(info);
 // define I2S pins if you dont want to use the default pins
 config.pin_bck = BCLKPIN;
 config.pin_ws = WSPIN;
 config.pin_data = DOPIN;
 config.pin_mck = MCLKPIN;
 config.rx_tx_mode = TX_MODE;
 config.input_device = ADC_INPUT_NONE; // no input
 config.output_device = DAC_OUTPUT_ALL; // use both channels of the internal dac
 config.sd_active = true;
 config.use_apll = true; // use APLL for better clock
 config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; // two channel
 if (!out.begin(config)) {
 Serial.println("I2S failed to start!");
 return false;
 }
 
 // additinal settings
 out.setVolume(0.8);
 Serial.println("I2S started...");
 play_file("/Audio/danger.wav",1.0); // play test sound
}
void loop()
{
 player.copy();
}

Other Steps to Reproduce

My WAV files are 8K, mono, 8-bit and sound like noise when played.

Debug logging:

starting I2S...
[D] I2SCodecStream.h : 79 - virtual bool audio_tools::I2SCodecStream::begin(audio_tools::I2SCodecConfig)
[D] I2SCodecStream.h : 216 - bool audio_tools::I2SCodecStream::begin1()
[D] I2SCodecStream.h : 253 - void audio_tools::I2SCodecStream::setupI2SPins()
[D] I2SCodecStream.h : 278 - audio_driver_local::Optional<audio_driver::PinsI2S> audio_tools::I2SCodecStream::getI2SPins()
[D] I2SCodecStream.h : 285 - bool audio_tools::I2SCodecStream::beginCodec(audio_tools::I2SCodecConfig)
[D] I2SCodecStream.h : 301 - input: 0
[D] I2SCodecStream.h : 302 - output: 3
[D] I2SCodecStream.h : 318 - BIT_LENGTH_16BITS
[D] I2SCodecStream.h : 340 - RATE_16K
[D] I2SCodecStream.h : 367 - I2S_NORMAL
Debug: AudioBoard::begin
Info: AudioDriver::begin
Info: setupI2CAddress: 0x18
Info: ==> Updating address: 0x18
Info: sd_active: 1
Debug: DriverPins::begin
Debug: DriverPins::setupPinMode
Debug: pinMode for 46
Debug: PinsSPI::begin for 7
Info: setting up SPI miso:1,mosi:3, clk:2, cs:-1
Debug: PinsI2C::begin for function 8 on port 0
Info: i2c_bus_create
Info: setting up I2C w/o pins
[188689][W][Wire.cpp:301] begin(): Bus already started in Master Mode.
Info: AudioDriver::setConfig
Info: MCLK_SOURCE: 0
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x2
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x3
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x16
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x4
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x5
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xB
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xC
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x10
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x11
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x0
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x0
Info: ES8311 in Slave mode
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x0
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1
Info: ES8311 clock source: MCLK
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x2
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x2
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x5
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x5
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x3
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x3
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x4
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x4
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x7
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x7
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x8
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x8
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x6
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x6
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x6
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x6
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x13
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1B
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x1C
Debug: mode->CODEC_MODE_DECODE
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x9
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xA
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x9
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xA
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x17
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xE
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x12
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x14
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x14
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x14
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xD
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x15
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x37
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x45
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x9
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xA
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x9
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xA
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x9
Debug: i2c_bus_read_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xA
Debug: ES8311 in I2S Format
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x9
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0xA
Info: setPAPower pin 46 -> 1
Debug: es8311_codec_set_voice_volume:70
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x32
Debug: setVolume: 70
[D] I2SStream.h : 72 - bool audio_tools::I2SStream::begin(audio_tools::I2SConfig)
[D] BaseStream.h : 131 - virtual void audio_tools::AudioStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 125 - in: sample_rate: 16000 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 125 - out: sample_rate: 16000 / channels: 1 / bits_per_sample: 16
[D] I2SESP32.h : 63 - bool audio_tools::I2SDriverESP32::begin(audio_tools::I2SConfigESP32)
[D] I2SESP32.h : 182 - bool audio_tools::I2SDriverESP32::begin(audio_tools::I2SConfigESP32, int, int)
[I] AudioTypes.h : 125 - sample_rate: 16000 / channels: 1 / bits_per_sample: 16
[I] I2SConfigESP32.h : 80 - rx/tx mode: TX_MODE
[I] I2SConfigESP32.h : 81 - port_no: 0
[I] I2SConfigESP32.h : 82 - is_master: Master
[I] I2SConfigESP32.h : 83 - sample rate: 16000
[I] I2SConfigESP32.h : 84 - bits per sample: 16
[I] I2SConfigESP32.h : 85 - number of channels: 1
[I] I2SConfigESP32.h : 86 - signal_type: Digital
[I] I2SConfigESP32.h : 88 - i2s_format: I2S_STD_FORMAT
[I] I2SConfigESP32.h : 90 - auto_clear: true
[I] I2SConfigESP32.h : 92 - use_apll: true
[I] I2SConfigESP32.h : 97 - buffer_count:6
[I] I2SConfigESP32.h : 98 - buffer_size:512
[I] I2SConfigESP32.h : 101 - pin_mck: 42
[I] I2SConfigESP32.h : 103 - pin_bck: 9
[I] I2SConfigESP32.h : 105 - pin_ws: 45
[I] I2SConfigESP32.h : 107 - pin_data: 8
[D] I2SESP32.h : 214 - i2s_driver_install
[D] I2SESP32.h : 230 - i2s_set_pin
[D] I2SESP32.h : 241 - i2s_zero_dma_buffer
[D] I2SESP32.h : 245 - begin - started
Debug: setVolume: 100
Debug: es8311_codec_set_voice_volume:100
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x32
Debug: setVolume: 80
Debug: es8311_codec_set_voice_volume:80
Debug: i2c_bus_write_bytes: addr=0x18 reglen=1 datalen=1 - reg=0x32
I2S started...
[D] Allocator.h : 76 - Allocated 4
[D] Allocator.h : 76 - Allocated 12
[D] AudioPlayer.h : 195 - void audio_tools::AudioPlayer::end()
[I] MetaDataID3.h : 592 - virtual void audio_tools::MetaDataID3::end()
[I] AudioPlayer.h : 201 - reset codec
[D] AudioPlayer.h : 303 - bool audio_tools::AudioPlayer::setPath(const char*)
[I] AudioPlayer.h : 559 - void audio_tools::AudioPlayer::writeEnd()
[D] StreamCopy.h : 108 - copy 1024 bytes
[I] AudioSourceIdxSDMMC.h : 79 - -> selectStream: /Audio/danger.wav
[D] AudioPlayer.h : 195 - void audio_tools::AudioPlayer::end()
[I] MetaDataID3.h : 592 - virtual void audio_tools::MetaDataID3::end()
[I] AudioPlayer.h : 201 - reset codec
[D] AudioEncoded.h : 150 - virtual bool audio_tools::EncodedAudioOutput::begin()
[D] AudioEncoded.h : 152 - virtual bool audio_tools::EncodedAudioOutput::begin()
[D] Allocator.h : 76 - Allocated 8
[D] AudioCodecsBase.h : 29 - virtual void audio_tools::AudioDecoder::setAudioInfo(audio_tools::AudioInfo)
[D] AudioPlayer.h : 325 - open selected stream
[I] MetaDataID3.h : 586 - virtual void audio_tools::MetaDataID3::begin()
[D] Allocator.h : 76 - Allocated 256
[D] StreamCopy.h : 51 - void audio_tools::StreamCopyT<T>::begin() [with T = unsigned char]
[I] StreamCopy.h : 57 - buffer_size=1024
[D] AudioPlayer.h : 150 - bool audio_tools::AudioPlayer::begin(int, bool)
[I] AudioPlayer.h : 363 - setVolume(1.000000)
[D] Allocator.h : 76 - Allocated 8
[D] Allocator.h : 76 - Allocated 8
[I] VolumeStream.h : 199 - setVolume: 1.000000 at 0
[I] VolumeStream.h : 199 - setVolume: 1.000000 at 1
[D] BaseStream.h : 131 - virtual void audio_tools::AudioStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 125 - in: sample_rate: 16000 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 125 - out: sample_rate: 16000 / channels: 1 / bits_per_sample: 16
[D] Allocator.h : 76 - Allocated 2
[D] Allocator.h : 76 - Allocated 4
[D] Allocator.h : 76 - Allocated 4
[D] AudioEncoded.h : 150 - virtual bool audio_tools::EncodedAudioOutput::begin()
[D] AudioSourceIdxSDMMC.h : 43 - virtual void audio_tools::AudioSourceIdxSDMMC::begin()
[D] SDIndex.h : 25 - void audio_tools::SDIndex<SDT, FileT>::begin(const char*, const char*, const char*, bool) [with SDT = fs::SDMMCFS; FileT = fs::File]
[I] SDIndex.h : 32 - Index file size: 296
[I] MetaDataID3.h : 586 - virtual void audio_tools::MetaDataID3::begin()
[D] VolumeStream.h : 101 - bool audio_tools::VolumeStream::begin(audio_tools::VolumeStreamConfig)
[I] AudioSourceIdxSDMMC.h : 66 - selectStream: 0
[D] SDIndex.h : 84 - 0 -> /Audio/traffic.wav
[I] AudioSourceIdxSDMMC.h : 70 - Using file /Audio/traffic.wav
[D] AudioPlayer.h : 195 - void audio_tools::AudioPlayer::end()
[I] AudioEncoded.h : 178 - virtual void audio_tools::EncodedAudioOutput::end()
[I] MetaDataID3.h : 592 - virtual void audio_tools::MetaDataID3::end()
[I] AudioPlayer.h : 201 - reset codec
[D] AudioEncoded.h : 150 - virtual bool audio_tools::EncodedAudioOutput::begin()
[D] AudioEncoded.h : 152 - virtual bool audio_tools::EncodedAudioOutput::begin()
[D] AudioCodecsBase.h : 29 - virtual void audio_tools::AudioDecoder::setAudioInfo(audio_tools::AudioInfo)
[D] AudioPlayer.h : 325 - open selected stream
[I] MetaDataID3.h : 586 - virtual void audio_tools::MetaDataID3::begin()
[D] StreamCopy.h : 51 - void audio_tools::StreamCopyT<T>::begin() [with T = unsigned char]
[I] StreamCopy.h : 57 - buffer_size=1024
[D] StreamCopy.h : 51 - void audio_tools::StreamCopyT<T>::begin() [with T = unsigned char]
[I] StreamCopy.h : 57 - buffer_size=1024
[D] AudioPlayer.h : 405 - size_t audio_tools::AudioPlayer::copy(size_t)
[D] StreamCopy.h : 108 - copy 1024 bytes
[D] StreamCopy.h : 256 - available: 3554
[D] StreamCopy.h : 395 - write: 1024
[D] AudioEncoded.h : 191 - EncodedAudioOutput::write: 1024
[I] MultiDecoder.h : 253 - mime from mime_detector: audio/vnd.wave
[I] MultiDecoder.h : 199 - Using decoder for audio/vnd.wave (audio/vnd.wave)
[D] CodecWAV.h : 297 - virtual bool audio_tools::WAVDecoder::begin()
[I] MultiDecoder.h : 208 - Decoder audio/vnd.wave started
[D] CodecWAV.h : 319 - virtual size_t audio_tools::WAVDecoder::write(const uint8_t*, size_t)
[D] Buffers.h : 67 - writeArray 1024 -> 200
[I] CodecWAV.h : 57 - WAVHeader::begin: 200
[I] CodecWAV.h : 213 - WAVHeader sound_pos: 44
[I] CodecWAV.h : 214 - WAVHeader channels: 1
[I] CodecWAV.h : 215 - WAVHeader bits_per_sample: 8
[I] CodecWAV.h : 216 - WAVHeader sample_rate: 8000
[I] CodecWAV.h : 217 - WAVHeader format: 1
[I] CodecWAV.h : 422 - WAV sample_rate: 8000
[I] CodecWAV.h : 423 - WAV data_length: 3470
[I] CodecWAV.h : 424 - WAV is_streamed: 0
[I] CodecWAV.h : 426 - WAV is_valid: false
[D] AudioCodecsBase.h : 29 - virtual void audio_tools::AudioDecoder::setAudioInfo(audio_tools::AudioInfo)
[D] AudioPlayer.h : 230 - virtual void audio_tools::AudioPlayer::setAudioInfo(audio_tools::AudioInfo)
[I] AudioPlayer.h : 231 - sample_rate: 8000
[I] AudioPlayer.h : 232 - bits_per_sample: 8
[I] AudioPlayer.h : 233 - channels: 1

What is your development environment (incl. core version info)

No response

I have checked existing issues, discussions and online documentation

  • I confirm I have checked existing issues, discussions and online documentation
You must be logged in to vote

I guess there are quite a few possibilities that might work: e.g.
a) use a CodecChain consisting of a WAVDecoder and a DecoderL8;
b) Instead of sending the output to I2SStream send it to a NumberFormatConverterStreamT<uint8_t, int16_t> nfc(out);

ps: this is not a bug in my code, so it shuld be a discussion and not an issue!

Replies: 2 comments 5 replies

Comment options

I guess there are quite a few possibilities that might work: e.g.
a) use a CodecChain consisting of a WAVDecoder and a DecoderL8;
b) Instead of sending the output to I2SStream send it to a NumberFormatConverterStreamT<uint8_t, int16_t> nfc(out);

ps: this is not a bug in my code, so it shuld be a discussion and not an issue!

You must be logged in to vote
5 replies
Comment options

Agreed, my bad for not opening a discussion.

The I2SStream is currently embedded in AudioPlayer is it not? How would you "inject" such a CodecChain or that NumberFormatConverterStream?

I guess I need a code example.

Comment options

I've tried switching to an MP3 file instead, and this looks OK in the logging, but sounds like noise on the output.
The file plays OK on my PC. I must admit there's a lot going on in the loop, not just the audio handling.
I haven't tried with a basic AudioPlayer only sketch.

MobaXterm_COM16Waveshare1.75_20250904_193500.txt

Comment options

No, there is no relationship between the player and I2S: you define the output object to the audio player and this can be anything!
In my proposal this would be the nfc!

AudioBoard board{AudioDriverES8311, NoPins};
AudioBoardStream out(board);
NumberFormatConverterStreamT<uint8_t, int16_t> nfc(out);
AudioPlayer player(source, nfc, multi);
Comment options

The MP3 player worked OK, when I removed the debug logger, makes sense, all that Serial logging was eating too many CPU cycles.

Comment options

FYI: I gave up on the number converter and converted my audio files to MP3 instead. Thanks for your support!

Answer selected by pschatzmann
Comment options

To make things a bit simpler, I extended the WAVDecoder to automatically convert 8 bit data to 16 bits and tested the functioniality today!

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
Converted from issue

This discussion was converted from issue #2152 on September 04, 2025 16:41.

AltStyle によって変換されたページ (->オリジナル) /