Reply 2200 of 2410, by hail-to-the-ryzen
I think this would better meet the implementation recommended by jmarsh and krcroft. Tested the values for unsigned 8-bit mono sound only. This saves the xor operation, but one report suggests that the xor may use less than a cpu cycle. I think that the data value should have a casting operator, but the data type is also somewhat constricted by the condition "sizeof(Type)==1" and "signeddata".
It is best to use the previous version for any testing because this version would likely require additional code to verify the variable casting, otherwise one of the many compilers will probably report a warning. This is posted for reference for a slightly different way to run the conversion from 8-bit to 16-bit values and avoid a conversion bias.
The bias occurs with the 8-bit sample shifted by 8 bits to the left. For an signed 8-bit sample, it would range from -128 to 127. Where using the bit shift method to convert it to signed 16-bit, it becomes an unscaled range from -32768 to 32512. This is shown here:
https://github.com/dosbox-staging/dosbox-staging/pull/1005
The methods of scaling correct for that unscaled range so that the values will range from -32768 to 32767. This allows for a symmetric set of values and avoid some bias toward the negative values, as jmarsh discovered. Otherwise, there are 32768 negative values and 32512 positive values. I believe this can also lead to loss of color values where the conversion is for a color image with the same bit widths.
diff -rupN dosbox-original/src/hardware/mixer.cpp dosbox/src/hardware/mixer.cpp
--- dosbox-original/src/hardware/mixer.cpp
+++ dosbox/src/hardware/mixer.cpp
@@ -54,6 +54,8 @@
#define MIXER_SSIZE 4
#define MIXER_VOLSHIFT 13
+static Bit16s Sample_16_Table[256];
+
static INLINE Bit16s MIXER_CLIP(Bits SAMP) {
if (SAMP < MAX_AUDIO) {
if (SAMP > MIN_AUDIO)
@@ -379,12 +381,12 @@ inline void MixerChannel::loadCurrentSam
last[1] = current[1];
if (sizeof(Type) == 1) {
- const Bit8u xr = signeddata ? 0x00 : 0x80;
+ Bit16s *tablePtr = signeddata ? (Sample_16_Table + 128) : Sample_16_Table;
len--;
- current[0] = ((Bit8s)((*data++) ^ xr)) << 8;
+ current[0] = *(tablePtr + (*data++));
if (stereo)
- current[1] = ((Bit8s)((*data++) ^ xr)) << 8;
+ current[1] = *(tablePtr + (*data++));
else
current[1] = current[0];
}
@@ -888,6 +890,15 @@ void MIXER_Controls_Init() {
MAPPER_AddHandler(MAPPER_RecVolumeDown,MK_kpminus,MMOD1|MMOD2,"recvoldown","RecVolDn");
}
+void Mixer_SetSample16Table(void) {
+ for (Bitu i=0;i<256;i++) {
+ if (i > 128)
+ Sample_16_Table[i]=((i-128) << 8) | (2 * (i-128) + 1);
+ else
+ Sample_16_Table[i]=(i-128) << 8;
+ }
+}
+
void MIXER_Init(Section* sec) {
sec->AddDestroyFunction(&MIXER_Stop);
@@ -913,6 +924,8 @@ void MIXER_Init(Section* sec) {
mixer.recordvol[0]=1.0f;
mixer.recordvol[1]=1.0f;
+ Mixer_SetSample16Table();
+
/* Start the Mixer using SDL Sound at 22 khz */
SDL_AudioSpec spec;
SDL_AudioSpec obtained;