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

编辑:最后,我完全按照下面的说明使用,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来改变音高吗?

您可以使用AVRecorder或类似实时IO音频单元的东西。

“量”的概念非常模糊。 您可能希望了解计算峰值和RMS值之间的差异,以及了解如何在给定时间内集成RMS值(例如300米,这是VU仪表使用的值)。

基本上你总结了值的所有平方。 您可以使用平方根并使用10 * log10f(sqrt(sum / num_samples))转换为dBFS,但是您可以在没有sqrt的情况下使用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 // eg 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); } }; 

OpenAL重采样将反向改变音高和持续时间。 例如,重新采样到更高音高的声音将播放更短的时间并因此更快。