2011-03-01 103 views
10
音频计算世界的

你好样的人的阵列的间距,编程增加音频采样

我有一个respresent记录样本数组。让我们说,它是在44100Hz 5秒。我将如何以更高的音调回放?是否有可能动态增加和减少音高?就像球场慢慢增加,速度加倍,然后回落。

换句话说,我想借此录制和回放,就好像它是由一个D.J.“划伤”

伪总是欢迎。我会起来C.写这

感谢,


编辑1

让我澄清我的意图。我想保持在44100Hz播放等于是我需要播放前处理样品。这也是因为我想混合具有增加的间距与被以正常速度运行音频音频。

以另一种方式表达,也许我需要在同一批样品莫名其妙的收缩声音?这样回放时它会听起来更快?


EDIT 2

另外,我想这样做我自己。没有图书馆请(除非你觉得我可以挑选的代码,并找到有趣的东西)。


EDIT 3

用C语言编写的代码的试片的是需要两个参数(样品和音调因数的数组),然后返回新的音频的阵列将是非常美妙!


PS我已经开始在这个奖金不是因为我不认为已经给出的答案是无效的。我只是觉得在这个问题上得到更多的反馈是很好的。



AWARD BOUNTY

的老实说,我希望我能在几个不同的答案分发奖金,因为他们是我认为是超级有帮助不少。特别大喊答题节目环节丹尼尔传递我一些代码和AShelly和Hotpaw2的投入如此详细的答复。

最终,尽管我使用了来自datatist引用的another SO question的回答,所以颁奖给了他。

再次感谢大家!

+0

请澄清编辑3.搔抓像DJ的记录将导致一个文件,是不一样的长度。例如如果DJ快速旋转一个记录两次,则记录该声音的文件将是原始长度的一半。这是你想要的吗? – hotpaw2 2011-03-19 18:26:13

+0

@ hotpaw2。是的,对此感到抱歉。我纠正了编辑3.事实上,它将是一半的长度,这正是我期待的。谢谢:) – 2011-03-21 09:52:15

回答

9

看看Nosredna的“大象”论文对此的回答(非常相似)SO问题:提供 How do you do bicubic (or other non-linear) interpolation of re-sampled audio data?

实现范例开始第37页,以及用于参考,AShelly的回答对应于线性内插(即同一页上)。稍微调整一下,本文中的任何其他公式都可以插入到该框架中。

为了评估一个给定的插值方法的质量(以及使用“便宜”方案的理解潜在的问题),看看这个页面:

http://www.discodsp.com/highlife/aliasing/

更多的理论可能比你想处理(源代码),这是一个很好的参考,以及:

https://ccrma.stanford.edu/~jos/resample/

0

为了减小和增大的间距为在比44.1kHz的较低或较高的速率播放样品背面一样简单。这将产生较慢/较快的录音,但您需要添加真实记录的“scratchiness”。

+0

请看看我的编辑1. – 2011-03-01 15:23:56

+1

+1我认为这是最简单的解决方案。大多数音频硬​​件支持非常容易地更改播放速率。 – user492238 2011-03-25 09:54:47

+0

@ user492238通用音频硬件在应用程序之间共享,并以固定速率运行。软件混合器由操作系统提供,以表示您拥有“拥有”硬件。 – 2014-01-24 22:20:11

0

This帮助我重新采样,这是你需要同样的事情刚刚从对面望去。

如果你找不到代码,ping我,我有一个很好的C例程。

+0

我看不清楚,FIR在这里会有帮助吗? OP正在寻找的是以*非线性*方式改变音频。基本上,FIR有帮助的是改变音频中几个频率的大小,而不是改变固有频率,信号是由? – user492238 2011-03-25 09:53:15

8

的一种方式是一个浮点指数保持到原来的波,和内插样本混合到输出波形。

//Simulate scratching of `inwave`: 
// `rate` is the speedup/slowdown factor. 
// result mixed into `outwave` 
// "Sample" is a typedef for the raw audio type. 
void ScratchMix(Sample* outwave, Sample* inwave, float rate) 
{ 
    float index = 0; 
    while (index < inputLen) 
    { 
     int i = (int)index;   
     float frac = index-i;  //will be between 0 and 1 
     Sample s1 = inwave[i]; 
     Sample s2 = inwave[i+1]; 
     *outwave++ += s1 + (s2-s1)*frac; //do clipping here if needed 
     index+=rate; 
    } 

}

如果你想在飞行中改变rate,你可以做到这一点。

如果这产生嘈杂工件时率> 1时,尝试使用这种技术(from this question

*outwave++ = InterpolateHermite4pt3oX(inwave+i-1,frac); 

替换*outwave++ += s1 + (s2-s1)*frac;其中使用的“线性内插技术的

public static float InterpolateHermite4pt3oX(Sample* x, float t) 
{ 
    float c0 = x[1]; 
    float c1 = .5F * (x[2] - x[0]); 
    float c2 = x[0] - (2.5F * x[1]) + (2 * x[2]) - (.5F * x[3]); 
    float c3 = (.5F * (x[3] - x[0])) + (1.5F * (x[1] - x[2])); 
    return (((((c3 * t) + c2) * t) + c1) * t) + c0; 
} 

实施例Windows Startup.wav“的系数为1.1。原来是在上面,在加速的版本是在底部:

它可能不是数学上完美的,但它听起来像它应该,而且应该做工精细的OP的需求..

+0

这是行不通的,因为音频不是屏幕上的像素 - 并且会在输出信号中给您带来令人难以置信且难以忍受的声音伪影和噪音。此外,您不需要裁剪,因为权重始终总和为100%,因此不会发生溢出。 – 2011-03-02 11:10:39

+0

@DanielMošmondor,这个_does_工作,假设'inwave'是一个pcm频道,你的因素并不是那么极端,以至于你会失去别名。我有一个红宝石工作程序来证明它。如果您将样本与时间进行比较,您会得到一个波形。插入点以给出该波形的不同表示是完全有效的。 – AShelly 2011-03-02 21:48:06

+0

至于剪辑,我添加了评论来处理OP的意见,他想将拉伸的样本混合到另一个轨道。这段代码处理'outwave'已经包含好数据的情况。 – AShelly 2011-03-02 21:50:31

3

是的,这是可能的。

但是这不是伪代码量小。您正在寻求一种时间音高修改算法,这是一个相当大且复杂的DSP代码量,用于体面的结果。

这里有一个 Time Pitch stretching overview from DSP Dimensions。您也可以使用Google进行相位声码器算法。

新增:

如果要“从零开始”,作为一个DJ可能与在物理转盘的LP做的,你不需要时间音高修改。 Scratching以相同的数量改变球场和速度(不是独立的,因为需要时间间距修改)。

并将所得阵列将不具有相同的长度,但将通过音调/变速的入账金额更短或更长。

通过使用正确过滤的插值重新采样信号,您可以改变音高,并以相同的比例使声音播放更快或更慢。只需移动每个采样点,而不是1.0,通过浮动点加上所需的速率变化,然后过滤并插入该点处的数据。使用带窗口的Sinc插值内核进行插值,其低通滤波器转换频率低于原始插值局部采样率和插值局部采样率的较低值,可以很好地工作。在网上搜索“窗口Sinc插值”会返回很多合适的结果。

你需要包括低通滤波器,否则你会听到可怕的混叠噪声的插值方法。 (例外情况是,如果您的原始声音文件已经严重低通滤波,比采样率低十倍或更多)。

2

如果你想要这个很容易做到,看到AShelly的建议[编辑:作为事实上,第一次尝试也无妨]。如果您需要高质量,则基本上需要phase vocoder

相位声码器的非常基本的想法是找到声音组成的频率,改变这些频率根据需要和再合成的声音。因此,一个残酷的简化是:

  1. 运行FFT
  2. 改变所有频率的一个因素
  3. 运行逆FFT

如果你要自己实现,你一定要读a thorough explanation of how a phase vocoder works。算法确实需要比上述三步简化更多的考虑。

当然,ready-made实施exist,但从我收集你想自己做这个问题。

+1

我喜欢第二个链接,它有很好的说明。但是我有点困惑:在所描述的算法中,在逆FFT之后,您会得到“一个信号,现在要么延伸或压缩,并且音调不会改变”。你是否也在说改变音调(因为这是OP所要的),你需要在FFT之后修改频率数据吗?这是否就像重新解释当你做相反的时候箱子有多宽一样简单? – AShelly 2011-03-24 17:38:46

+0

@快速:发生的情况是首先音频在保持音高的同时被拉伸/压缩,然后加速/减速以获得适当的长度。这导致了想要的音高改变。我的粗略简化可能不是可以直接实施的;我认为这是主意,但是这样做是为了获得正确的阶段。我自己没有经验实现声码器的经验,但有些人使用其他FFT/DCT。所以我试图指出一个很好的来源。 – dancek 2011-03-24 19:59:23

+0

此外,我绝对建议首先尝试AShelly算法,如果自己做这件事很重要。 – dancek 2011-03-24 20:01:12