Commit fccd6f31 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen Committed by Takashi Iwai
Browse files

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: default avatarOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230518140339.3722279-3-oswald.buddenhagen@gmx.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 08e55ae9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -709,6 +709,8 @@ SUB_REG(PEFE, FILTERAMOUNT, 0x000000ff) /* Filter envlope amount */
#define ADCBS_BUFSIZE_57344	0x0000001e
#define ADCBS_BUFSIZE_65536	0x0000001f

// On Audigy, the FX send amounts are not applied instantly, but determine
// targets towards which the following registers swerve gradually.
#define A_CSBA			0x4c		/* FX send B & A current amounts			*/
#define A_CSDC			0x4d		/* FX send D & C current amounts			*/
#define A_CSFE			0x4e		/* FX send F & E current amounts			*/
+17 −0
Original line number Diff line number Diff line
@@ -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));