Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/audio/phase_vocoder/phase_vocoder_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ static int32_t unwrap_angle_q27(int32_t angle)
void phase_vocoder_reset_for_new_speed(struct phase_vocoder_comp_data *cd)
{
struct phase_vocoder_state *state = &cd->state;
struct phase_vocoder_polar *polar = &state->polar;
struct phase_vocoder_fft *fft = &state->fft;
struct ipolar32 *polar_prev_ch;
int32_t *angle_delta_prev_ch;
int32_t *output_phase_ch;
int ch, i;

state->speed = cd->speed_ctrl;

Expand All @@ -232,6 +238,27 @@ void phase_vocoder_reset_for_new_speed(struct phase_vocoder_comp_data *cd)
*/
state->num_input_fft = 1;
state->num_output_ifft = 0;

/* Re-anchor synthesis phase so the first post-reset IFFT lands
* output_phase back on polar_prev.angle (the steady-state invariant).
* Between speed changes output_phase advances by one analysis-hop
* delta per output IFFT regardless of speed, so at speed != 1 it
* drifts away from the true polar angle; and each reset also adds
* one extra angle_delta_prev on the first no-consume IFFT. If not done,
* both accumulate across with interactive speed changes as a per-bin
* phase offset which smears transients and dulls the sound.
Comment on lines +247 to +249
*/
for (ch = 0; ch < cd->process_channels; ch++) {
polar_prev_ch = polar->polar_prev[ch];
angle_delta_prev_ch = polar->angle_delta_prev[ch];
output_phase_ch = polar->output_phase[ch];
if (!polar_prev_ch || !angle_delta_prev_ch || !output_phase_ch)
continue;

for (i = 0; i < fft->half_fft_size; i++)
output_phase_ch[i] =
unwrap_angle_q27(polar_prev_ch[i].angle - angle_delta_prev_ch[i]);
}
}

static void copy_polar_angles(int32_t *angle_delta_ch, struct ipolar32 *polar_data_ch,
Expand Down
Loading