Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在iOS上录制、修改和播放音频_Ios_Audio_Avfoundation_Audio Recording_Pitch - Fatal编程技术网

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

在iOS上录制、修改和播放音频,ios,audio,avfoundation,audio-recording,pitch,Ios,Audio,Avfoundation,Audio Recording,Pitch,编辑:最后,正如我在下面解释的那样,我使用了AVRecorder来录制语音,使用openAL进行音调转换和播放。结果很好 我有一个关于录音、修改和播放音频的问题。我以前问过一个类似的问题(),但现在我有了更多的信息,请给我一些进一步的建议 首先,这是我要做的(在主线程的一个单独线程上): 监控iphone麦克风 检查声音是否大于一定音量 如果高于阈值,则开始录制,例如,此人开始讲话 继续记录,直到音量降至阈值以下,例如,人员停止讲话 修改录制声音的音调 播放声音 我正在考虑使用AVRecorde

编辑:最后,正如我在下面解释的那样,我使用了AVRecorder来录制语音,使用openAL进行音调转换和播放。结果很好

我有一个关于录音、修改和播放音频的问题。我以前问过一个类似的问题(),但现在我有了更多的信息,请给我一些进一步的建议

首先,这是我要做的(在主线程的一个单独线程上):

  • 监控iphone麦克风
  • 检查声音是否大于一定音量
  • 如果高于阈值,则开始录制,例如,此人开始讲话
  • 继续记录,直到音量降至阈值以下,例如,人员停止讲话
  • 修改录制声音的音调
  • 播放声音
  • 我正在考虑使用AVRecorder来监视和录制声音,这里有一个很好的教程:

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


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

    您可以使用AVRecorder或类似实时IO音频单元的更低版本

    “体积”的概念相当模糊。您可能希望了解计算峰值和RMS值之间的差异,并了解如何在给定时间内积分RMS值(例如VU仪表使用的300ms)

    基本上你要求所有值的平方和。您可以取平方根,并使用10*log10f(sqrt(sum/num_samples))转换为dBFS,但使用20*log10f(sum/num_samples)一步就可以不用sqrt

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

    对于音高变换,我认为OpenAL采用了这种技巧,其背后的技术称为带限插值-

    此示例将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);
        }
    };
    
    class真空计
    {
    受保护的:
    //每秒采样数
    浮式采样器;
    //积分时间(秒)(vu计为300ms)
    浮点积分时间;
    //它们维护一个循环缓冲区,其中包含
    //音频样本的“正方形”
    int_积分缓冲长度;
    浮点*集成缓冲区;
    浮点*\u集成缓冲区结束;
    浮动*光标;
    //这是一种用于运行的累加器
    //平均效率更高
    浮点数;
    公众:
    VUMeter()
    :_采样器(48000.0f)
    积分时间(0.3f)
    ,_和(0)
    {
    //创建要集成的值缓冲区
    //例如,48khz时300ms为14400个样本
    _integrationBufferLength=(int)(\u integrationTime*\u sampleRate);
    _integrationBuffer=新浮点[_integrationBufferLength+1];
    bzero(_integrationBuffer,_integrationBufferLength);
    //为循环缓冲区设置指针
    _integrationBufferEnd=\u integrationBuffer+\u integrationBufferLength;
    _游标=\u集成缓冲区;
    }
    ~VUMeter()
    {
    删除集成缓冲区;
    }
    浮点getRms(浮点*音频,整数样本)
    {
    //处理样品
    //此部分累积“正方形”
    对于(int i=0;i
    您可以使用AVRecorder或类似实时IO音频单元的更低版本

    “体积”的概念相当模糊。您可能希望了解计算峰值和RMS值之间的差异,并了解如何在给定时间内积分RMS值(例如VU仪表使用的300ms)

    基本上你要求所有值的平方和。您可以取平方根,并使用10*log10f(sqrt(sum/num_samples))转换为dBFS,但使用20*log10f(sum/num_samples)一步就可以不用sqrt

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

    对于音高变换,我认为OpenAL采用了这种技巧,其背后的技术称为带限插值-

    此示例将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);
        }
    };
    
    class真空计
    {
    受保护的:
    //每秒采样数
    浮式采样器;
    //积分时间(秒)(vu计为300ms)
    浮点积分时间;
    //它们维护一个循环缓冲区,其中包含
    //音频样本的“正方形”
    int_积分缓冲长度;
    浮点*集成缓冲区;
    浮点*\u集成缓冲区结束;
    浮动*光标;
    //这是一种用于运行的累加器
    //平均效率更高
    浮点数;
    公众:
    VUMeter()
    :_采样器(48000.0f)
    积分时间(0.3f)
    ,_和(0)
    {
    //创建要集成的值缓冲区
    //例如,48khz时300ms为14400个样本
    _int