在iOS上录制,修改和播放音频

时间:2011-02-28 03:08:06

标签: ios audio avfoundation audio-recording pitch

编辑:最后,我完全按照下面的说明使用,AVRecorder用于录制语音,openAL用于音高移位和播放。它运作得很好。

我有一个关于录制,修改和播放音频的问题。我之前问了一个类似的问题(Record, modify pitch and play back audio in real time on iOS),但我现在有更多的信息,可以提供一些进一步的建议。

首先,这就是我要做的事情(在主线程的单独线程上):

  1. 监听iphone话筒
  2. 检查大于某个音量的声音
  3. 如果高于阈值则开始记录,例如人开始说话
  4. 继续记录,直到音量降至阈值以下,例如人停止说话
  5. 修改录制声音的音高。
  6. 播放声音
  7. 我在考虑使用AVRecorder来监听和录制声音,这里有一个很好的教程:http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/

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

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

2 个答案:

答案 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重采样将反向改变音高和持续时间。例如重新采样到更高音高的声音将播放更短的时间,从而更快。