10000 AudiogeneratorMOD: use full 16bit with slightly better accuracy (#479) · murarduino/ESP8266Audio@7a82ba2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7a82ba2

Browse files
authored
AudiogeneratorMOD: use full 16bit with slightly better accuracy (earlephilhower#479)
* Fix a tricky bug that causes delays in playback ... this bug was already present in stellaplayer. Obviously "effectNumber" must be checked, because "effectParameterX" just holds the "upper nibble" of effectParameter * fix for issue earlephilhower#474 - do channel mixing in 32bit, to avoid noise from over/underflow - write audio output as "signed int" (not unsigned) - add int16 saturation check ("clipping") * avoid crash when MOD file has to many CHANNELS - avoid guru meditation, by logging an error and refusing playback in case MOD.numberOfChannels > CHANNELS - correct small typo * internal DAC: avoid possible overflow in conversion int16 -> uint16 * update constants .. we can do 16bit and 8 channels, so let's do it ;-) This adds some debugging code to better understand what is going on inside the mixer code (AudioGeneratorMOD::GetSample). And it also prints out some usefull information from the MOD file. Only active when do_MIXER_DEBUG is defined. * MOD generator: 12 bits of "real" resolution (instead of 10) With this change, we gain 2 additional bits of "real resolution" from the sample interpolation step. Still need some testing to be sure that nothing get "lost" at the same time. * limit to 4 channels on ESP8266 As discussed in earlephilhower#479 (comment)
1 parent c55d240 commit 7a82ba2

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

src/AudioGeneratorMOD.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ bool AudioGeneratorMOD::stop()
6969
free(FatBuffer.channels[i]);
7070
FatBuffer.channels[i] = NULL;
7171
}
72+
73+
if(running && (file != NULL) && (file->isOpen() == true)) {
74+
output->flush(); //flush I2S output buffer, if the player was actually running before.
75+
}
76+
7277
if (file) file->close();
7378
running = false;
7479
output->stop();
@@ -803,14 +808,20 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2])
803808

804809
current = FatBuffer.channels[channel][(samplePointer - FatBuffer.samplePointer[channel]) /*& (FATBUFFERSIZE - 1)*/];
805810
next = FatBuffer.channels[channel][(samplePointer + 1 - FatBuffer.samplePointer[channel]) /*& (FATBUFFERSIZE - 1)*/];
806-
807-
out = current;
811+
812+
// preserve a few more bits from sample interpolation, by upscaling input values.
813+
// This does (slightly) reduce quantization noise in higher frequencies, typically above 8kHz.
814+
// Actually we could could even gain more bits, I was just not sure if more bits would cause overflows in other conputations.
815+
int16_t current16 = (int16_t) current << 2;
816+
int16_t next16 = (int16_t) next << 2;
817+
818+
out = current16;
808819

809820
// Integer linear interpolation - only works correctly in 16bit
810-
out += (next - current) * (Mixer.channelSampleOffset[channel] & ((1 << FIXED_DIVIDER) - 1)) >> FIXED_DIVIDER;
821+
out += (next16 - current16) * (Mixer.channelSampleOffset[channel] & ((1 << FIXED_DIVIDER) - 1)) >> FIXED_DIVIDER;
811822

812-
// Upscale to BITDEPTH
813-
out32 = (int32_t)out << (BITDEPTH - 8);
823+
// Upscale to BITDEPTH, considering the we already gained two bits in the previous step
824+
out32 = (int32_t)out << (BITDEPTH - 10);
814825

815826
// Channel volume
816827
out32 = out32 * Mixer.channelVolume[channel] >> 6;
@@ -819,7 +830,7 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2])
819830
sumL += out32 * min(128 - Mixer.channelPanning[channel], 64) >> 6;
820831
sumR += out32 * min(Mixer.channelPanning[channel], 64) >> 6;
821832
}
822-
833+
823834
// Downscale to BITDEPTH - a bit faster because the compiler can replaced division by constants with proper "right shift" + correct handling of sign bit
824835
if (Mod.numberOfChannels <= 4) {
825836
// up to 4 channels

src/AudioGeneratorMOD.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class AudioGeneratorMOD : public AudioGenerator
5353

5454
protected:
5555
int mixerTick;
56-
enum {BITDEPTH = 15};
56+
enum {BITDEPTH = 16};
5757
int sampleRate;
5858
int fatBufferSize; //(6*1024) // File system buffers per-CHANNEL (i.e. total mem required is 4 * FATBUFFERSIZE)
5959
enum {FIXED_DIVIDER = 10}; // Fixed-point mantissa used for integer arithmetic
@@ -64,8 +64,14 @@ class AudioGeneratorMOD : public AudioGenerator
6464
// Hz = 7159091 / (amigaPeriod * 2) for NTSC
6565
int AMIGA;
6666
void UpdateAmiga() { AMIGA = ((usePAL?7159091:7093789) / 2 / sampleRate << FIXED_DIVIDER); }
67-
67+
68+
#ifdef ESP8266 // Not sure if C3/C2 have RAM constraints, maybe add them here?
69+
// support max 4 channels
6870
enum {ROWS = 64, SAMPLES = 31, CHANNELS = 4, NONOTE = 0xFFFF, NONOTE8 = 0xff };
71+
#else
72+
// support max 8 channels
73+
enum {ROWS = 64, SAMPLES = 31, CHANNELS = 8, NONOTE = 0xFFFF, NONOTE8 = 0xff };
74+
#endif
6975

7076
typedef struct Sample {
7177
uint16_t length;

0 commit comments

Comments
 (0)
0