0

编辑:最后我完全按照下面的解释使用了 AVRecorder 用于录制语音,而 openAL 用于音高转换和播放。结果很好。

我有一个关于录制、修改和播放音频的问题。我之前问过一个类似的问题(在 iOS 上实时录制、修改音高和播放音频),但我现在有了更多信息,可以提供一些进一步的建议。

所以首先这是我想要做的(在主线程的单独线程上):

  1. 监控 iphone 麦克风
  2. 检查大于某个音量的声音
  3. 如果高于阈值开始记录,例如人开始说话
  4. 继续录音,直到音量降至阈值以下,例如人停止说话
  5. 修改录制声音的音高。
  6. 播放声音

我正在考虑使用 AVRecorder 来监控和录制声音,这里有很好的教程:http: //mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/

我正在考虑使用 openAL 来修改录制音频的音高。

所以我的问题是,我在上述要点列表中的想法是否正确,我是否遗漏了什么或者有更好/更简单的方法来做到这一点。我可以避免混合音频库而只使用 AVFoundation 来改变音高吗?

4

2 回答 2

2

您可以使用 AVRecorder 或更低的版本,例如实时 IO 音频单元。

“体积”的概念非常模糊。您可能想查看计算峰值和 RMS 值之间的差异,并了解如何在给定时间(比如 300 毫秒,这是 VU 表使用的)内积分 RMS 值。

基本上,您将所有值的平方相加。您将取平方根并使用 10 * log10f(sqrt(sum/num_samples)) 转换为 dBFS,但您可以使用 20 * log10f(sum/num_samples) 一步完成,而无需 sqrt。

您需要对集成时间和阈值进行大量调整,以使其以您想要的方式运行。

对于音高转换,我认为 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);
    }
};
于 2011-02-28T05:33:55.797 回答
1

OpenAL resampling will change the pitch and the duration inversely. e.g. a sound resampled to a higher pitch will play for a shorter amount of time and thus faster.

于 2011-02-28T06:21:06.033 回答