音频会话

音频会话是 WASAPI 客户端可以进行统一管理的一组相关的音频流。 客户端可以控制每个会话的音量水平和静音状态。 系统会将客户端指定的音量和静音设置统一应用于会话中的所有流。

在客户端初始化音频流时,它会将音频流分配给音频会话。 有关详细信息,请参阅 IAudioClient::Initialize

音频会话包含呈现流或捕获流,但不会同时包含这两种流。 默认情况下,呈现会话的音量和静音设置会在系统重启时保持不变。 捕获会话的音量和静音设置不会持续生效。 (包含以环回模式运行的流的会话与捕获会话的处理方式相同。也就是说,会话设置不会持久生效。有关环回模式的详细信息,请参阅环回录制。)

每个音频流都正好属于一个会话。 客户端在初始化音频流对象时,会将音频流分配给特定的会话。 流在其生命周期内一直都具有会话的成员身份。 在创建流对象后,该对象会一直存在,直到客户端释放对该对象的最后一个计数引用,然后该对象才会被删除。

虽然客户端无法更改已分配给现有流的会话,但可以通过删除流(释放对它的所有引用)、创建新的流来取代已删除的流并将新的流分配给另一个会话来达到类似的效果。

每个呈现会话都代表构成全局混合流的一个子集,该混合流会通过特定的音频终结点设备来播放。 全局组合会将共享设备的所有应用程序的所有会话合并到一起。

通常情况下,拥有多个流的应用程序会将所有流分配给同一个会话。 但是,应用程序可以选择将不同的流分配给不同的会话。 应用程序未明确分配给会话的任何流都属于默认会话。

典型的音频应用程序应避免修改会话的音量和静音设置。 相反,用户通过控制程序的用户界面来控制这些设置。 例如,在 Windows Vista 中,系统提供的程序 Sndvol.exe 会为系统中每个活动或最近活动的呈现会话显示音量控件和静音控件。 通过这些控件,用户可以调整系统中所有会话的音量和静音设置。

Sndvol 程序目前只会显示音频呈现终结点设备的音量控制。 它不会显示音频采集设备的音量控件。

如果会话包含一个或多个处于活动状态的流,则该会话就处于活动状态。 活动状态的流将处于运行状态。 非活动状态的流将处于停止状态。 当第一个流处于活动状态时,会话即会进入活动状态。 当会话的最后一个活动流变为非活动状态时,该会话就会变为非活动状态。 当会话处于非活动状态一段时间后,系统就会将会话状态从非活动状态更改为已过期。

Sndvol 会显示所有活动和非活动状态呈现会话的音量和静音控制。 当会话状态从非活动状态变为过期或会话终止时,Sndvol 会删除会话的音量和静音控件。 (当最后一个流被删除时,会话即告终止;也就是说,当客户端释放会话中最后一个剩余流对象的最终引用计数时,会话即告终止)。系统通知声音是此规则的一个例外。 Sndvol 会始终显示系统通知声音的音量和静音控件,而与这些声音的会话状态无关。

通常情况下,流属于一个会话,该会话只跨越包含创建流的应用程序的进程。 不过,应用程序可以选择定义跨进程会话,将两个或多个进程的流结合起来。

WASAPI 支持跨进程会话的主要目的在于:

  • Sndvol 程序可为用户提供单一音量控件,以管理所有应用程序的系统通知声音。
  • 在一个进程中运行的媒体播放器可以将受保护的内容流式传输给在另一个进程中运行的解密程序。

与特定进程呈现会话的控件设置类似,跨进程呈现会话的控件设置在默认情况下也会在系统重启时保持不变。 WASAPI 提供这种行为主要是为了系统通知声音,因为当应用程序组合随时间变化时,系统通知声音必须保留用户的音量和静音设置。

Sndvol 程序会为每个会话的音量控件标上显示名称和图标。 客户端可以选择为会话明确指定显示名称和图标。 如果客户端没有提供这些项目,则 Sndvol 将显示默认名称和默认图标。 默认名称包含应用程序窗口标题等信息。 默认图标是应用程序窗口的图标。 只有在特定流程会话的情况下,这些默认值才能为用户提供有意义的信息。 请注意,一个跨进程会话可以与多个应用程序相关联。 在这种情况下,只有客户端提供的显示名称和图标才有意义。

虽然,呈现会话的音量和静音设置默认情况下会在系统重启时保持不变,但客户端提供的显示名称和图标却不会发生变化。 为确保 Sndvol 显示客户端提供的名称和图标,客户端必须在为会话分配第一个流时,为会话明确分配名称和图标。 系统只保留会话的显示名称和图标,直到会话终止。

每个会话都由一个会话 GUID 标识。 客户端在打开流时,会将该流分配给一个特定的会话。 客户端提供以下两条信息来标识会话:

  • 一个会话 GUID。
  • 会话是跨进程会话还是特定进程会话 — 特定进程会话只包含客户进程的流。

这些信息足以将特定会话与同一台计算机中的所有其他会话区分开来。 进程特定会话的会话 GUID 仅在拥有该会话的进程范围内唯一标识该会话。 相比之下,跨进程会话的会话 GUID 在计算机上运行的所有进程范围内都是唯一的。

如果是特定于进程的会话,系统会使用会话 GUID 和进程 ID 的组合来唯一标识计算机范围内的会话。 因此,如果两个不同进程中的客户端将各自的流分配给具有相同会话 GUID 的两个特定进程会话,系统会将这些会话视为不同的会话,因为它们的进程 ID 不同。 此外,如果跨进程会话与一个或多个特定进程会话使用相同的会话 GUID,即使它们共享相同的会话 GUID,系统也会将跨进程会话与特定进程会话区别对待。

例如,在 Windows Vista 中,Windows 多媒体 waveOutXxx 函数和 DirectSound 等高级 API 通常会将其创建的音频流分配给默认的特定于进程的会话,这些会话由会话 GUID 值 GUID_NULL 标识。 对于这些 API 的客户端而言,每个客户端进程的默认会话与其他客户端进程的默认会话是分开的,即使这些会话的会话 GUID 相同。 此外,如果一个或多个应用程序将流分配给由会话 GUID 值 GUID_NULL 标识的跨进程会话,则系统会将此跨进程会话与共享相同会话 GUID 的默认特定进程会话分开处理。 因此,Sndvol 程序会为每个客户端的默认进程特定会话显示单独的音量控件,如果存在会话 GUID 值 GUID_NULL,它还会为跨进程会话显示额外的音量控件。

每个会话只与一个音频终结点设备相关联。 如果两个会话的会话 GUID 和进程 ID 相同,但与不同的设备相关联,则系统会将这两个会话视为不同的设备。 一个会话永远不可能同时包含捕获流和呈现流,因为捕获流只能与捕获设备相关联,而呈现流只能与呈现设备相关联。

如前所述,会话的音量和静音设置会在系统重启时持续生效。 应用程序的两个或多个实例可以创建具有相同会话 GUID 的特定进程会话。 通过 Sndvol 程序,用户可以为每个会话选择不同的音量和静音设置。 这些会话终止后,系统只保留其中一个会话的控件设置,即最后一个终止的会话。 之后,如果应用程序的新实例创建了一个进程特定会话,其会话 GUID 与之前的相同,该会话就会继承之前保存的音量和静音设置。

应用程序不应尝试向另一个无关应用程序拥有的会话添加流或控制其音量水平。 此外,应用程序不应尝试控制通知声音的系统管理会话音量水平。 不过,应用程序可以通过调用 PlaySound 函数,以便通过系统会话来播放通知声音。 有关详细信息,请参阅传统音频应用程序的通知声音

应用程序可以注册,以便在会话状态发生变化时接收通知。 有关详细信息,请参阅音频会话事件

在极少数情况下,创建特定于进程的会话的应用程序可能需要将两个或多个应用程序实例的特定于进程的会话控制合并到 Sndvol 中的单个音量控件下。 有关详细信息,请参阅分组参数

编程指南