在iOS上录制,修改和播放音频 [英] Recording, modifying and playing audio on iOS
问题描述
编辑:最后,我完全按照下面的说明使用,AVRecorder用于录制语音,openAL用于音高移位和播放。它运作得很好。
In the end I used exactly as I explained below, AVRecorder for recording the speech and openAL for the pitch shift and playback. It worked out quite well.
我有一个关于录制,修改和播放音频的问题。之前我问了一个类似的问题(记录,修改在iOS上实时播放和播放音频)但我现在有更多的信息,可以提供一些进一步的建议。
I got a question regarding recording, modifying and playing back audio. I asked a similar question before ( Record, modify pitch and play back audio in real time on iOS ) but I now have more information and could do with some further advice please.
所以首先这是什么我正在尝试(在主线程的单独线程上):
So firstly this is what I am trying to do (on a separate thread to the main thread):
- 监听iphone麦克风
- 检查大于某一音量的声音
- 如果超过阈值开始录音,例如此人开始说话
- 继续记录,直到音量降至阈值以下,例如人不再说话
- 修改录制声音的音高。
- 播放声音
- monitor the iphone mic
- check for sound greater than a certain volume
- if above threshold start recording e.g. person starts talking
- continue to record until volume drops below threshold e.g. person stops talking
- modify pitch of recorded sound.
- playback sound
我正在考虑使用AVRecorder来监听和录制声音,这里有一个很好的教程: http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/
I was thinking of using the AVRecorder to monitor and record the sound, good tutorial here: http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/
我正在考虑使用openAL修改录制音频的音高。
and I was thinking of using openAL to modify the pitch of the recorded audio.
所以我的问题是,我的想法是正确的上面的点列表,我错过了什么或有更好/更简单的方法来做到这一点。我可以避免混合使用音频库,也可以使用AVFoundation来改变音高吗?
So my question is, is my thinking correct in the list of points above, am I missing something or is there a better/easier way to do it. Can I avoid mixing audio libraries and just use AVFoundation to change the pitch too?
推荐答案
您可以使用AVRecorder或类似的东西实时IO音频单元。
You can either use AVRecorder or something lower like the realtime IO audio unit.
'音量'的概念非常模糊。您可能希望了解计算峰值和RMS值之间的差异,并了解如何在给定时间内整合RMS值(例如300米,这是VU仪表使用的值)。
The concept of 'volume' is pretty vague. You might want to look at the difference between calculating peak and RMS values, and understanding how to integrate an RMS value over a given time (say 300ms which is what a VU meter uses).
基本上你总结了值的所有平方。您可以使用平方根并使用10 * log10f(sqrt(sum / num_samples))转换为dBFS,但是您可以使用20 * log10f(sum / num_samples)在没有sqrt的情况下执行此操作。
Basically you sum all the squares of the values. You would take the square root and convert to dBFS with 10 * log10f(sqrt(sum/num_samples)), but you can do that without the sqrt in one step with 20 * log10f(sum/num_samples).
你需要做很多调整积分时间和阈值才能让它按照你想要的方式运行。
You'll need to do a lot of adjusting of integration times and thresholds to get it to behave the way you want.
For音高变换,我认为OpenAL有诀窍,其背后的技术称为带限插值 - https://ccrma.stanford.edu/~jos/resample/Theory_Ideal_Bandlimited_Interpolation.html
For pitch shifting, I think OpenAL with do the trick, the technique behind it is called band limited interpolation - https://ccrma.stanford.edu/~jos/resample/Theory_Ideal_Bandlimited_Interpolation.html
此示例将rms计算显示为运行平均值。循环缓冲区保持正方形的历史,并且无需对每个操作求和。我没有运行它所以把它当作伪代码;)
This example shows a rms calculation as a running average. The circular buffer maintains a history of squares, and eliminates the need to sum the squares every operation. I haven't run it so treat it as pseudo code ;)
示例:
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);
}
};
这篇关于在iOS上录制,修改和播放音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!