我的小组正在开发一个简单的MATLAB图形用户界面(GUI),用于记录麦克风的音频 - 插入或内置到计算机中 - 并播放信号。到目前为止,我们已经完成了。我们的GUI还可以加载一个样本(.wav文件等)并使用GUI上相同的“播放”按钮播放它。我们有一个播放,录制,加载和保存按钮。现在对于加载或记录的样本的音高变换......我们知道我们需要一个峰值拾取算法来找到信号的基频。然后我们认为我们可以将每个值乘以一个常数来改变所有这些频率的音高。我们的目标是使用这个算法并将不同的按钮分配给不同的按钮或无线按钮,我们可以在其中加载我们的样本,按下按钮并通过这样做来操纵音高,然后播放它。使用峰值拾取算法是否会充分改变信号的音调,或者在播放过程中信号会被搞砸?
(这不是实时处理)
答案 0 :(得分:4)
正如我在上面的评论中所提到的,您可以使用两种方法,即相位声码器或更高的采样率。使用声码器的第一种方法将保持信号长度,同时将所包含的频率移位得更高。我不打算通过算法来了解如何执行此操作,但哥伦比亚大学公开提供代码 - http://www.ee.columbia.edu/ln/labrosa/matlab/pvoc/
第二种方法是将* .wav文件写入更高的采样率。
假设您有一个440 Hz的信号,你希望它是880 Hz,只需加倍采样率。
所以不要说wavwrite(signal,fs,'file')
,而是使用wavwrite(signal,2*fs,'file')
然而,这会缩短音频文件的长度,无论您采用何种因素提高采样率。
总的来说,我认为更好,更令人印象深刻的方法是声码器,我不建议盲目地使用哥伦比亚的代码,但实际上需要时间来理解它并且能够以数学方式解释它背后的逻辑
答案 1 :(得分:3)
比哥伦比亚算法稍微简单一点(不是表现得很好,但可能让你对它的工作方式有所了解)会是这样的:
interp1
以更高的采样率重新采样FFT;例如,向上移动1个完整音符(2个半音符),你可以做到
F1 = fft(originalSignal);
N = numel(F1);
F1a = F1(1:N/2); % the lower half of the fft
F1b = F1(end:-1:N/2+1); % the upper half of the fft - flipped "the right way around"
t1 = 1:N/2; % indices of the lower half
t2 = 1+ (t1-1) / (1 + 2.^(2/12)); % finer sampling... will make peaks appear higher
F2a = interp1(t1, F1a, t2); % perform sampling of lower half
F2b = interp1(t1, F1b, t2); % resample upper half
F2 = [F2a F2b(end:-1:1)]; % put the two together again
shiftedSignal = ifft(F2); % and do the inverse FFT
我没有做任何窗口等,所以这是“近似”。实际上,您希望一次处理一小部分重叠的数据块,而不是一次处理整个文件。所以上面应该被认为是“仅用于说明”,而不是工作代码。
答案 2 :(得分:0)
音高转换的一个强大特性是在不改变声音速度的情况下改变音高,如果你改变采样率,你的速度就会改变,你需要重新采样你的信号。
如果你的麦克风输入始终是单声道的,你应该考虑使用PSOLA方法,在时域中工作,你可以在语音信号中得到很好的结果