编辑:最后,我完全按照下面的说明使用,AVRecorder用于录制语音,openAL用于音高移位和播放。它运作得很好。
我有一个关于录制,修改和播放音频的问题。我之前问了一个类似的问题(Record, modify pitch and play back audio in real time on iOS),但我现在有更多的信息,可以提供一些进一步的建议。
首先,这就是我要做的事情(在主线程的单独线程上):
我在考虑使用AVRecorder来监听和录制声音,这里有一个很好的教程:http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/
我正在考虑使用openAL来修改录制音频的音高。
所以我的问题是,我的想法在上面的点列表中是正确的,我是否遗漏了某些东西,或者是否有更好/更简单的方法来做到这一点。我可以避免混合音频库,也可以使用AVFoundation来改变音高吗?
答案 0 :(得分:2)
您可以使用AVRecorder或类似实时IO音频设备的其他设备。
'音量'的概念非常模糊。您可能希望了解计算峰值和RMS值之间的差异,以及了解如何在给定时间内集成RMS值(例如300米,这是VU仪表使用的值)。
基本上,你总结了值的所有平方。您可以使用平方根并使用10 * log10f(sqrt(sum / num_samples))转换为dBFS,但是您可以在没有使用20 * log10f(sum / num_samples)的步骤的情况下执行此操作。
您需要对整合时间和阈值进行大量调整,以使其按照您希望的方式运行。
对于音高变换,我认为OpenAL有诀窍,其背后的技术称为带限插值 - https://ccrma.stanford.edu/~jos/resample/Theory_Ideal_Bandlimited_Interpolation.html
此示例将rms计算显示为运行平均值。循环缓冲区保持正方形的历史,并且无需对每个操作求和。我没有运行它所以把它当作伪代码;)
示例:
class VUMeter
{
protected:
// samples per second
float _sampleRate;
// the integration time in seconds (vu meter is 300ms)
float _integrationTime;
// these maintain a circular buffer which contains
// the 'squares' of the audio samples
int _integrationBufferLength;
float *_integrationBuffer;
float *_integrationBufferEnd;
float *_cursor;
// this is a sort of accumulator to make a running
// average more efficient
float _sum;
public:
VUMeter()
: _sampleRate(48000.0f)
, _integrationTime(0.3f)
, _sum(0.)
{
// create a buffer of values to be integrated
// e.g 300ms @ 48khz is 14400 samples
_integrationBufferLength = (int) (_integrationTime * _sampleRate);
_integrationBuffer = new float[_integrationBufferLength + 1];
bzero(_integrationBuffer, _integrationBufferLength);
// set the pointers for our ciruclar buffer
_integrationBufferEnd = _integrationBuffer + _integrationBufferLength;
_cursor = _integrationBuffer;
}
~VUMeter()
{
delete _integrationBuffer;
}
float getRms(float *audio, int samples)
{
// process the samples
// this part accumulates the 'squares'
for (int i = 0; i < samples; ++i)
{
// get the input sample
float s = audio[i];
// remove the oldest value from the sum
_sum -= *_cursor;
// calculate the square and write it into the buffer
double square = s * s;
*_cursor = square;
// add it to the sum
_sum += square;
// increment the buffer cursor and wrap
++_cursor;
if (_cursor == _integrationBufferEnd)
_cursor = _integrationBuffer;
}
// now calculate the 'root mean' value in db
return 20 * log10f(_sum / _integrationBufferLength);
}
};
答案 1 :(得分:1)
OpenAL重采样将反向改变音高和持续时间。例如重新采样到更高音高的声音将播放更短的时间,从而更快。