持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情
iOS实现耳返功能
实现iOS 耳返的功能可以通过AudioUnit来进行实现。
实现的步骤如下:
-
创建
AudioSession获取硬件的权限在iOS的音视频开发中,使用音频回话需要创建一个AudioSession,用于管理与获取iOS设备的音频信息。
AVAudioSession *session = [AVAudioSession sharedInstance];根据我们的具体需求来设置类别:
1)在类别中如果需要进行录音等操作,需要设置类别为record 类型
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&error];2)设置I/O 的buffer,buffer越小说明延迟越低
NSTimeInterval bufferTimer = 0.01; [session setPreferredIOBufferDuration:bufferTimer error:nil];3) 进行
audioSession被打断进行监听/// 接收session 被打断的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; /// 处理监听 - (void)handleInterruption:(NSNotification *)notification { NSDictionary *dic = notification.userInfo; if ([notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeBegan) { // 开始被打断,暂停 } else if ([dic[AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeEnded) { // 结束打断了, 重开 }
}
-
构建AudioUnit
在创建并启用音频会话之后,就可以构建AudioUnit 了。构建的时候需要制定类型、子类型以及厂商。我们以RemoteIO 这个AudioUnit为例来讲解他的参设置,RemoteIO 这个AudioUnit 是一个和硬件相关的Unit,他分为输入端和输出端。输入端一般指的就是麦克风,输出端指的就是扬声器或者耳机。如果同时需要输入输出,即我们的耳返功能,则需要开发者做一些设置将他们联系起来。
- 指定
AudioUnit的属性 - 实例化
AUGraph对象(代表 audio processing graph)。(可以通过其他方式创建audioUnit) - 实例化一个或多个
AUNode对象(每一个代表一个 audio unit in the graph.)。 - 添加nodes到graphgraph并且实例化
- 打开graph并且实例化 audio units
- 获取audioUnit引用
- 使用属性配置AudioUnit
AudioComponentDescription audioDesc = {0}; audioDesc.componentManufacturer = kAudioUnitManufacturer_Apple; audioDesc.componentType = kAudioUnitType_Output; audioDesc.componentSubType = kAudioUnitSubType_RemoteIO; audioDesc.componentFlags = 0; audioDesc.componentFlagsMask = 0; // 创建augraph AUGraph processingGraph; NewAUGraph(&processingGraph); // 按照描述在AUGraph 中增加一个AUNode AUNode ioNode; AUGraphAddNode(processingGraph, &audioDesc, &ioNode); // 打开AUGraph AUGraphOpen(processingGraph); // 获得audioUnit 的引用 AudioUnit audioUnit; AUGraphNodeInfo(processingGraph, ioNode, NULL, &audioUnit);// 配置属性 UInt32 oneFlag = 1; AudioUnitSetProperty(remoteIOUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &oneFlag, sizeof(oneFlag)); AudioUnitSetProperty(remoteIOUnit, // unit kAudioOutputUnitProperty_EnableIO, // ID kAudioUnitScope_Input, // scope 1, // element &oneFlag, sizeof(oneFlag)); - 指定
3. 使用`AUGraphSetNodeInputCallback` 配置audioUnit回调函数
```Objc
inputProc.inputProc = myInputCallBack;
inputProc.inputProcRefCon = (__bridge void *)(self);
AUGraphSetNodeInputCallback(auGraph, remoteIONode, 0, &inputProc)
4.使用audioGraph为audioUnit 分配内存
// 在调用initialize 之前可以先调用update 方法,如果update 成功,则graph 已经被动态配置就位
AUGraphUpdate(auGraph, NULL);
AUGraphInitialize(auGraph);
- 开始接收数据并回传给耳机
AUGraphStart(auGraph);
// cashow 是打印状态
CAShow(auGraph);
- 停止使用
AUGraphStop(auGraph);