回忆一个场景,我们使用iPhone 打开一首歌曲,音频从内置扬声器中播放出来,此时有电话拨入,音乐会立即停止并处于暂停状态。此时听到的是手机呼叫的铃声,当我们挂掉电话后,刚才的音乐再次响起。在这一过程中 iOS 提供了一个可管理的音频环境,通过 音频会话(Audio Session)来管理应用程序、应用程序间和设备级别的音频行为。
音频会话在应用程序和操作系统之间扮演者中间人的角色,它提供了一种简单实用的方法使得系统得知应用程序应该如何与 iOS 音频环境进行交互。开发者不需要了解与音频硬件交互的具体细节,只需要对应用程序的行为进行抽象的配置,并把对该行为的管理委托给音频会话,可确保对用户的音频体验进行最佳管理。

所有 iOS 应用程序启动后,都具有一个默认音频会话,无论是否使用。默认音频会话来自于以下一些预配置:
默认音频会话提供了很多实用的功能,但在大多数情况下,开发者应该对其进行自定义以更好地满足应用程序的需求。要更改行为,需要配置应用的音频会话。幸运的是,通过设置”类别“功能,可以很容易地定制我们的特殊需求。
表达音频行为的主要机制是音频会话类别。通过设置类别,可以指定应用程序是使用输入还是输出,是否希望音乐与音频一起继续播放等等。AV Foundation 定义了许多音频会话类别,可让开发者自定义音频行为。下面表格总结了 AV Foundation 定义的 6 种类别行为细节。
| 类别 | 作用 | 是否允许混音 | 音频的输入与输出 | 由响铃/静音开关和屏幕锁定静音 |
|---|---|---|---|---|
AVAudioSessionCategoryAmbient |
游戏、效率应用程序 | Yes | 仅输出 | Yes |
AVAudioSessionCategorySoloAmbient (默认) |
游戏、效率应用程序 | No | 仅输出 | Yes |
AVAudioSessionCategoryPlayback |
音频和视频播放器 | 可选 | 仅输出 | No |
AVAudioSessionCategoryRecord |
录音机、音频捕捉 | No | 仅输入 | No |
AVAudioSessionCategoryPlayAndRecord |
Voip、语言聊天 | 可选 | 输入和输出 | No |
AVAudioSessionCategoryMultiRoute |
使用外部硬件的高级 A/V应用程序 | No | 输入和输出 | No |
可以通过 setCategory:mode:options:error:设置上述音频会话类别,其中一些分类可以通过使用 options 和 modes进一步自定义附加行为。示例如下:
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
if (![session setCategory:AVAudioSessionCategoryPlayback error:&error]) {
NSLog(@"Category Error: %@", [error localizedDescription]);
}
if (![session setActive:YES error:&error]) {
NSLog(@"Activation Error: %@", [error localizedDescription]);
}
音频中断是应用程序音频会话的停用——它会立即停止音频。当来自其它应用程序的音频会话被激活并且该会话未被系统分类以与我们的应用程序的音频混合时,就会发生中断。在会话处于非活动状态后,系统会发送一条“被中断”消息,可以通过保存状态、更新用户界面等来响应该消息。
应用程序可能会在中断后暂停。当用户接听电话时会发生这种情况。如果用户转而忽略呼叫或解除警报,系统会发出“中断结束”消息,并且应用程序会继续运行。要恢复音频,必须重新激活音频会话。下图说明了回放应用程序的音频会话中断之前、期间和之后的事件顺序。

中断事件(在此示例中为 FaceTime 请求的到达)按如下方式进行。编号的步骤对应于图中的数字。
在开发音频功能时,我们要确保应用程序可以正确地处理中断事件,音频会话相关代码以处理中断可确保应用程序的音频在来电、时钟或日历警报响起或其他应用程序激活其音频会话时继续正常运行。
首先需要得到中断出现的通知,可以选择注册应用程序的 AVAudioSession 发送的通知 AVAudioSessionInterruptionNotification。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
在系统发送通知调用 handlerInterruption: 时传递的NSNotification 实例包含一个 userInfo 提供中断详细信息的填充字典。可以通过从字典中检索 AVAudioSessionInterruptionType 值来确定中断的类型,中断类型指示中断是已经开始还是已经结束。
typedef NS_ENUM(NSUInteger, AVAudioSessionInterruptionType) {
AVAudioSessionInterruptionTypeBegan = 1, ///< the system has interrupted your audio session
AVAudioSessionInterruptionTypeEnded = 0, ///< the interruption has ended
};
当中断出现时,类型为 AVAudioSessionInterruptionTypeBegan,需要采取的动作就是暂停音频播放以及 UI 界面的处理。
当中断结束时,类型为 AVAudioSessionInterruptionTypeEnded,userInfo 中可能包含一个AVAudioSessionInterruptionOptions 值,指示音频会话是否以及重新激活以及它是否可以再次播放。如果选项值为 AVAudioSessionInterruptionOptionShouldResume,则可以继续播放。
当应用程序运行时,用户可能会插入或拔出耳机,或使用带有音频连接的扩展坞。iOS 人机界面指南描述了应用程序应如何响应此类事件。要实施这些建议,可以通过音频会话处理音频硬件路由的更改。
音频硬件路由是音频信号的有线电子通路。当设备的用户插入或拔出耳机时,系统会发生线路改变, AVAudioSession 会广播一个描述该变化的通知AVAudioSessionRouteChangeNotification 给所有相关的监听者。下图描述了录入和播放期间各种路线变化的事件:

如上图所示,在应用启动后,系统会初步确定音频路由。当应用程序运行时,它会继续监控活动路线。首先考虑用户在应用程序中点击“录制”按钮的情况,由图左侧的“录制开始”框表示。
在录制过程中,用户可以插入或拔出耳机,请参见图中左下角的菱形决策元素。作为响应,系统发送包含更改原因和先前路由的路由更改通知,应用应停止录制。
播放的情况类似,但结果不同,如图右侧所示。如果用户在播放过程中拔下耳机,应用应暂停音频。如果用户在播放过程中插入耳机,应用应该只允许继续播放。那么应该怎么做呢?
首先需要注册 AVAudioSession 发送的通知AVAudioSessionRouteChangeNotification,该通知包含一个 userInfo 字典,携带了通知发送的原因及前一个路由的描述。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRouteChange:)
name:AVAudioSessionRouteChangeNotification
object:[AVAudioSession sharedInstance]];
收到通知后查看保存在userInfo 字典中 AVAudioSessionRouteChangeReasonKey 判断路由变更的原因:
AVAudioSessionRouteChangeReasonNewDeviceAvailable,连接新设备AVAudioSessionRouteChangeReasonOldDeviceUnavailable,移除设备 当有设备断开时,获取 userInfo 中描述前一个路由信息 的AVAudioSessionRouteChangePreviousRouteKey,其整合在一个输入 NSArray 和一个输出 NSArray 中,判断其中第一个是否为 AVAudioSessionPortHeadphones (耳机接口)。
- (void)handleRouteChange:(NSNotification *)notification {
NSDictionary *info = notification.userInfo;
AVAudioSessionRouteChangeReason reason =
[info[AVAudioSessionRouteChangeReasonKey] unsignedIntValue];
if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
AVAudioSessionRouteDescription *previousRoute =
info[AVAudioSessionRouteChangePreviousRouteKey];
AVAudioSessionPortDescription *previousOutput = previousRoute.outputs[0];
NSString *portType = previousOutput.portType;
if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
//暂停
}
}
}
音频应用程序所需的一项常见功能是后台播放音频。启用此功能后,当用户切换到另一个应用程序或锁定他们的 iOS 设备时,应用程序的音频可以继续播放。在 iOS 中启用 AirPlay 流式传输和画中画播放等高级播放功能也需要此功能。
配置这些功能的最简单方法是使用 Xcode。在 Xcode 中选择应用程序的目标,然后选择 Capabilities 选项卡。在“功能”选项卡下,将“后台模式”开关设置为“开”,然后从可用模式列表中选择“音频、AirPlay 和画中画”选项。

本人是音乐爱好者,从小就特别喜欢那个随着音乐跳动的方框效果,就是这个:arduino上一大把对,我忍你很久了,我就想用mpy做,全网没有,行我自己研究。果然兴趣是最好的老师,我之前有篇博客专门讲音频,有兴趣的可以回顾一下。提到可视化频谱,必然绕不开fft,大学学过这玩意,当时一心玩,老师讲的一个字都么听进去,网上教程简略扫了一下,大该就是把时域转频域的工具,我大mpy居然没有fft函数,奶奶的,先放着。音频信息如何收集?第一种傻瓜式的ADC,模拟转数字,原始粗暴,第二种,I2S库,我之前博客有讲过,数据是PCM编码。然后又去学PCM编码,一学豁然开朗,舒服,以代码为例:audio_in=I2S
解决台式机麦克风不可用问题戴尔灵越3880最近因为需要开线上会议,发现戴尔台式机音频只有输出没有输入,也就是只能听见声音,无法输入声音。先后尝试了各种驱动安装更新之类的调试,无果。之后通过戴尔支持解决~这里多说一句,专业的就是专业,问题描述过去,直接给了解决方案,可能是他们遇到的相似问题比较多了,但也告诉我们,有些时候是可以通过这些官方服务解决问题的,比起自己折腾效率要高很多。那就记录一下吧~问题描述:电脑只能输出声音,不能输入声音。1、前提需要准备一只带麦克风的耳机,将耳机插入面板。2、先确定是否可以听到声音,可以通过播放歌曲或者视频。3、然后确认麦克风是否可用,可以通过调用win自带麦克风
以VSTiTriforce为例,由Tweakbench提供。当加载到市场上的任何VST主机时,它允许主机向VSTi发送(大概是MIDI)信号。然后VSTi将处理该信号并输出由VSTi内的软件乐器创建的合成音频。例如,将A4(我相信是MIDI音符)发送到VSTi会导致它合成高于中央C的A。它将音频数据发送回VST主机,然后它可以在我的扬声器上播放或将其保存为.wav或其他一些音频文件格式。假设我有Triforce,我正在尝试用我选择的语言编写一个程序,它可以通过发送要合成的A4纸条与VSTi交互,并自动将其保存到系统上的文件?最终,我希望能够解析整个单轨MIDI文件(使用已经可用于此
特性工作电压范围:6V-14V输出功率:7W(CLASSD,7.4V/4Ω,THD=10%)10W(CLASSD,9V/4Ω,THD=10%)18W(CLASSD,12V/4Ω,THD=10%)最高可达92%效率(12V/8Ω)电平设置工作模式无需输出滤波器差分输入优异的“上电,掉电”噪声抑制过流保护、过热保护、欠压保护 eSOP-8封装典型应用电路很简单:如下是本人的设计。 输入电阻:输入电阻主要是确定增益,即输出功率,所以一定要确定输入信号的幅度,喇叭的幅度,前后使用有效值计算。此设计搭配的喇叭是8R3W,额定功率3W,额定电压4.89V(有效值),最大功率4W。我们先确定输入信号的赋值,
做音频处理(虽然它也可以是图像处理)我有一个一维数字数组。(它们恰好是代表音频样本的16位有符号整数,这个问题同样适用于float或不同大小的整数。)为了匹配不同频率的音频(例如,将44.1kHz样本与22kHz样本混合),我需要拉伸(stretch)或压缩值数组以满足特定长度。将数组减半很简单:每隔一个样本丢弃一次。[231,8143,16341,2000,-9352,...]=>[231,16341,-9352,...]将数组宽度加倍稍微不那么简单:将每个条目加倍(或可选地在相邻的“真实”样本之间执行一些插值)。[231,8143,16341,2000,-9352,...]=>[2
我正在尝试实现一个具有两个输入channel和一个输出channel的ScriptProcessorNode。varsource=newArray(2);source[0]=context.createBufferSource();source[0].buffer=buffer[0];source[1]=context.createBufferSource();source[1].buffer=buffer[1];vartest=context.createScriptProcessor(4096,2,1);source[0].connect(test,0,0);source[1].c
我正在尝试在加载Javascriptaudio()对象时调用一个函数,但使用onload时它不起作用。myaud.onload=audioDone;但它正在使用image()对象。我怎样才能让它与audio()对象一起工作?谢谢 最佳答案 安元素有一组特定的事件称为mediaevents,和onload不是其中之一您可以使用canplaythrough检查音频是否已加载并可以播放。事件myaud.addEventListener('canplaythrough',audioDone,false);
我有一个音频元素varaudioSrc='https://mfbx9da4.github.io/assets/audio/dope-drum-loop_C_major.wav'varaudio=document.createElement('audio')audio.src=audioSrc我需要AudioBuffer做beatdetection所以我尝试在加载音频时访问缓冲区:audio.oncanplaythrough=()=>{console.info('loaded');varsource=context.createMediaElementSource(audio);sour
我有一个绑定(bind)到onClick事件的函数。它应该播放一首歌。如果有一首歌曲已经在播放,它应该停止当前歌曲并开始播放新歌曲。唯一的问题是,据我所知,只有一个pause方法,这意味着上一首歌曲将从暂停位置而不是开头继续播放。有什么办法解决这个问题(比如.stop()方法)吗?这是我的代码:varcurrSong="";functionplaySong(newSong){alert(newSong);if(newSong!=""){if(currSong!=""){document.getElementById(currSong).pause();}document.getElem
是否可以收听iframe中的youtube视频的音频,然后对其进行分析以用于基于网络音频api的可视化工具?从我的网站制作方式来看,我只能从iframe中获取源url。这是我的一个iframe的示例: 最佳答案 希望这对future的Google员工有所帮助。我发现这样做的唯一方法是使用音频流库(如节点的youtube-audio-stream)并从服务器端缓冲/传输音频。varexpress=require('express');varrouter=express.Router();varyoutubeStream=require