"ossaudiodev"  --- 访问兼容OSS的音频设备
****************************************

======================================================================

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

3.3 版更變: 此模块中过去会引发 "IOError" 的操作现在将引发 "OSError"。

也參考:

  开放之声系统程序员手册
     OSS C API 的官方文档

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

"ossaudiodev" 定义了下列变量和函数:

exception ossaudiodev.OSSAudioError

   此异常会针对特定错误被引发。 其参数为一个描述错误信息的字符串。

   （如果 "ossaudiodev" 从系统调用例如 "open()", "write()" 或
   "ioctl()" 接收到错误，它将引发 "OSError"。 由 "ossaudiodev" 直接检
   测到的错误将引发 "OSSAudioError"。）

   （为了向下兼容，此异常类也可通过 "ossaudiodev.error" 访问。）

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

   打开一个音频设备并返回 OSS 音频设备对象。 此对象支持许多文件类方法
   ，例如 "read()", "write()" 和 "fileno()" (不过传统的 Unix 读/写语义
   与 OSS 音频设备的存在一些细微的差异)。 它还支持一些音频专属的方法；
   完整的方法列表见下文。

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

   *mode* 可以为 "'r'" 表示只读（录音）访问，"'w'" 表示只写（回放）访
   问以及 "'rw'" 表示同时读写。 由于许多声卡在同一时间只允许单个进程打
   开录音机或播放器，因此好的做法是只根据活动的需要打开设备。 并且，有
   些声卡是半双工的：它们可以被打开用于读取或写入，但不能同时读写。

   请注意这里特殊的调用语法: *first* 参数是可选的，而第二个参数则是必
   需的。 这是出于历史原因要与 "ossaudiodev" 所替代的 "linuxaudiodev"
   模块保持兼容。

ossaudiodev.openmixer([device])

   打开一个混音设备并返回 OSS 混音设备对象。 *device* 是要使用的混音设
   备文件名。 如果未指定，则此模块会先在环境变量 "MIXERDEV" 中查找要使
   用的设备。 如果未找到，它将回退为 "/dev/mixer"。


音频设备对象
============

在你写入或读取音频设备之前，你必须按照正确的顺序调用三个方法:

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 版更變: 现在支持可写的 *字节类对象*。

oss_audio_device.writeall(data)

   将一个 *bytes-like object* *data* 写入音频设备：等待直到音频设备能
   够接收数据，将根据其所能接收的数据量尽可能多地写入，并重复操作直至
   *data* 被完全写入。 如果设备处于阻塞模式（默认），则其效果与
   "write()" 相同；"writeall()" 仅适用于非阻塞模式。 它没有返回值，因
   为写入的数据量总是等于所提供的数据量。

   3.5 版更變: 现在支持可写的 *字节类对象*。

3.2 版更變: 音频设备对象还支持上下文管理协议，就是说它们可以在 "with"
语句中使用。

下列方法各自映射一个 "ioctl()" 系统调用。 对应关系很明显：例如，
"setfmt()" 对应 "SNDCTL_DSP_SETFMT" ioctl，而 "sync()" 对应
"SNDCTL_DSP_SYNC" (这在查阅 OSS 文档时很有用)。 如果下层的 "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 压缩格式，由 Interactive Multimedia  |
   |                           | Association 定义                              |
   +---------------------------+-----------------------------------------------+
   | "AFMT_U8"                 | 无符号的 8 位音频                             |
   +---------------------------+-----------------------------------------------+
   | "AFMT_S16_LE"             | Signed, 16-bit audio, little-endian byte      |
   |                           | order (as used by Intel processors)           |
   +---------------------------+-----------------------------------------------+
   | "AFMT_S16_BE"             | Signed, 16-bit audio, big-endian byte order   |
   |                           | (as used by 68k, PowerPC, Sparc)              |
   +---------------------------+-----------------------------------------------+
   | "AFMT_S8"                 | Signed, 8 bit audio                           |
   +---------------------------+-----------------------------------------------+
   | "AFMT_U16_LE"             | Unsigned, 16-bit little-endian audio          |
   +---------------------------+-----------------------------------------------+
   | "AFMT_U16_BE"             | Unsigned, 16-bit big-endian audio             |
   +---------------------------+-----------------------------------------------+

   Consult the OSS documentation for a full list of audio formats, and
   note that most devices support only a subset of these formats.
   Some older devices only support "AFMT_U8"; the most common format
   used today is "AFMT_S16_LE".

oss_audio_device.setfmt(format)

   Try to set the current audio format to *format*---see "getfmts()"
   for a list.  Returns the audio format that the device was set to,
   which may not be the requested format.  May also be used to return
   the current audio format---do this by passing an "audio format" of
   "AFMT_QUERY".

oss_audio_device.channels(nchannels)

   Set the number of output channels to *nchannels*.  A value of 1
   indicates monophonic sound, 2 stereophonic.  Some devices may have
   more than 2 channels, and some high-end devices may not support
   mono. Returns the number of channels the device was set to.

oss_audio_device.speed(samplerate)

   Try to set the audio sampling rate to *samplerate* samples per
   second.  Returns the rate actually set.  Most sound devices don't
   support arbitrary sampling rates.  Common rates are:

   +---------+---------------------------------------------+
   | 采样率  | 描述                                        |
   |=========|=============================================|
   | 8000    | "/dev/audio" 的默认采样率                   |
   +---------+---------------------------------------------+
   | 11025   | 语音录音                                    |
   +---------+---------------------------------------------+
   | 22050   |                                             |
   +---------+---------------------------------------------+
   | 44100   | CD品质的音频（16位采样和2通道）             |
   +---------+---------------------------------------------+
   | 96000   | DVD品质的音频（24位采样）                   |
   +---------+---------------------------------------------+

oss_audio_device.sync()

   Wait until the sound device has played every byte in its buffer.
   (This happens implicitly when the device is closed.)  The OSS
   documentation recommends closing and re-opening the device rather
   than using "sync()".

oss_audio_device.reset()

   Immediately stop playing or recording and return the device to a
   state where it can accept commands.  The OSS documentation
   recommends closing and re-opening the device after calling
   "reset()".

oss_audio_device.post()

   Tell the driver that there is likely to be a pause in the output,
   making it possible for the device to handle the pause more
   intelligently.  You might use this after playing a spot sound
   effect, before waiting for user input, or before doing disk I/O.

The following convenience methods combine several ioctls, or one ioctl
and some simple calculations.

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

   Set the key audio sampling parameters---sample format, number of
   channels, and sampling rate---in one method call.  *format*,
   *nchannels*, and *samplerate* should be as specified in the
   "setfmt()", "channels()", and "speed()"  methods.  If *strict* is
   true, "setparameters()" checks to see if each parameter was
   actually set to the requested value, and raises "OSSAudioError" if
   not.  Returns a tuple (*format*, *nchannels*, *samplerate*)
   indicating the parameter values that were actually set by the
   device driver (i.e., the same as the return values of "setfmt()",
   "channels()", and "speed()").

   For example,

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

   is equivalent to

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

oss_audio_device.bufsize()

   Returns the size of the hardware buffer, in samples.

oss_audio_device.obufcount()

   Returns the number of samples that are in the hardware buffer yet
   to be played.

oss_audio_device.obuffree()

   Returns the number of samples that could be queued into the
   hardware buffer to be played without blocking.

Audio device objects also support several read-only attributes:

oss_audio_device.closed

   Boolean indicating whether the device has been closed.

oss_audio_device.name

   String containing the name of the device file.

oss_audio_device.mode

   The I/O mode for the file, either ""r"", ""rw"", or ""w"".


Mixer Device Objects
====================

The mixer object provides two file-like methods:

oss_mixer_device.close()

   This method closes the open mixer device file.  Any further
   attempts to use the mixer after this file is closed will raise an
   "OSError".

oss_mixer_device.fileno()

   Returns the file handle number of the open mixer device file.

3.2 版更變: Mixer objects also support the context management
protocol.

The remaining methods are specific to audio mixing:

oss_mixer_device.controls()

   This method returns a bitmask specifying the available mixer
   controls ("Control" being a specific mixable "channel", such as
   "SOUND_MIXER_PCM" or "SOUND_MIXER_SYNTH").  This bitmask indicates
   a subset of all available mixer controls---the "SOUND_MIXER_*"
   constants defined at module level. To determine if, for example,
   the current mixer object supports a PCM mixer, use the following
   Python code:

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

   For most purposes, the "SOUND_MIXER_VOLUME" (master volume) and
   "SOUND_MIXER_PCM" controls should suffice---but code that uses the
   mixer should be flexible when it comes to choosing mixer controls.
   On the Gravis Ultrasound, for example, "SOUND_MIXER_VOLUME" does
   not exist.

oss_mixer_device.stereocontrols()

   Returns a bitmask indicating stereo mixer controls.  If a bit is
   set, the corresponding control is stereo; if it is unset, the
   control is either monophonic or not supported by the mixer (use in
   combination with "controls()" to determine which).

   See the code example for the "controls()" function for an example
   of getting data from a bitmask.

oss_mixer_device.reccontrols()

   Returns a bitmask specifying the mixer controls that may be used to
   record.  See the code example for "controls()" for an example of
   reading from a bitmask.

oss_mixer_device.get(control)

   Returns the volume of a given mixer control.  The returned volume
   is a 2-tuple "(left_volume,right_volume)".  Volumes are specified
   as numbers from 0 (silent) to 100 (full volume).  If the control is
   monophonic, a 2-tuple is still returned, but both volumes are the
   same.

   Raises "OSSAudioError" if an invalid control is specified, or
   "OSError" if an unsupported control is specified.

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

   Sets the volume for a given mixer control to "(left,right)". "left"
   and "right" must be ints and between 0 (silent) and 100 (full
   volume).  On success, the new volume is returned as a 2-tuple. Note
   that this may not be exactly the same as the volume specified,
   because of the limited resolution of some soundcard's mixers.

   Raises "OSSAudioError" if an invalid mixer control was specified,
   or if the specified volumes were out-of-range.

oss_mixer_device.get_recsrc()

   This method returns a bitmask indicating which control(s) are
   currently being used as a recording source.

oss_mixer_device.set_recsrc(bitmask)

   Call this function to specify a recording source.  Returns a
   bitmask indicating the new recording source (or sources) if
   successful; raises "OSError" if an invalid source was specified.
   To set the current recording source to the microphone input:

      mixer.setrecsrc (1 << ossaudiodev.SOUND_MIXER_MIC)
