diff --git a/us144mkii_playback.c b/us144mkii_playback.c index 0234993..af31d86 100644 --- a/us144mkii_playback.c +++ b/us144mkii_playback.c @@ -256,6 +256,22 @@ void playback_urb_complete(struct urb *urb) } urb->transfer_buffer_length = total_bytes; + /* A stuck PLL can produce all-zero-length packets, which makes the + * device underflow and output persistent noise. Force a minimal + * nominal packet if that happens. + */ + if (total_bytes == 0) { + tascam->freq_q16 = div_u64(((u64)tascam->current_rate << 16), 8000); + tascam->phase_accum = 0; + frames = min((u32)(tascam->current_rate / 8000), (u32)MAX_FRAMES_PER_PACKET); + if (frames == 0) + frames = 1; + urb->iso_frame_desc[0].offset = 0; + urb->iso_frame_desc[0].length = frames * PLAYBACK_FRAME_SIZE; + total_bytes = urb->iso_frame_desc[0].length; + urb->transfer_buffer_length = total_bytes; + } + /* Ghost Playback: Send Silence */ if (!atomic_read(&tascam->playback_active)) { if (tascam->running_ghost_playback) { @@ -342,9 +358,22 @@ void feedback_urb_complete(struct urb *urb) u8 *d = urb->transfer_buffer + urb->iso_frame_desc[p].offset; u32 val = (urb->iso_frame_desc[p].actual_length >= 3) ? (d[0] + d[1] + d[2]) : (d[0] * 3); u32 target = (val << 16) / 24; - tascam->freq_q16 = (tascam->freq_q16 * PLL_FILTER_OLD_WEIGHT + - target * PLL_FILTER_NEW_WEIGHT) / PLL_FILTER_DIVISOR; - tascam->feedback_synced = true; + u32 nominal = div_u64(((u64)tascam->current_rate << 16), 8000); + u32 min_freq = nominal - (nominal >> 2); + u32 max_freq = nominal + (nominal >> 2); + + /* Ignore transient bad feedback that would drive the PLL to + * zero or an unrealistic value and cause DAC underflow noise. + */ + if (tascam->current_rate > 0 && target >= min_freq && target <= max_freq) { + tascam->freq_q16 = (tascam->freq_q16 * PLL_FILTER_OLD_WEIGHT + + target * PLL_FILTER_NEW_WEIGHT) / PLL_FILTER_DIVISOR; + if (tascam->freq_q16 < min_freq) + tascam->freq_q16 = min_freq; + else if (tascam->freq_q16 > max_freq) + tascam->freq_q16 = max_freq; + tascam->feedback_synced = true; + } } } }