Commit df335e9a authored by Oswald Buddenhagen's avatar Oswald Buddenhagen Committed by Takashi Iwai

ALSA: emu10k1: fix synthesizer sample playback position and caching

Compensate for the cache delay, and actually populate the cache.
Without these, the playback would start with garbage (which would be
(mostly?) masqueraded by the attack phase).

Unlike for the PCM voices, this doesn't try to compensate for the
interpolator read-ahead, because it's pointless to be super-exact here.

Note that this code is probably still broken for particularly short
samples, because we ignore the loop-related parts of CCR. But I'm not
going to reverse-engineer that now ...
Signed-off-by: default avatarOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230518140339.3722308-1-oswald.buddenhagen@gmx.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 816967d5
...@@ -253,7 +253,7 @@ lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw, ...@@ -253,7 +253,7 @@ lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
/* check if sample is finished playing (non-looping only) */ /* check if sample is finished playing (non-looping only) */
if (bp != best + V_OFF && bp != best + V_FREE && if (bp != best + V_OFF && bp != best + V_FREE &&
(vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) { (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch); val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch) - 64;
if (val >= vp->reg.loopstart) if (val >= vp->reg.loopstart)
bp = best + V_OFF; bp = best + V_OFF;
} }
...@@ -360,7 +360,7 @@ start_voice(struct snd_emux_voice *vp) ...@@ -360,7 +360,7 @@ start_voice(struct snd_emux_voice *vp)
map = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); map = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
addr = vp->reg.start; addr = vp->reg.start + 64;
temp = vp->reg.parm.filterQ; temp = vp->reg.parm.filterQ;
ccca = (temp << 28) | addr; ccca = (temp << 28) | addr;
if (vp->apitch < 0xe400) if (vp->apitch < 0xe400)
...@@ -428,40 +428,14 @@ start_voice(struct snd_emux_voice *vp) ...@@ -428,40 +428,14 @@ start_voice(struct snd_emux_voice *vp)
/* Q & current address (Q 4bit value, MSB) */ /* Q & current address (Q 4bit value, MSB) */
CCCA, ccca, CCCA, ccca,
/* cache */
CCR, REG_VAL_PUT(CCR_CACHEINVALIDSIZE, 64),
/* reset volume */ /* reset volume */
VTFT, vtarget | vp->ftarget, VTFT, vtarget | vp->ftarget,
CVCF, vtarget | CVCF_CURRENTFILTER_MASK, CVCF, vtarget | CVCF_CURRENTFILTER_MASK,
REGLIST_END); REGLIST_END);
#if 0
/* cache */
{
unsigned int val, sample;
val = 32;
if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS)
sample = 0x80808080;
else {
sample = 0;
val *= 2;
}
/* cache */
snd_emu10k1_ptr_write(hw, CCR, ch, 0x1c << 16);
snd_emu10k1_ptr_write(hw, CDE, ch, sample);
snd_emu10k1_ptr_write(hw, CDF, ch, sample);
/* invalidate maps */
temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
/* fill cache */
val -= 4;
val <<= 25;
val |= 0x1c << 16;
snd_emu10k1_ptr_write(hw, CCR, ch, val);
}
#endif
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment