从内置音频输入中捕获音频的最简单方法是什么,并且能够在请求时实时读取原始采样值(如.wav中),例如从套接字读取。 / p>
希望代码使用Apple的一个框架(音频队列)。文档不是很清楚,我需要的是非常基础的。
答案 0 :(得分:7)
为此尝试AudioQueue框架。您主要必须执行3个步骤:
在第3步中,您有机会使用AudioQueueGetProperty()分析传入的音频数据
大致是这样的:
static void HandleAudioCallback (void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc) {
// Here you examine your audio data
}
static void StartRecording() {
// now let's start the recording
AudioQueueNewInput (&aqData.mDataFormat, // The sampling format how to record
HandleAudioCallback, // Your callback routine
&aqData, // e.g. AudioStreamBasicDescription
NULL,
kCFRunLoopCommonModes,
0,
&aqData.mQueue); // Your fresh created AudioQueue
AudioQueueStart(aqData.mQueue,
NULL);
}
我建议Apple AudioQueue Services Programming Guide了解有关如何启动和停止AudioQueue以及如何正确设置所有必需对象的详细信息。
您可能还需要仔细研究Apple的演示程序SpeakHere。但这是恕我直言,开始时有点混乱。
答案 1 :(得分:2)
这取决于你需要它的“实时”
如果您需要它非常清脆,请在底层向下并使用音频单元。这意味着设置INPUT回调。请记住,当发生这种情况时,您需要分配自己的缓冲区,然后从麦克风请求音频。
即不要被参数中存在缓冲区指针所迷惑......它只是因为Apple正在为输入使用相同的函数声明并渲染回调。
这是我的一个项目中的粘贴:
OSStatus dataArrivedFromMic(
void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * dummy_notused )
{
OSStatus status;
RemoteIOAudioUnit* unitClass = (RemoteIOAudioUnit *)inRefCon;
AudioComponentInstance myUnit = unitClass.myAudioUnit;
AudioBufferList ioData;
{
int kNumChannels = 1; // one channel...
enum {
kMono = 1,
kStereo = 2
};
ioData.mNumberBuffers = kNumChannels;
for (int i = 0; i < kNumChannels; i++)
{
int bytesNeeded = inNumberFrames * sizeof( Float32 );
ioData.mBuffers[i].mNumberChannels = kMono;
ioData.mBuffers[i].mDataByteSize = bytesNeeded;
ioData.mBuffers[i].mData = malloc( bytesNeeded );
}
}
// actually GET the data that arrived
status = AudioUnitRender( (void *)myUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
& ioData );
// take MONO from mic
const int channel = 0;
Float32 * outBuffer = (Float32 *) ioData.mBuffers[channel].mData;
// get a handle to our game object
static KPRing* kpRing = nil;
if ( ! kpRing )
{
//AppDelegate * appDelegate = [UIApplication sharedApplication].delegate;
kpRing = [Game singleton].kpRing;
assert( kpRing );
}
// ... and send it the data we just got from the mic
[ kpRing floatsArrivedFromMic: outBuffer
count: inNumberFrames ];
return status;
}