OSS--跨平臺的音頻接口簡介

來源:http://www.ibm.com/developerworks/cn/linux/l-ossapi/index.html

 

OSS--跨平臺的音頻接口簡介

 

級別: 初級

湯凱 ([email protected]),

2003 年 3 月 03 日

OSS(Open Sound System)是 unix 平臺上一個統一的音頻接口, 即只要音頻處理應用程序按照OSS的API來編寫,那麼在移植到另外一個平臺時,只需要重新編譯即可。

OSS(Open Sound System)是unix平臺上一個統一的音頻接口。以前,每個Unix廠商都會提供一個自己專有的API,用來處理音頻。這就意味着爲一種Unix平臺編寫的音頻處理應用程序,在移植到另外一種Unix平臺上時,必須要重寫。不僅如此,在一種平臺上具備的功能,可能在另外一個平臺上無法實現。但是,OSS出現以後情況就大不一樣了,只要音頻處理應用程序按照OSS的API來編寫,那麼在移植到另外一個平臺時,只需要重新編譯即可。因此,OSS提供了源代碼級的可移植性。

同時,很多的Unix工作站中,只能提供錄音與放音的功能。有了OSS後,給這些工作站帶來了MIDI功能,加上音頻流、語音識別/生成、計算機電話(CT)、JAVA以及其它的多媒體技術,在Unix工作站中,同樣可以享受到同Windows、Macintosh環境一樣的音頻世界。另外,OSS還提供了與視頻和動畫播放同步的音頻能力,這對在Unix中實現動畫、遊戲提供了幫助。

本文首先解釋在音頻編程時經常遇到的名詞、設備文件的含義,然後分別在錄音、播放、Mixer方面對OSS接口的使用方法進行介紹。由於OSS API十分豐富,因此在本文中只介紹那些最爲常用的接口。對於OSS API的一個完整描述,可以參考[1]。

一、基礎知識

數字音頻設備(有時也稱codec,PCM,DSP,ADC/DAC設備):播放或錄製數字化的聲音。它的指標主要有:採樣速率(電話爲8K,DVD爲96K)、channel數目(單聲道,立體聲)、採樣分辨率(8-bit,16-bit)。

mixer(混頻器):用來控制多個輸入、輸出的音量,也控制輸入(microphone,line-in,CD)之間的切換。

synthesizer(合成器):通過一些預先定義好的波形來合成聲音,有時用在遊戲中聲音效果的產生。

MIDI 接口:MIDI接口是爲了連接舞臺上的synthesizer、鍵盤、道具、燈光控制器的一種串行接口。

在Unix系統中,所有的設備都被統一成文件,通過對文件的訪問方式(首先open,然後read/write,同時可以使用ioctl讀取/設置參數,最後close)來訪問設備。在OSS中,主要有以下的幾種設備文件:

  • /dev/mixer:訪問聲卡中內置的mixer,調整音量大小,選擇音源。
  • /dev/sndstat:測試聲卡,執行cat /dev/sndstat會顯示聲卡驅動的信息。
  • /dev/dsp 、/dev/dspW、/dev/audio:讀這個設備就相當於錄音,寫這個設備就相當於放音。/dev/dsp與/dev/audio之間的區別在於採樣的編碼不同,/dev/audio使用μ律編碼,/dev/dsp使用8-bit(無符號)線性編碼,/dev/dspW使用16-bit(有符號)線形編碼。/dev/audio主要是爲了與SunOS兼容,所以儘量不要使用。
  • l /dev/sequencer:訪問聲卡內置的,或者連接在MIDI接口的synthesizer。

這些設備文件的設備編號見[1]。





回頁首

二、音頻編程

OSS爲音頻編程提供三種設備,分別是/dev/dsp,/dev/dspW和/dev/audio,前面已經提到了它們之間的區別。

用戶可以直接使用Unix的命令來放音和錄音,命令cat /dev/dsp >xyz可用來錄音,錄音的結果放在xyz文件中;命令cat xyz >/dev/dsp播放聲音文件xyz。

如果通過編程的方式來使用這些設備,那麼Unix平臺通過文件系統提供了統一的訪問接口。程序員可以通過文件的操作函數直接控制這些設備,這些操作函數包括:open、close、read、write、ioctl等。下面我們就分別討論打開音頻設備、放音、錄音和參數調整。

1. 打開音頻設備


1) 頭文件定義

/*
* Standard includes
*/
#include <ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>
/*
* Mandatory variables.
*/
#define BUF_SIZE 4096
int audio_fd;
unsigned char audio_buffer[BUF_SIZE];


2) 打開設備
if ((audio_fd = open(DEVICE_NAME, open_mode, 0)) == -1) {
/* Open of device failed */
perror(DEVICE_NAME);
exit(1);
}

open_mode有三種選擇:O_RDONLY,O_WRONLY和O_RDWR,分別表示只讀、只寫和讀寫。OSS建議儘量使用只讀或只寫,只有在全雙工的情況下(即錄音和放音同時)才使用讀寫模式。

2. 錄音

int len;
if ((len = read(audio_fd, audio_buffer, count)) == -1) {
perror("audio read");
exit(1);
}

count爲錄音數據的字節個數(建議爲2的指數),但不能超過audio_buffer的大小。從讀字節的個數可以精確的測量時間,例如8kHZ 16-bit stereo的速率爲8000*2*2=32000bytes/second,這是知道何時停止錄音的唯一方法。

3. 放音

放音實際上和錄音很類似,只不過把read改成write即可,相應的audio_buffer中爲音頻數據,count爲數據的長度。

注意,用戶始終要讀/寫一個完整的採樣。例如一個16-bit的立體聲模式下,每個採樣有4個字節,所以應用程序每次必須讀/寫4的倍數個字節。

另外,由於OSS是一個跨平臺的音頻接口,所以用戶在編程的時候,要考慮到可移植性的問題,其中一個重要的方面是讀/寫時的字節順序。

4. 設置參數

  • 設置採樣格式
    int format;
    format = AFMT_S16_LE;
    if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1) {
    /* fatal error */
    perror("SNDCTL_DSP_SETFMT");
    exit(1);
    }
    if (format != AFMT_S16_LE) {
    /* 本設備不支持選擇的採樣格式. */
    }
    在設置採樣格式之前,可以先測試設備能夠支持那些採樣格式,方法如下:
    int mask;
    if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
    /* Handle fatal error ... */
    }
    if (mask & AFMT_MPEG) {
    /* 本設備支持MPEG採樣格式 ... */}
    
  • 設置通道數目
    int channels = 2; /* 1=mono, 2=stereo */
    if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
    /* Fatal error */
    perror("SNDCTL_DSP_CHANNELS");
    exit(1);
    }
    if (channels != 2)
    {/* 本設備不支持立體聲模式 ... */}
    
  • 設置採樣速率
    int speed = 11025;
    if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1) {
    /* Fatal error */
    perror("SNDCTL_DSP_SPEED");
    exit(Error code);
    }
    if ( /* 返回的速率(即硬件支持的速率)與需要的速率差別很大... */ ) {
    /* 本設備不支持需要的速率... */
    }
    

音頻設備通過分頻的方法產生需要的採樣時鐘,因此不可能產生所有的頻率。驅動程序會計算出最接近要求的頻率來,用戶程序要檢查返回的速率值,如果誤差較小,可以忽略,但誤差不能太大。





回頁首

三、Mixer編程

對Mixer的控制,包括調節音量(volume)、選擇錄音音源(microphone,line-in)、查詢mixer的功能和狀態,主要是通過Mixer設備/dev/mixer的ioctl接口。相應的,ioctl接口提供的功能也分爲三類:調節音量、查詢mixer的能力、選擇mixer的錄音通道。下面就分別介紹使用的方法:

下面的mixer_fd是對mixer設備執行open操作返回的文件描述符。

  • 調節音量

    應用程序通過ioctl的SOUND_MIXER_READ和SOUND_MIXER_WIRTE功能號來讀取/設置音量。在OSS中,音量的大小範圍在0-100之間。使用方法如下:

    int vol;
    if (ioctl(mixer_fd, SOUND_MIXER_READ(SOUND_MIXER_MIC), &vol) == -1) {
    /* 訪問了沒有定義的mixer通道... */
    

    SOUND_MIXER_MIC是通道參數,表示讀microphone通道的音量,結果放置在vol中。如果通道是立體聲,那麼vol的最低有效字節爲左聲道的音量值,接着的字節爲右聲道的音量值,另外的兩個字節不用。如果通道是單聲道,vol中左聲道與右聲道具有相同的值。

  • 查詢mixer的能力

    int mask;
    if (ioctl(mixer_fd, SOUND_MIXER_READ_xxxx, &mask) == -1) {
    /* Mixer 的沒有此能力... */
    }
    

    SOUND_MIXER_READ_xxxx 中的xxxx代表具體要查詢的內容,比如檢查可用的mixer通道用SOUND_MIXER_READ_DEVMASK;檢查可用的錄音設備,用SOUND_MIXER_READ_RECMASK;檢查單聲道/立體聲,用SOUND_MIXER_READ_STEREODEVS;檢查mixer的一般能力,用SOUND_MIXER_READ_CAPS等等。所有通道的查詢的結果都放在mask中,所以要區分出特定通道的狀況,使用mask& (1 << channel_no)。

  • 選擇mixer的錄音通道

    首先可以通過SOUND_MIXER_READ_RECMASK檢查可用的錄音通道,然後通過SOUND_MIXER_WRITE_RECSRC選擇錄音通道。可以隨時通過SOUND_MIXER_READ_RECSRC查詢當前聲卡中已經被選擇的錄音通道。

    OSS建議把mixer的用戶控制功能單獨出來形成一個通用的程序。但前提是,在使用mixer之前,首先通過API的查詢功能檢查聲卡的能力。在linux中,就有一個專門的mixer程序--aumix。





回頁首

四、結束語

前面討論的是OSS中一些最基本的內容,實際上OSS中還有很多高級的特性,比如在音頻編程時十分重要的實時性問題,畫面與聲音的同步問題,這裏都沒有介紹。如果讀者對這些特性感興趣的話,可以進一步參考[1]。另外,在[2]中,還可以下載使用OSS接口的樣例程序。


參考資料

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章