From 0987b12e585c7f8a28d01cf5a751731101fd9442 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 23 May 2018 22:35:56 -0700 Subject: [PATCH] Fix 8->16 bit output conversion overflow error The I2S outputs were converting samples in the buffer passed in from u8->s16 on every call. When the I2S was full, however, the sample would not get pushed and the output function would be called at a later time with the same buffer...which was already at 16 bits. It'd be converted again and turned into a high frequency noise on the output. Now only modify a copy of the input sample in I2S and I2SNoDAC. Fixes the conversion problem competely. Fixes #2 --- README.md | 2 +- src/AudioOutputI2S.cpp | 18 +++++++++++------- src/AudioOutputI2SNoDAC.cpp | 7 +++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 062e19ca..ee8f96b4 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ AudioFileSourceHTTPStream: Simple implementation of a streaming HTTP reader for ## AudioFileSourceBuffer - Double buffering, useful for HTTP streams AudioFileSourceBuffer is an input source that simpy adds an additional RAM buffer of the output of any other AudioFileSource. This is particularly useful for web streaming where you need to have 1-2 packets in memory to ensure hiccup-free playback. -Simply create your standard input file source, create the buffer with the original source as its input, and pass this buffer object to the generator. +Create your standard input file source, create the buffer with the original source as its input, and pass this buffer object to the generator. ```` ... AudioGeneratorMP3 *mp3; diff --git a/src/AudioOutputI2S.cpp b/src/AudioOutputI2S.cpp index e2ed6e51..93bfe2e4 100644 --- a/src/AudioOutputI2S.cpp +++ b/src/AudioOutputI2S.cpp @@ -168,25 +168,29 @@ bool AudioOutputI2S::begin() bool AudioOutputI2S::ConsumeSample(int16_t sample[2]) { - MakeSampleStereo16( sample ); + int16_t ms[2]; + + ms[0] = sample[0]; + ms[1] = sample[1]; + MakeSampleStereo16( ms ); if (this->mono) { // Average the two samples and overwrite - uint32_t ttl = sample[LEFTCHANNEL] + sample[RIGHTCHANNEL]; - sample[LEFTCHANNEL] = sample[RIGHTCHANNEL] = (ttl>>1) & 0xffff; + int32_t ttl = ms[LEFTCHANNEL] + ms[RIGHTCHANNEL]; + ms[LEFTCHANNEL] = ms[RIGHTCHANNEL] = (ttl>>1) & 0xffff; } #ifdef ESP32 uint32_t s32; if (output_mode == INTERNAL_DAC) { - int16_t l = Amplify(sample[LEFTCHANNEL]) + 0x8000; - int16_t r = Amplify(sample[RIGHTCHANNEL]) + 0x8000; + int16_t l = Amplify(ms[LEFTCHANNEL]) + 0x8000; + int16_t r = Amplify(ms[RIGHTCHANNEL]) + 0x8000; s32 = (r<<16) | (l&0xffff); } else { - s32 = ((Amplify(sample[RIGHTCHANNEL]))<<16) | (Amplify(sample[LEFTCHANNEL]) & 0xffff); + s32 = ((Amplify(ms[RIGHTCHANNEL]))<<16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); } return i2s_push_sample((i2s_port_t)portNo, (const char *)&s32, 0); #else - uint32_t s32 = ((Amplify(sample[RIGHTCHANNEL]))<<16) | (Amplify(sample[LEFTCHANNEL]) & 0xffff); + uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL]))<<16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); return i2s_write_sample_nb(s32); // If we can't store it, return false. OTW true #endif } diff --git a/src/AudioOutputI2SNoDAC.cpp b/src/AudioOutputI2SNoDAC.cpp index 8503b558..8fd85fa4 100644 --- a/src/AudioOutputI2SNoDAC.cpp +++ b/src/AudioOutputI2SNoDAC.cpp @@ -80,11 +80,14 @@ void AudioOutputI2SNoDAC::DeltaSigma(int16_t sample[2], uint32_t dsBuff[8]) bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2]) { - MakeSampleStereo16( sample ); + int16_t ms[2]; + ms[0] = sample[0]; + ms[1] = sample[1]; + MakeSampleStereo16( ms ); // Make delta-sigma filled buffer uint32_t dsBuff[8]; - DeltaSigma(sample, dsBuff); + DeltaSigma(ms, dsBuff); // Either send complete pulse stream or nothing #ifdef ESP32