ALSA 上的 OSS 音序器模擬

Copyright (c) 1998,1999 by Takashi Iwai

ver.0.1.8; Nov. 16, 1999

描述

此目錄包含 ALSA 上的 OSS 音序器模擬驅動程式。請注意,此程式仍處於開發狀態。

它的作用 - 它提供 OSS 音序器的模擬,透過 /dev/sequencer/dev/music 裝置進行訪問。如果準備了合適的 ALSA 音序器,則大多數使用 OSS 的應用程式都可以執行。

此驅動程式模擬以下功能

  • 普通音序器和 MIDI 事件

    它們被轉換為 ALSA 音序器事件,併發送到相應的埠。

  • 定時器事件

    定時器不能透過 ioctl 選擇。控制速率固定為 100,與 HZ 無關。也就是說,即使在 Alpha 系統上,一個滴答也總是 1/100 秒。可以在 /dev/music 中更改基本速率和速度。

  • 補丁載入

    它純粹取決於合成器驅動程式是否支援,因為補丁載入是透過回撥到合成器驅動程式實現的。

  • I/O 控制

    大多數控制都被接受。一些控制依賴於合成器驅動程式,甚至依賴於原始 OSS。

此外,您還可以找到以下高階功能

  • 更好的佇列機制

    事件在處理之前被排隊。

  • 多個應用程式

    您可以同時執行兩個或多個應用程式(甚至對於 OSS 音序器)!但是,每個 MIDI 裝置都是獨佔的 - 也就是說,如果一個 MIDI 裝置被某個應用程式開啟一次,其他應用程式就不能使用它。合成器裝置沒有這樣的限制。

  • 即時事件處理

    事件可以即時處理,無需使用越界 ioctl。要切換到即時模式,請傳送 ABSTIME 0 事件。隨後的事件將以即時方式處理,無需排隊。要關閉即時模式,請傳送 RELTIME 0 事件。

  • /proc 介面

    可以透過 /proc/asound/seq/oss 隨時顯示應用程式和裝置的狀態。在以後的版本中,配置也將透過 /proc 介面更改。

安裝

執行配置指令碼,同時啟用音序器支援 (--with-sequencer=yes) 和 OSS 模擬 (--with-oss=yes) 選項。將建立一個模組 snd-seq-oss.o。如果您的音效卡的合成器模組支援 OSS 模擬(目前只有 Emu8000 驅動程式),則會自動載入此模組。否則,您需要手動載入此模組。

一開始,此模組會探測所有已連線到音序器的 MIDI 埠。之後,埠的建立和刪除將由 ALSA 音序器的通知機制監控。

可在 proc 介面中找到可用的合成器和 MIDI 裝置。執行 cat /proc/asound/seq/oss,並檢查裝置。例如,如果您使用 AWE64 卡,您將看到如下內容

OSS sequencer emulation version 0.1.8
ALSA client number 63
ALSA receiver port 0

Number of applications: 0

Number of synth devices: 1
synth 0: [EMU8000]
  type 0x1 : subtype 0x20 : voices 32
  capabilities : ioctl enabled / load_patch enabled

Number of MIDI devices: 3
midi 0: [Emu8000 Port-0] ALSA port 65:0
  capability write / opened none

midi 1: [Emu8000 Port-1] ALSA port 65:1
  capability write / opened none

midi 2: [0: MPU-401 (UART)] ALSA port 64:0
  capability read/write / opened none

請注意,裝置編號可能與 /proc/asound/oss-devices 或原始 OSS 驅動程式中的資訊不同。使用 /proc/asound/seq/oss 中列出的裝置編號,透過 OSS 音序器模擬進行播放。

使用合成器裝置

執行您喜歡的程式。我測試了 playmidi-2.4、awemidi-0.4.3、gmod-3.1 和 xmp-1.1.5。您還可以透過 /dev/sequencer 載入取樣,如 sfxload。

如果底層驅動程式支援對合成器裝置進行多次訪問(如 Emu8000 驅動程式),則允許同時執行兩個或多個應用程式。

使用 MIDI 裝置

到目前為止,只測試了 MIDI 輸出。完全沒有檢查 MIDI 輸入,但希望它能工作。使用 /proc/asound/seq/oss 中列出的裝置編號。請注意,這些數字大多與 /proc/asound/oss-devices 中的列表不同。

模組選項

可以使用以下模組選項

maxqlen

指定最大讀/寫佇列長度。此佇列是 OSS 音序器私有的,因此它獨立於 ALSA 音序器的佇列長度。預設值為 1024。

seq_oss_debug

指定除錯級別,並接受零(= 無除錯訊息)或正整數。預設值為 0。

佇列機制

OSS 音序器模擬使用 ALSA 優先順序佇列。來自 /dev/sequencer 的事件被處理並放入模組選項指定的佇列中。

所有來自 /dev/sequencer 的事件都在開始時被解析。定時事件也在此時被解析,以便事件可以即時處理。傳送事件 ABSTIME 0 會將操作模式切換到即時模式,傳送事件 RELTIME 0 會關閉它。在即時模式下,所有事件都會立即分發。

排隊的事件在 ALSA 音序器排程程式安排的時間之後被分發到相應的 ALSA 音序器埠。

如果寫入佇列已滿,則應用程式會休眠,直到一定數量(預設為一半)在阻塞模式下變空。還實現了寫入定時的同步。

來自 MIDI 裝置的輸入或回聲事件儲存在讀取 FIFO 佇列中。如果應用程式在阻塞模式下讀取 /dev/sequencer,則該程序將被喚醒。

合成器裝置介面

註冊

要註冊 OSS 合成器裝置,請使用 snd_seq_oss_synth_register() 函式

int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
        snd_seq_oss_callback_t *oper, void *private_data)

引數 nametypesubtypenvoices 用於建立用於 ioctl 的適當 synth_info 結構。返回值是此裝置的索引號。必須記住此索引以進行登出。如果註冊失敗,將返回 -errno。

要釋放此裝置,請呼叫 snd_seq_oss_synth_unregister() 函式

int snd_seq_oss_synth_unregister(int index)

其中 index 是註冊函式返回的索引號。

回撥

OSS 合成器裝置具有采樣下載和 ioctl(如取樣重置)的功能。在 OSS 模擬中,這些特殊功能透過使用回撥來實現。註冊引數 oper 用於指定這些回撥。必須定義以下回調函式

snd_seq_oss_callback_t:
 int (*open)(snd_seq_oss_arg_t *p, void *closure);
 int (*close)(snd_seq_oss_arg_t *p);
 int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
 int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
 int (*reset)(snd_seq_oss_arg_t *p);

除了 openclose 回撥之外,允許它們為 NULL。

每個回撥函式都採用引數型別 snd_seq_oss_arg_t 作為第一個引數。

struct snd_seq_oss_arg_t {
    int app_index;
    int file_mode;
    int seq_mode;
    snd_seq_addr_t addr;
    void *private_data;
    int event_passing;
};

前三個欄位,app_indexfile_modeseq_mode 由 OSS 音序器初始化。app_index 是應用程式索引,對於每個開啟 OSS 音序器的應用程式都是唯一的。file_mode 是指示檔案操作模式的位標誌。有關其含義,請參閱 seq_oss.hseq_mode 是音序器操作模式。在當前版本中,僅使用 SND_OSSSEQ_MODE_SYNTH

接下來的兩個欄位,addrprivate_data,必須由合成器驅動程式在打開回調時填充。addr 包含分配給此裝置的 ALSA 音序器埠的地址。如果驅動程式為 private_data 分配了記憶體,則必須在關閉回撥中自行釋放。

最後一個欄位 event_passing 指示如何翻譯音符開/關事件。在 PROCESS_EVENTS 模式下,音符 255 被視為速度變化,並且關鍵壓力事件被傳遞到埠。在 PASS_EVENTS 模式下,所有音符開/關事件都未經修改地傳遞到埠。PROCESS_KEYPRESS 模式檢查高於 128 的音符,並將其視為關鍵壓力事件(主要用於 Emu8000 驅動程式)。

打開回調

每次使用 OSS 音序器的應用程式開啟此裝置時,都會呼叫 open。這不能為 NULL。通常,打開回調執行以下過程

  1. 分配私有資料記錄。

  2. 建立一個 ALSA 音序器埠。

  3. arg->addr 上設定新的埠地址。

  4. arg->private_data 上設定私有資料記錄指標。

請注意,此合成器埠的 port_info 中的型別位標誌不能包含 TYPE_MIDI_GENERIC 位。相反,應使用 TYPE_SPECIFIC。此外,也不應包含 CAP_SUBSCRIPTION 位。這對於將其與其他普通 MIDI 裝置區分開來是必要的。如果開啟過程成功,則返回零。否則,返回 -errno。

Ioctl 回撥

當音序器接收到特定於裝置的 ioctl 時,會呼叫 ioctl 回撥。以下兩個 ioctl 應由此回撥處理

IOCTL_SEQ_RESET_SAMPLES

重置記憶體中的所有采樣 -- 返回 0

IOCTL_SYNTH_MEMAVL

返回可用記憶體大小

FM_4OP_ENABLE

通常可以忽略

其他 ioctl 在音序器內部處理,而不傳遞到底層驅動程式。

Load_Patch 回撥

load_patch 回撥用於取樣下載。此回撥必須讀取使用者空間上的資料並傳輸到每個裝置。如果成功,則返回 0,如果失敗,則返回 -errno。format 引數是 patch_info 記錄中的補丁鍵。buf 是使用者空間指標,其中儲存了 patch_info 記錄。offs 可以忽略。count 是此取樣資料的總資料大小。

關閉回撥

當應用程式關閉此裝置時,會呼叫 close 回撥。如果在打開回調中分配了任何私有資料,則必須在關閉回撥中釋放它。ALSA 埠的刪除也應在此處完成。此回撥不能為 NULL。

重置回撥

當應用程式重置或關閉音序器裝置時,會呼叫 reset 回撥。回撥應立即關閉相關埠上的聲音,並初始化埠的狀態。如果未定義此回撥,則 OSS seq 會向埠傳送一個 HEARTBEAT 事件。

事件

大多數事件都由音序器處理並轉換為適當的 ALSA 音序器事件,以便每個合成器裝置可以透過 ALSA 音序器埠的 input_event 回撥接收。驅動程式應實現以下 ALSA 事件

ALSA 事件

原始 OSS 事件

NOTEON

SEQ_NOTEON, MIDI_NOTEON

NOTE

SEQ_NOTEOFF, MIDI_NOTEOFF

KEYPRESS

MIDI_KEY_PRESSURE

CHANPRESS

SEQ_AFTERTOUCH, MIDI_CHN_PRESSURE

PGMCHANGE

SEQ_PGMCHANGE, MIDI_PGM_CHANGE

PITCHBEND

SEQ_CONTROLLER(CTRL_PITCH_BENDER), MIDI_PITCH_BEND

CONTROLLER

MIDI_CTL_CHANGE, SEQ_BALANCE (與 CTL_PAN 一起)

CONTROL14

SEQ_CONTROLLER

REGPARAM

SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)

SYSEX

SEQ_SYSEX

這些行為中的大多數可以透過 Emu8000 底層驅動程式中包含的 MIDI 模擬驅動程式來實現。在未來的版本中,此模組將是獨立的。

一些 OSS 事件(SEQ_PRIVATESEQ_VOLUME 事件)作為事件型別 SND_SEQ_OSS_PRIVATE 傳遞。OSS 音序器傳遞這些事件 8 位元組資料包,不做任何修改。底層驅動程式應適當處理這些事件。

MIDI 裝置介面

由於 OSS 模擬透過接收來自 ALSA 音序器的通知來自動探測 ALSA MIDI 音序器埠的建立和刪除,因此 MIDI 裝置不需要像合成器裝置那樣顯式註冊。但是,註冊到 ALSA 音序器的 MIDI port_info 必須包含組名 SND_SEQ_GROUP_DEVICE 和 capability-bit CAP_READCAP_WRITE。此外,還必須定義訂閱功能 CAP_SUBS_READCAP_SUBS_WRITE。如果未滿足這些條件,則該埠不會註冊為 OSS 音序器 MIDI 裝置。

透過 MIDI 裝置的事件在 OSS 音序器中解析並轉換為相應的 ALSA 音序器事件。來自 MIDI 音序器的輸入也由 OSS 音序器轉換為 MIDI 位元組事件。這與 seq_midi 模組的工作方式相反。

已知問題/待辦事項

  • 尚未實現透過 ALSA 樂器層載入補丁。