# 22.9. `ossaudiodev` - 访问与OSS兼容的音频设备

此模块允许您访问OSS（开放声音系统）音频接口。OSS可用于广泛的开源和商业版本，是Linux和最新版本的FreeBSD的标准音频接口。

在版本3.3中更改：此模块中的操作现已引发`OSError`其中`IOError`被引发。

也可以看看

打开音响系统程序员指南
  OSS C API的官方文档

该模块定义了由OSS设备驱动程序提供的大量常量；请参阅`<sys/soundcard.h>`在Linux或FreeBSD上的列表。

`ossaudiodev`定义以下变量和函数：

exception `ossaudiodev.``OSSAudioError`

  对某些错误引发此异常。参数是一个描述错误的字符串。

  (If `ossaudiodev` receives an error from a system call such as `open()`, `write()`, or `ioctl()`, it raises `OSError`. 由`ossaudiodev`直接检测到的错误会导致`OSSAudioError`。）

  （为了向后兼容，异常类也可用作`ossaudiodev.error`。）

`ossaudiodev.``open`(mode)
`ossaudiodev.``open`(device, mode)

  打开音频设备并返回OSS音频设备对象。此对象支持许多类似文件的方法，例如`read()`，`write()`和`fileno()`在常规的Unix读/写语义和OSS音频设备的语义之间）。它还支持许多音频专用方法；请参阅下面的完整方法列表。

  设备是要使用的音频设备文件名。如果未指定，则此模块首先在环境变量 `AUDIODEV`中查找要使用的设备。如果未找到，它会返回到`/dev/dsp`。

  mode is one of `'r'` for read-only (record) access, `'w'` for write-only (playback) access and `'rw'` for both. 由于许多声卡只允许一个进程一次打开录音机或播放器，因此最好只为需要的活动打开设备。此外，一些声卡是半双工的：它们可以打开以进行读取或写入，但不能同时打开。

  注意不寻常的调用语法：第一参数是可选的，第二个是必需的。这是一个与旧的`linuxaudiodev`模块兼容的历史工件，`ossaudiodev`取代。

`ossaudiodev.``openmixer`([device])

  打开混音器设备并返回OSS混音器设备对象。设备是要使用的混合设备文件名。如果未指定，则此模块首先在环境变量 `MIXERDEV`中查找要使用的设备。如果找不到，它会回到`/dev/mixer`。

## 22.9.1. Audio Device Objects

在对音频设备进行写入或读取之前，必须按正确的顺序调用三种方法：

1. `setfmt()`设置输出格式
2. `channels()`设置通道数
3. `speed()`设置采样率

或者，您可以使用`setparameters()`方法同时设置所有三个音频参数。这更方便，但在所有情况下可能不那么灵活。

由`open()`返回的音频设备对象定义以下方法和（只读）属性：

`oss_audio_device.``close`()

  显式关闭音频设备。当您完成对音频设备的写入或读取时，应该明确地关闭它。闭合的设备不能再次使用。

`oss_audio_device.``fileno`()

  返回与设备关联的描述器。

`oss_audio_device.``read`(size)

  从音频输入读取size个字节，并将它们作为Python字符串返回。与大多数Unix设备驱动程序不同，处于阻塞模式的OSS音频设备（默认）会阻塞`read()`，直到所有请求的数据量都可用。

`oss_audio_device.``write`(data)

  向音频设备写入bytes-like object data并返回写入的字节数。如果音频设备处于阻塞模式（默认），则总是写入整个数据（同样，这与通常的Unix设备语义不同）。如果设备处于非阻塞模式，可能无法写入某些数据 - 请参阅`writeall()`。

  在版本3.5中已更改：可写入bytes-like object现已接受。

`oss_audio_device.``writeall`(data)

  Write a bytes-like object data to the audio device: waits until the audio device is able to accept data, writes as much data as it will accept, and repeats until data has been completely written. 如果器件处于阻塞模式（默认值），这与`write()`具有相同的效果； `writeall()`仅在非阻塞模式下有用。没有返回值，因为写入的数据量总是等于提供的数据量。

  在版本3.5中已更改：可写入bytes-like object现已接受。

在版本3.2中更改：音频设备对象也支持上下文管理协议，即它们可以在`with`语句中使用。

以下方法均映射到正好一个`ioctl()`系统调用。对应是显而易见的：例如，`setfmt()`对应于`SNDCTL_DSP_SETFMT` ioctl和`sync()`至`SNDCTL_DSP_SYNC` 如果底层`ioctl()`失败，它们都引发`OSError`。

`oss_audio_device.``nonblock`()

  将设备置于非阻塞模式。一旦处于非阻塞模式，就无法将其返回到阻塞模式。

`oss_audio_device.``getfmts`()

  返回声卡支持的音频输出格式的位掩码。OSS支持的一些格式如下：

  格式 | 描述
  --- | ---
  `AFMT_MU_LAW` | 对数编码（由Sun `.au`文件和`/dev/audio`使用）
  `AFMT_A_LAW` | 对数编码
  `AFMT_IMA_ADPCM` | 由交互式多媒体协会定义的4:1压缩格式
  `AFMT_U8` | 无符号，8位音频
  `AFMT_S16_LE` | 有符号，16位音频，小端字节顺序（由英特尔处理器使用）
  `AFMT_S16_BE` | 带符号，16位音频，大端字节顺序（由68k，PowerPC，Sparc使用）
  `AFMT_S8` | 有签名，8位音频
  `AFMT_U16_LE` | 无符号，16位小端音频
  `AFMT_U16_BE` | 无符号，16位大端音频

  有关音频格式的完整列表，请参阅OSS文档，并注意大多数设备仅支持这些格式的一部分。某些旧版设备只支持`AFMT_U8`；现在最常用的格式是`AFMT_S16_LE`。

`oss_audio_device.``setfmt`(format)

  尝试将当前音频格式设置为格式 - see `getfmts()`以获取列表。返回设备设置为的音频格式，可能不是请求的格式。也可以用于返回当前音频格式 - 通过传递`AFMT_QUERY`的“音频格式”执行此操作。

`oss_audio_device.``channels`(nchannels)

  将输出通道的数量设置为nchannels。值1表示单声道声音，2表示立体声。一些设备可能具有多于2个通道，并且一些高端设备可能不支持单声道。返回设备设置的通道数。

`oss_audio_device.``speed`(samplerate)

  尝试将音频采样率设置为每秒samplerate个样本。返回实际设置的速率。大多数声音设备不支持任意采样率。常用价格为：

  率 | 描述
  --- | ---
  8000 | `/dev/audio`的默认速率
  11025 | 语音记录
  22050 |
  44100 | CD质量音频（16位/样本和2通道）
  96000 | DVD质量音频（24位/采样）

`oss_audio_device.``sync`()

  等待声音设备播放其缓冲区中的每个字节。（这种情况在设备关闭时隐式发生。）OSS文档建议关闭并重新打开设备，而不要使用`sync()`。

`oss_audio_device.``reset`()

  立即停止播放或录制并将设备恢复到可以接受命令的状态。OSS文档建议在调用`reset()`后关闭并重新打开设备。

`oss_audio_device.``post`()

  告诉驾驶员输出可能有暂停，使得设备可以更智能地处理暂停。您可以在播放点音效之后，等待用户输入之前，或在执行磁盘I / O之前使用此功能。

以下方便方法组合几个ioctl或一个ioctl和一些简单的计算。

`oss_audio_device.``setparameters`(format, nchannels, samplerate[, strict=False])

  在一个方法调用中设置关键音频采样参数 - 采样格式，通道数和采样率。format, nchannels, and samplerate should be as specified in the `setfmt()`, `channels()`, and `speed()` methods. 如果严格为真，则`setparameters()`检查每个参数是否实际设置为请求的值，如果不是，则引发`OSSAudioError`。返回表示设备驱动程序实际设置的参数值的元组（格式，nchannels，samplerate）（即，返回值`setfmt()`，`channels()`和`speed()`）。

  例如，

      (fmt, channels, rate) = dsp.setparameters(fmt, channels, rate)

  相当于

      fmt = dsp.setfmt(fmt)
      channels = dsp.channels(channels)
      rate = dsp.rate(rate)

`oss_audio_device.``bufsize`()

  返回采样中硬件缓冲区的大小。

`oss_audio_device.``obufcount`()

  返回在硬件缓冲区中尚未播放的样本数。

`oss_audio_device.``obuffree`()

  返回可以排队进入硬件缓冲区以在无阻塞的情况下播放的样本数。

音频设备对象还支持几个只读属性：

`oss_audio_device.``closed`

  布尔值，表示设备是否已关闭。

`oss_audio_device.``name`

  包含设备文件名称的字符串。

`oss_audio_device.``mode`

  文件的I / O模式，`"r"`，`"rw"`或`"w"`。

## 22.9.2. Mixer Device Objects

混音器对象提供两个类文件方法：

`oss_mixer_device.``close`()

  此方法关闭打开的混音器设备文件。在此文件关闭后任何进一步尝试使用混合器将引发`OSError`。

`oss_mixer_device.``fileno`()

  返回打开的混音器设备文件的文件句柄号。

在版本3.2中更改：混合器对象也支持上下文管理协议。

其余的方法是特定于音频混合：

`oss_mixer_device.``controls`()

  此方法返回指定可用混频器控制的位掩码（“Control”是特定可混频“通道”，例如`SOUND_MIXER_PCM`或`SOUND_MIXER_SYNTH`）。该位掩码指示所有可用混频器控制的子集 - 在模块级定义的`SOUND_MIXER_*`常量。要确定例如当前混音器对象是否支持PCM混音器，请使用以下Python代码：

      mixer=ossaudiodev.openmixer()
      if mixer.controls() & (1 << ossaudiodev.SOUND_MIXER_PCM):
          # PCM is supported
          ... code ...

  对于大多数用途，`SOUND_MIXER_VOLUME`（主音量）和`SOUND_MIXER_PCM`控制应该足够了 - 但是当选择混频器控制时，使用混频器的代码应该是灵活的。例如，在Gravis Ultrasound上，`SOUND_MIXER_VOLUME`不存在。

`oss_mixer_device.``stereocontrols`()

  返回指示立体声混音器控制的位掩码。如果一个位被置位，则相应的控制是立体声；如果未设置，则控制是单声道的或不受混频器支持（与`controls()`组合使用以确定哪个）。

  有关从位掩码获取数据的示例，请参阅`controls()`函数的代码示例。

`oss_mixer_device.``reccontrols`()

  返回指定可用于记录的混音器控制的位掩码。有关从位掩码读取的示例，请参阅`controls()`的代码示例。

`oss_mixer_device.``get`(control)

  返回给定混频器控制的音量。返回的卷是2元组`(left_volume,right_volume)`。卷指定为从0（无声）到100（全卷）的数字。如果控制是单声道，仍然返回2元组，但是两个卷是相同的。

  如果指定了无效控件，则引发`OSSAudioError`，如果指定了不支持的控件，则引发`OSError`。

`oss_mixer_device.``set`(control, (left, right))

  将给定混频器控制的音量设置为`(left,right)`。`left`和`right`必须为int，介于0（无声）和100（全音量）之间。成功后，新卷将作为2元组返回。请注意，这可能与指定的音量不完全相同，因为某些声卡的混音器的分辨率有限。

  如果指定了无效的混合器控件或指定的卷超出范围，则引发`OSSAudioError`。

`oss_mixer_device.``get_recsrc`()

  此方法返回位掩码，指示当前正在使用哪些控制作为记录源。

`oss_mixer_device.``set_recsrc`(bitmask)

  调用此函数指定记录源。如果成功，返回指示新记录源（或多个源）的位掩码；如果指定了无效的源，则引发`OSError`。要将当前录音来源设置为麦克风输入：

      mixer.setrecsrc (1 << ossaudiodev.SOUND_MIXER_MIC)