我正在尝试使用相位声码器算法编写一个执行音高变换的Pd外部电路。这是我第一次写外部,我不是一个C程序员,所以我希望你们可以帮助我解决这个问题。我只是附上了执行方法。
当我改变要转置的半音的数量时,我得到了一个奇怪的行为。它确实有音高变换,但有许多奇怪的伪像,而不是我设定的数量。我认为代码是对的,但显然不是;任何人都可以给我一些关于问题可能是什么的提示吗?我知道这是一段很长的代码而且我的问题很模糊,但我发现使用Pd进行调试是不可能的,而且我已经没有想法来测试代码了。
int i, j, n, frame_size, frame_size_half, overlap_in, overlap_chunk, hop_in, hop_out;
int semitones;
t_float amp_scalar, alpha;
t_pitchShifter_tilde *x = (t_pitchShifter_tilde *)(w[1]);
t_sample *in = (t_float *)(w[2]);
t_sample *out = (t_float *)(w[3]);
n = w[4]; //Tamaño del buffer de entrada
semitones = x->semitones;
frame_size = x->frame_size;
frame_size_half = x->frame_size_half;
overlap_in = x->overlap_in;
overlap_chunk = x->hop_in;
hop_in = x->hop_in;
alpha = pow(2.0,semitones/12.0);//x->alpha;
hop_out = round(alpha*hop_in);//x->hop_out;
amp_scalar = x->amp_scalar;
// shift previous contents back
for(i=0; i<(frame_size-n); i++)
x->input_buf[i] = x->input_buf[n+i];
// buffer most recent block
for(i=0; i<n; i++)
x->input_buf[frame_size-n+i] = in[i]; // C
if(x->dsp_tick>=x->buffer_limit)
{
x->dsp_tick = 0;
// ANALYSIS
// window the signal
for(i=0; i<frame_size; i++){
x->input_buf_windowed[i] = x->input_buf[i] * x->hann[i];
}
// take FT of window
mayer_realfft(frame_size, x->input_buf_windowed);
//Debug:
if(debug){
for(i=0; i<frame_size; i++){
post("fft output %i: %f", i, x->input_buf_windowed[i]);
}
}
// unpack mayer_realfft results into R&I arrays
for(i=0; i<=frame_size_half; i++)
{
x->signal_R[i] = x->input_buf_windowed[i];
if(fabs(x->signal_R[i]) < 0.0001)
x->signal_R[i] = 0.0;
}
x->signal_I[0]=0; // DC
for(i=(frame_size-1), j=1; i>frame_size_half; i--, j++)
{
x->signal_I[j] = x->input_buf_windowed[i];
if(fabs(x->signal_I[j]) < 0.0001)
x->signal_I[j] = 0.0;
}
x->signal_I[frame_size_half]=0; // Nyquist
// PROCESSING
for(i=0; i<=frame_size_half; i++)
{
// Calculate the magnitude
x->signal_mag[i] = cabsf(x->signal_R[i]+I*x->signal_I[i]); //sqrt(x->signal_R[i]*x->signal_R[i]+x->signal_I[i]*x->signal_I[i]);
// Calculate the phase
x->signal_phase[i] = cargf(x->signal_R[i]+I*x->signal_I[i]); //sqrt
// Calculate the phase difference between consecutive frames
x->phase_dif[i] = x->signal_phase[i] - x->prev_signal_phase[i];
//Store current frame's phase for next frame's processing
x->prev_signal_mag[i] = x->signal_mag[i];
x->prev_signal_phase[i] = x->signal_phase[i];
// Remove the expected phase difference
x->phase_dif[i] -= hop_in*2*M_PI*i/frame_size; //2*M_PI*i/x->overlap_in;
// Wrap around
x->phase_dif[i] = x->phase_dif[i] + M_PI;
x->phase_dif[i] = (x->phase_dif[i]-floor(x->phase_dif[i]/(2*M_PI)) * 2*M_PI) - M_PI;
// Calculate true frequency
x->true_freq[i] = 2*M_PI*i/frame_size + x->phase_dif[i]/hop_in; //W_bin + deltaW
// Get the cumulative phase
x->cumulative_phase[i] += (hop_out)* x->true_freq[i];
// Wrap around
x->cumulative_phase[i] += M_PI;
x->cumulative_phase[i] -= floor(x->cumulative_phase[i]/(2*M_PI))*2*M_PI - M_PI;
// Save the real and imaginary part
x->signal_R[i] = x->signal_mag[i] * cos(x->cumulative_phase[i]);
x->signal_I[i] = x->signal_mag[i] * sin(x->cumulative_phase[i]);
}
// SYNTHESIS
// pack real and imaginary parts in correct order for mayer_realifft
for(i=0; i<=frame_size_half; i++)
x->input_buf_windowed[i] = x->signal_R[i];
for(i=(frame_size_half+1), j=(frame_size_half-1); i<frame_size; i++, j--)
x->input_buf_windowed[i] = x->signal_I[j];
// resynth
mayer_realifft(frame_size, x->input_buf_windowed);
// window
for(i=0; i<frame_size; i++)
{
x->input_buf_windowed[i] *= x->hann[i];
x->input_buf_windowed[i] *= amp_scalar;
}
// Overlap/Add:
// shift overlap/add buffer's previous contents back
for(i=0; i<( 2*frame_size - hop_out); i++)
x->overlap_add_buffer[i] = x->overlap_add_buffer[i+hop_out];
// Set to 0 last overlap chunk:
for(i= (2*frame_size - hop_out); i< 2*frame_size; i++)
x->overlap_add_buffer[i] = 0;
// Overlap/add most recent block
for(i=0; i<frame_size; i++)
x->overlap_add_buffer[frame_size + i] += x->input_buf_windowed[i];
// Put out a hop_out size array
for(i=0; i<hop_out; i++)
x->vocoder_output[i] = x->overlap_add_buffer[frame_size - hop_out + i];
// RE-SAMPLING
int index_floor, index_ceil;
for(i=0; i<hop_in; i++)
{
index_floor = floor(alpha*i);
index_ceil = index_floor + 1;
x->final_output[i] = x->vocoder_output[ index_floor];
x->final_output[i] += ( x->vocoder_output[index_ceil] - x->vocoder_output[index_floor] )*(alpha*i - index_floor);
}
}; // If
// OUTPUT
for(i=0; i<n; i++, out++)
*out = x->final_output[(x->dsp_tick*n)+i];
x->dsp_tick++;
return (w+5);}