Added volume control support per channel for stereo samples

TODO: do the same for mono samples (requires data doubling in emulation)
This commit is contained in:
Volker Ruppert 2013-12-15 17:09:18 +00:00
parent 15ab8d32c2
commit acd0fe11b5
7 changed files with 39 additions and 21 deletions

View File

@ -358,7 +358,7 @@ public:
virtual void VOC_init_file(FILE *stream) {}
virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen,
Bit8u header[], Bit32u datalen, Bit8u data[]) {}
virtual void pcm_apply_volume(Bit32u datalen, Bit8u data[], Bit8u volume,
virtual void pcm_apply_volume(Bit32u datalen, Bit8u data[], Bit16u volume,
Bit8u bits, bx_bool stereo, bx_bool issigned) {}
};
#endif

View File

@ -483,6 +483,7 @@ void bx_es1370_c::write(Bit32u address, Bit32u value, unsigned io_len)
Bit8u index, master_vol, dac_vol;
bx_bool set_wave_vol = 0;
unsigned i;
float tmp_vol;
BX_DEBUG(("register write to address 0x%04x - value = 0x%08x", address, value));
@ -563,12 +564,14 @@ void bx_es1370_c::write(Bit32u address, Bit32u value, unsigned io_len)
}
if (set_wave_vol) {
master_vol = ((0x1f - (BX_ES1370_THIS s.codec_reg[0] & 0x1f)) +
(0x1f - (BX_ES1370_THIS s.codec_reg[1] & 0x1f))) / 2;
dac_vol = ((0x1f - (BX_ES1370_THIS s.codec_reg[2] & 0x1f)) +
(0x1f - (BX_ES1370_THIS s.codec_reg[3] & 0x1f))) / 2;
float tmp_vol = (float)master_vol/31.0f*pow(10.0f, (float)(31-dac_vol)*-0.065f);
master_vol = (0x1f - (BX_ES1370_THIS s.codec_reg[0] & 0x1f));
dac_vol = (0x1f - (BX_ES1370_THIS s.codec_reg[2] & 0x1f));
tmp_vol = (float)master_vol/31.0f*pow(10.0f, (float)(31-dac_vol)*-0.065f);
BX_ES1370_THIS s.wave_vol = (Bit8u)(255 * tmp_vol);
master_vol = (0x1f - (BX_ES1370_THIS s.codec_reg[1] & 0x1f));
dac_vol = (0x1f - (BX_ES1370_THIS s.codec_reg[3] & 0x1f));
tmp_vol = (float)master_vol/31.0f*pow(10.0f, (float)(31-dac_vol)*-0.065f);
BX_ES1370_THIS s.wave_vol |= ((Bit8u)(255 * tmp_vol) << 8);
}
}
@ -830,7 +833,7 @@ void bx_es1370_c::sendwavepacket(unsigned channel, Bit32u buflen, Bit8u *buffer)
issigned = (format >> 1) & 1;
// apply wave volume
if (BX_ES1370_THIS s.wave_vol != 255) {
if (BX_ES1370_THIS s.wave_vol != 0xffff) {
DEV_soundmod_pcm_apply_volume(buflen, buffer, BX_ES1370_THIS s.wave_vol,
bits, stereo, issigned);
}

View File

@ -56,7 +56,7 @@ typedef struct {
Bit32u mempage;
Bit8u codec_index;
Bit8u codec_reg[BX_ES1370_CODEC_REGS];
Bit8u wave_vol;
Bit16u wave_vol;
Bit32u sctl;
int dac1_timer_index;

View File

@ -1426,7 +1426,7 @@ void bx_sb16_c::dsp_sendwavepacket()
return;
// apply wave volume
if (BX_SB16_THIS wave_vol != 255) {
if (BX_SB16_THIS wave_vol != 0xffff) {
DEV_soundmod_pcm_apply_volume(DSP.dma.chunkindex, DSP.dma.chunk, BX_SB16_THIS wave_vol,
DSP.dma.bits, DSP.dma.stereo, DSP.dma.format & 1);
}
@ -1628,6 +1628,7 @@ void bx_sb16_c::mixer_writedata(Bit32u value)
int i;
bx_bool set_wave_vol = 0;
Bit8u master_vol, dac_vol;
float tmp_vol;
// do some action depending on what register was written
switch (MIXER.regindex)
@ -1774,10 +1775,14 @@ void bx_sb16_c::mixer_writedata(Bit32u value)
MIXER.reg[MIXER.regindex] = value;
if (set_wave_vol) {
master_vol = ((MIXER.reg[0x30] >> 3) + (MIXER.reg[0x31] >> 3)) / 2;
dac_vol = ((MIXER.reg[0x32] >> 3) + (MIXER.reg[0x33] >> 3)) / 2;
float tmp_vol = (float)master_vol/31.0f*pow(10.0f, (float)(31-dac_vol)*-0.065f);
master_vol = (MIXER.reg[0x30] >> 3);
dac_vol = (MIXER.reg[0x32] >> 3);
tmp_vol = (float)master_vol/31.0f*pow(10.0f, (float)(31-dac_vol)*-0.065f);
BX_SB16_THIS wave_vol = (Bit8u)(255 * tmp_vol);
master_vol = (MIXER.reg[0x31] >> 3);
dac_vol = (MIXER.reg[0x33] >> 3);
tmp_vol = (float)master_vol/31.0f*pow(10.0f, (float)(31-dac_vol)*-0.065f);
BX_SB16_THIS wave_vol |= ((Bit8u)(255 * tmp_vol) << 8);
}
writelog(BOTHLOG(4), "mixer register %02x set to %02x",

View File

@ -200,7 +200,7 @@ private:
int currentirq;
int currentdma8;
int currentdma16;
Bit8u wave_vol;
Bit16u wave_vol;
// the MPU 401 relevant variables
struct bx_sb16_mpu_struct {

View File

@ -267,39 +267,49 @@ void bx_soundmod_ctl_c::VOC_write_block(FILE *stream, int block,
fwrite(data, 1, datalen, stream);
}
void bx_soundmod_ctl_c::pcm_apply_volume(Bit32u datalen, Bit8u data[], Bit8u volume,
void bx_soundmod_ctl_c::pcm_apply_volume(Bit32u datalen, Bit8u data[], Bit16u volume,
Bit8u bits, bx_bool stereo, bx_bool issigned)
{
unsigned i;
Bit8u value8u;
Bit8s value8s;
Bit16u value16u;
Bit16u value16u, tmpvol;
Bit16s value16s;
Bit8u volumes[2], channel = 0;
if (stereo) {
volumes[0] = (Bit8u)(volume & 0xff);
volumes[1] = (Bit8u)(volume >> 8);
} else {
tmpvol = ((volume & 0xff) + (volume >> 8)) / 2;
volumes[0] = volumes[1] = (Bit8u)tmpvol;
}
UNUSED(stereo); // TODO
if (bits == 16) {
for (i = 0; i < datalen; i += 2) {
if (issigned) {
value16s = (Bit16s)(data[i] | (data[i+1] << 8));
value16s = (Bit16s)((Bit32s)value16s * volume / 256);
value16s = (Bit16s)((Bit32s)value16s * volumes[channel] / 256);
data[i] = (Bit8u)(value16s & 0xff);
data[i+1] = (Bit8u)(value16s >> 8);
} else {
value16u = data[i] | (data[i+1] << 8);
value16u = (Bit16u)((Bit32u)value16u * volume / 256);
value16u = (Bit16u)((Bit32u)value16u * volumes[channel] / 256);
data[i] = (Bit8u)(value16u & 0xff);
data[i+1] = (Bit8u)(value16u >> 8);
}
channel ^= 1;
}
} else {
for (i = 0; i < datalen; i++) {
if (issigned) {
value8s = (Bit8s)data[i];
data[i] = (Bit8u)(((Bit16s)value8s * volume) / 256);
data[i] = (Bit8u)(((Bit16s)value8s * volumes[channel]) / 256);
} else {
value8u = data[i];
data[i] = (Bit8u)(((Bit16u)value8u * volume) / 256);
data[i] = (Bit8u)(((Bit16u)value8u * volumes[channel]) / 256);
}
channel ^= 1;
}
}
}

View File

@ -53,7 +53,7 @@ public:
virtual void VOC_init_file(FILE *stream);
virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen,
Bit8u header[], Bit32u datalen, Bit8u data[]);
virtual void pcm_apply_volume(Bit32u datalen, Bit8u data[], Bit8u volume,
virtual void pcm_apply_volume(Bit32u datalen, Bit8u data[], Bit16u volume,
Bit8u bits, bx_bool stereo, bx_bool issigned);
private:
bx_sound_lowlevel_c *soundmod;