summaryrefslogtreecommitdiff
path: root/sound/pci/emu10k1/emupcm.c
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>2023-05-18 16:03:39 +0200
committerTakashi Iwai <tiwai@suse.de>2023-05-18 16:41:59 +0200
commitfccd6f31a450d58109f64eda2dd9294e160fb0aa (patch)
tree01e4d4fe2b15057105d964d102ca4e144ad7c8d2 /sound/pci/emu10k1/emupcm.c
parent08e55ae996cbdbd76c3eb12fcad6cc79cba7ddbc (diff)
ALSA: emu10k1: enable bit-exact playback, part 4: send amounts
On Audigy, the send amounts are merely targets, presumably to avoid sound distortion due to sudden changes, which the EMU8K docu explicitly warns about. However, that "soft-start" would prevent bit-for-bit reproduction, so we now force the current send amounts to their final values at PCM playback init. One might want to do that for the MIDI synthesizer as well, though it seems mostly pointless due to the attack phase each note has anyway. Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Link: https://lore.kernel.org/r/20230518140339.3722279-3-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/emu10k1/emupcm.c')
-rw-r--r--sound/pci/emu10k1/emupcm.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 0b23ff8d9c3b..903a68a4d396 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -236,6 +236,18 @@ static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
return CCCA_INTERPROM_2;
}
+static u16 emu10k1_send_target_from_amount(u8 amount)
+{
+ static const u8 shifts[8] = { 4, 4, 5, 6, 7, 8, 9, 10 };
+ static const u16 offsets[8] = { 0, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 };
+ u8 exp;
+
+ if (amount == 0xff)
+ return 0xffff;
+ exp = amount >> 5;
+ return ((amount & 0x1f) << shifts[exp]) + offsets[exp];
+}
+
static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
int master, int extra,
struct snd_emu10k1_voice *evoice,
@@ -301,6 +313,11 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
A_FXRT2, snd_emu10k1_compose_audigy_fxrt2(send_routing),
A_SENDAMOUNTS, snd_emu10k1_compose_audigy_sendamounts(send_amount),
REGLIST_END);
+ for (int i = 0; i < 4; i++) {
+ u32 aml = emu10k1_send_target_from_amount(send_amount[2 * i]);
+ u32 amh = emu10k1_send_target_from_amount(send_amount[2 * i + 1]);
+ snd_emu10k1_ptr_write(emu, A_CSBA + i, voice, (amh << 16) | aml);
+ }
} else {
snd_emu10k1_ptr_write(emu, FXRT, voice,
snd_emu10k1_compose_send_routing(send_routing));