Skip to content

Commit

Permalink
Fix 8->16 bit output conversion overflow error
Browse files Browse the repository at this point in the history
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 earlephilhower#2
  • Loading branch information
earlephilhower committed May 24, 2018
1 parent b9be5c6 commit 0987b12
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 11 additions & 7 deletions src/AudioOutputI2S.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
7 changes: 5 additions & 2 deletions src/AudioOutputI2SNoDAC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 0987b12

Please sign in to comment.