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_init_file(FILE *stream) {}
virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen, virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen,
Bit8u header[], Bit32u datalen, Bit8u data[]) {} 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) {} Bit8u bits, bx_bool stereo, bx_bool issigned) {}
}; };
#endif #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; Bit8u index, master_vol, dac_vol;
bx_bool set_wave_vol = 0; bx_bool set_wave_vol = 0;
unsigned i; unsigned i;
float tmp_vol;
BX_DEBUG(("register write to address 0x%04x - value = 0x%08x", address, value)); 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) { if (set_wave_vol) {
master_vol = ((0x1f - (BX_ES1370_THIS s.codec_reg[0] & 0x1f)) + 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));
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);
(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);
BX_ES1370_THIS s.wave_vol = (Bit8u)(255 * tmp_vol); 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; issigned = (format >> 1) & 1;
// apply wave volume // 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, DEV_soundmod_pcm_apply_volume(buflen, buffer, BX_ES1370_THIS s.wave_vol,
bits, stereo, issigned); bits, stereo, issigned);
} }

View File

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

View File

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

View File

@ -200,7 +200,7 @@ private:
int currentirq; int currentirq;
int currentdma8; int currentdma8;
int currentdma16; int currentdma16;
Bit8u wave_vol; Bit16u wave_vol;
// the MPU 401 relevant variables // the MPU 401 relevant variables
struct bx_sb16_mpu_struct { 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); 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) Bit8u bits, bx_bool stereo, bx_bool issigned)
{ {
unsigned i; unsigned i;
Bit8u value8u; Bit8u value8u;
Bit8s value8s; Bit8s value8s;
Bit16u value16u; Bit16u value16u, tmpvol;
Bit16s value16s; 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) { if (bits == 16) {
for (i = 0; i < datalen; i += 2) { for (i = 0; i < datalen; i += 2) {
if (issigned) { if (issigned) {
value16s = (Bit16s)(data[i] | (data[i+1] << 8)); 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] = (Bit8u)(value16s & 0xff);
data[i+1] = (Bit8u)(value16s >> 8); data[i+1] = (Bit8u)(value16s >> 8);
} else { } else {
value16u = data[i] | (data[i+1] << 8); 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] = (Bit8u)(value16u & 0xff);
data[i+1] = (Bit8u)(value16u >> 8); data[i+1] = (Bit8u)(value16u >> 8);
} }
channel ^= 1;
} }
} else { } else {
for (i = 0; i < datalen; i++) { for (i = 0; i < datalen; i++) {
if (issigned) { if (issigned) {
value8s = (Bit8s)data[i]; value8s = (Bit8s)data[i];
data[i] = (Bit8u)(((Bit16s)value8s * volume) / 256); data[i] = (Bit8u)(((Bit16s)value8s * volumes[channel]) / 256);
} else { } else {
value8u = data[i]; 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_init_file(FILE *stream);
virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen, virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen,
Bit8u header[], Bit32u datalen, Bit8u data[]); 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); Bit8u bits, bx_bool stereo, bx_bool issigned);
private: private:
bx_sound_lowlevel_c *soundmod; bx_sound_lowlevel_c *soundmod;