← Documents Documentation/sound/designs/seq-oss.rst GitHub 원문 ↗

Linux 6.18.37 · Sound

ALSA의 OSS 시퀀서 에뮬레이션

ALSA의 OSS sequencer 호환 계층이 event·timer·queue·MIDI port를 처리하는 방식과 synth driver 등록 함수, callback ABI, OSS→ALSA event 변환 규칙을 설명합니다.

Source pathDocumentation/sound/designs/seq-oss.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

seq-oss.rst:1-371

ALSA의 OSS sequencer 호환 계층이 event·timer·queue·MIDI port를 처리하는 방식과 synth driver 등록 함수, callback ABI, OSS→ALSA event 변환 규칙을 설명합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ===============================
2 OSS Sequencer Emulation on ALSA
3 ===============================
4
5 Copyright (c) 1998,1999 by Takashi Iwai
6
7 ver.0.1.8; Nov. 16, 1999
8
9 Description
10 ===========
11
12 This directory contains the OSS sequencer emulation driver on ALSA. Note
13 that this program is still in the development state.
14
15 What this does - it provides the emulation of the OSS sequencer, access
16 via ``/dev/sequencer`` and ``/dev/music`` devices.
17 The most of applications using OSS can run if the appropriate ALSA
18 sequencer is prepared.
19
20 The following features are emulated by this driver:
21
22 * Normal sequencer and MIDI events:
23
24 They are converted to the ALSA sequencer events, and sent to the
25 corresponding port.
26
27 * Timer events:
28
29 The timer is not selectable by ioctl. The control rate is fixed to
30 100 regardless of HZ. That is, even on Alpha system, a tick is always
31 1/100 second. The base rate and tempo can be changed in ``/dev/music``.
32
33 * Patch loading:
34
35 It purely depends on the synth drivers whether it's supported since
36 the patch loading is realized by callback to the synth driver.
37
38 * I/O controls:
39
40 Most of controls are accepted. Some controls
41 are dependent on the synth driver, as well as even on original OSS.
42
43 Furthermore, you can find the following advanced features:
44
45 * Better queue mechanism:
46
47 The events are queued before processing them.
48
49 * Multiple applications:
50
51 You can run two or more applications simultaneously (even for OSS
52 sequencer)!
53 However, each MIDI device is exclusive - that is, if a MIDI device
54 is opened once by some application, other applications can't use
55 it. No such a restriction in synth devices.
56
57 * Real-time event processing:
58
59 The events can be processed in real time without using out of bound
60 ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
61 events will be processed in real-time without queued. To switch off the
62 real-time mode, send RELTIME 0 event.
63
64 * ``/proc`` interface:
65
66 The status of applications and devices can be shown via
67 ``/proc/asound/seq/oss`` at any time. In the later version,
68 configuration will be changed via ``/proc`` interface, too.
69
70
71 Installation
72 ============
73
74 Run configure script with both sequencer support (``--with-sequencer=yes``)
75 and OSS emulation (``--with-oss=yes``) options. A module ``snd-seq-oss.o``
76 will be created. If the synth module of your sound card supports for OSS
77 emulation (so far, only Emu8000 driver), this module will be loaded
78 automatically.
79 Otherwise, you need to load this module manually.
80
81 At beginning, this module probes all the MIDI ports which have been
82 already connected to the sequencer. Once after that, the creation and deletion
83 of ports are watched by announcement mechanism of ALSA sequencer.
84
85 The available synth and MIDI devices can be found in proc interface.
86 Run ``cat /proc/asound/seq/oss``, and check the devices. For example,
87 if you use an AWE64 card, you'll see like the following:
88 ::
89
90 OSS sequencer emulation version 0.1.8
91 ALSA client number 63
92 ALSA receiver port 0
93
94 Number of applications: 0
95
96 Number of synth devices: 1
97 synth 0: [EMU8000]
98 type 0x1 : subtype 0x20 : voices 32
99 capabilities : ioctl enabled / load_patch enabled
100
101 Number of MIDI devices: 3
102 midi 0: [Emu8000 Port-0] ALSA port 65:0
103 capability write / opened none
104
105 midi 1: [Emu8000 Port-1] ALSA port 65:1
106 capability write / opened none
107
108 midi 2: [0: MPU-401 (UART)] ALSA port 64:0
109 capability read/write / opened none
110
111 Note that the device number may be different from the information of
112 ``/proc/asound/oss-devices`` or ones of the original OSS driver.
113 Use the device number listed in ``/proc/asound/seq/oss``
114 to play via OSS sequencer emulation.
115
116 Using Synthesizer Devices
117 =========================
118
119 Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
120 and xmp-1.1.5. You can load samples via ``/dev/sequencer`` like sfxload,
121 too.
122
123 If the lowlevel driver supports multiple access to synth devices (like
124 Emu8000 driver), two or more applications are allowed to run at the same
125 time.
126
127 Using MIDI Devices
128 ==================
129
130 So far, only MIDI output was tested. MIDI input was not checked at all,
131 but hopefully it will work. Use the device number listed in
132 ``/proc/asound/seq/oss``.
133 Be aware that these numbers are mostly different from the list in
134 ``/proc/asound/oss-devices``.
135
136 Module Options
137 ==============
138
139 The following module options are available:
140
141 maxqlen
142 specifies the maximum read/write queue length. This queue is private
143 for OSS sequencer, so that it is independent from the queue length of ALSA
144 sequencer. Default value is 1024.
145
146 seq_oss_debug
147 specifies the debug level and accepts zero (= no debug message) or
148 positive integer. Default value is 0.
149
150 Queue Mechanism
151 ===============
152
153 OSS sequencer emulation uses an ALSA priority queue. The
154 events from ``/dev/sequencer`` are processed and put onto the queue
155 specified by module option.
156
157 All the events from ``/dev/sequencer`` are parsed at beginning.
158 The timing events are also parsed at this moment, so that the events may
159 be processed in real-time. Sending an event ABSTIME 0 switches the operation
160 mode to real-time mode, and sending an event RELTIME 0 switches it off.
161 In the real-time mode, all events are dispatched immediately.
162
163 The queued events are dispatched to the corresponding ALSA sequencer
164 ports after scheduled time by ALSA sequencer dispatcher.
165
166 If the write-queue is full, the application sleeps until a certain amount
167 (as default one half) becomes empty in blocking mode. The synchronization
168 to write timing was implemented, too.
169
170 The input from MIDI devices or echo-back events are stored on read FIFO
171 queue. If application reads ``/dev/sequencer`` in blocking mode, the
172 process will be awaked.
173
174 Interface to Synthesizer Device
175 ===============================
176
177 Registration
178 ------------
179
180 To register an OSS synthesizer device, use snd_seq_oss_synth_register()
181 function:
182 ::
183
184 int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
185 snd_seq_oss_callback_t *oper, void *private_data)
186
187 The arguments ``name``, ``type``, ``subtype`` and ``nvoices``
188 are used for making the appropriate synth_info structure for ioctl. The
189 return value is an index number of this device. This index must be remembered
190 for unregister. If registration is failed, -errno will be returned.
191
192 To release this device, call snd_seq_oss_synth_unregister() function:
193 ::
194
195 int snd_seq_oss_synth_unregister(int index)
196
197 where the ``index`` is the index number returned by register function.
198
199 Callbacks
200 ---------
201
202 OSS synthesizer devices have capability for sample downloading and ioctls
203 like sample reset. In OSS emulation, these special features are realized
204 by using callbacks. The registration argument oper is used to specify these
205 callbacks. The following callback functions must be defined:
206 ::
207
208 snd_seq_oss_callback_t:
209 int (*open)(snd_seq_oss_arg_t *p, void *closure);
210 int (*close)(snd_seq_oss_arg_t *p);
211 int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
212 int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
213 int (*reset)(snd_seq_oss_arg_t *p);
214
215 Except for ``open`` and ``close`` callbacks, they are allowed to be NULL.
216
217 Each callback function takes the argument type ``snd_seq_oss_arg_t`` as the
218 first argument.
219 ::
220
221 struct snd_seq_oss_arg_t {
222 int app_index;
223 int file_mode;
224 int seq_mode;
225 snd_seq_addr_t addr;
226 void *private_data;
227 int event_passing;
228 };
229
230 The first three fields, ``app_index``, ``file_mode`` and ``seq_mode``
231 are initialized by OSS sequencer. The ``app_index`` is the application
232 index which is unique to each application opening OSS sequencer. The
233 ``file_mode`` is bit-flags indicating the file operation mode. See
234 ``seq_oss.h`` for its meaning. The ``seq_mode`` is sequencer operation
235 mode. In the current version, only ``SND_OSSSEQ_MODE_SYNTH`` is used.
236
237 The next two fields, ``addr`` and ``private_data``, must be
238 filled by the synth driver at open callback. The ``addr`` contains
239 the address of ALSA sequencer port which is assigned to this device. If
240 the driver allocates memory for ``private_data``, it must be released
241 in close callback by itself.
242
243 The last field, ``event_passing``, indicates how to translate note-on
244 / off events. In ``PROCESS_EVENTS`` mode, the note 255 is regarded
245 as velocity change, and key pressure event is passed to the port. In
246 ``PASS_EVENTS`` mode, all note on/off events are passed to the port
247 without modified. ``PROCESS_KEYPRESS`` mode checks the note above 128
248 and regards it as key pressure event (mainly for Emu8000 driver).
249
250 Open Callback
251 -------------
252
253 The ``open`` is called at each time this device is opened by an application
254 using OSS sequencer. This must not be NULL. Typically, the open callback
255 does the following procedure:
256
257 #. Allocate private data record.
258 #. Create an ALSA sequencer port.
259 #. Set the new port address on ``arg->addr``.
260 #. Set the private data record pointer on ``arg->private_data``.
261
262 Note that the type bit-flags in port_info of this synth port must NOT contain
263 ``TYPE_MIDI_GENERIC``
264 bit. Instead, ``TYPE_SPECIFIC`` should be used. Also, ``CAP_SUBSCRIPTION``
265 bit should NOT be included, too. This is necessary to tell it from other
266 normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
267 return -errno.
268
269 Ioctl Callback
270 --------------
271
272 The ``ioctl`` callback is called when the sequencer receives device-specific
273 ioctls. The following two ioctls should be processed by this callback:
274
275 IOCTL_SEQ_RESET_SAMPLES
276 reset all samples on memory -- return 0
277
278 IOCTL_SYNTH_MEMAVL
279 return the available memory size
280
281 FM_4OP_ENABLE
282 can be ignored usually
283
284 The other ioctls are processed inside the sequencer without passing to
285 the lowlevel driver.
286
287 Load_Patch Callback
288 -------------------
289
290 The ``load_patch`` callback is used for sample-downloading. This callback
291 must read the data on user-space and transfer to each device. Return 0
292 if succeeded, and -errno if failed. The format argument is the patch key
293 in patch_info record. The buf is user-space pointer where patch_info record
294 is stored. The offs can be ignored. The count is total data size of this
295 sample data.
296
297 Close Callback
298 --------------
299
300 The ``close`` callback is called when this device is closed by the
301 application. If any private data was allocated in open callback, it must
302 be released in the close callback. The deletion of ALSA port should be
303 done here, too. This callback must not be NULL.
304
305 Reset Callback
306 --------------
307
308 The ``reset`` callback is called when sequencer device is reset or
309 closed by applications. The callback should turn off the sounds on the
310 relevant port immediately, and initialize the status of the port. If this
311 callback is undefined, OSS seq sends a ``HEARTBEAT`` event to the
312 port.
313
314 Events
315 ======
316
317 Most of the events are processed by sequencer and translated to the adequate
318 ALSA sequencer events, so that each synth device can receive by input_event
319 callback of ALSA sequencer port. The following ALSA events should be
320 implemented by the driver:
321
322 ============= ===================
323 ALSA event Original OSS events
324 ============= ===================
325 NOTEON SEQ_NOTEON, MIDI_NOTEON
326 NOTE SEQ_NOTEOFF, MIDI_NOTEOFF
327 KEYPRESS MIDI_KEY_PRESSURE
328 CHANPRESS SEQ_AFTERTOUCH, MIDI_CHN_PRESSURE
329 PGMCHANGE SEQ_PGMCHANGE, MIDI_PGM_CHANGE
330 PITCHBEND SEQ_CONTROLLER(CTRL_PITCH_BENDER),
331 MIDI_PITCH_BEND
332 CONTROLLER MIDI_CTL_CHANGE,
333 SEQ_BALANCE (with CTL_PAN)
334 CONTROL14 SEQ_CONTROLLER
335 REGPARAM SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)
336 SYSEX SEQ_SYSEX
337 ============= ===================
338
339 The most of these behavior can be realized by MIDI emulation driver
340 included in the Emu8000 lowlevel driver. In the future release, this module
341 will be independent.
342
343 Some OSS events (``SEQ_PRIVATE`` and ``SEQ_VOLUME`` events) are passed as event
344 type SND_SEQ_OSS_PRIVATE. The OSS sequencer passes these event 8 byte
345 packets without any modification. The lowlevel driver should process these
346 events appropriately.
347
348 Interface to MIDI Device
349 ========================
350
351 Since the OSS emulation probes the creation and deletion of ALSA MIDI
352 sequencer ports automatically by receiving announcement from ALSA
353 sequencer, the MIDI devices don't need to be registered explicitly
354 like synth devices.
355 However, the MIDI port_info registered to ALSA sequencer must include
356 a group name ``SND_SEQ_GROUP_DEVICE`` and a capability-bit
357 ``CAP_READ`` or ``CAP_WRITE``. Also, subscription capabilities,
358 ``CAP_SUBS_READ`` or ``CAP_SUBS_WRITE``, must be defined, too. If
359 these conditions are not satisfied, the port is not registered as OSS
360 sequencer MIDI device.
361
362 The events via MIDI devices are parsed in OSS sequencer and converted
363 to the corresponding ALSA sequencer events. The input from MIDI sequencer
364 is also converted to MIDI byte events by OSS sequencer. This works just
365 a reverse way of seq_midi module.
366
367 Known Problems / TODO's
368 =======================
369
370 * Patch loading via ALSA instrument layer is not implemented yet.
371
372

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

에뮬레이션 범위와 확장 기능

1-69

이 문서는 Takashi Iwai가 1998~1999년에 작성한 ALSA OSS sequencer emulation driver 버전 0.1.8 설명이다. 문서 작성 당시 프로그램은 개발 중인 상태였으며 `/dev/sequencer`와 `/dev/music` 장치를 통해 OSS sequencer를 에뮬레이션했다. 적절한 ALSA sequencer가 준비되어 있으면 대부분의 OSS 애플리케이션을 실행할 수 있다.

일반 sequencer와 MIDI event는 ALSA sequencer event로 변환되어 대응 port로 전달된다. Timer는 ioctl로 선택할 수 없고 control rate는 `HZ`와 무관하게 100으로 고정되어 tick 하나가 항상 1/100초다. `/dev/music`에서는 base rate와 tempo를 바꿀 수 있다.

Patch loading은 synth driver callback으로 구현되므로 지원 여부가 synth driver에 달려 있다. 대부분의 I/O control은 받아들이지만 일부 control은 원래 OSS와 마찬가지로 synth driver에 종속된다.

Event는 처리 전에 queue에 들어가며 두 개 이상의 애플리케이션을 동시에 실행할 수 있다. 다만 MIDI 장치는 한 애플리케이션이 열면 다른 애플리케이션이 사용할 수 없는 exclusive 장치다. Synth 장치에는 이 제한이 없다.

Out-of-band ioctl 없이 real-time 처리가 가능하다. `ABSTIME 0` event를 보내면 이후 event를 queue하지 않고 실시간 처리하며, `RELTIME 0` event를 보내면 real-time mode를 끈다.

애플리케이션과 장치 상태는 언제든 `/proc/asound/seq/oss`에서 볼 수 있다. 문서는 향후 버전에서 이 proc interface로 구성도 바꿀 수 있게 될 것이라고 설명한다.

OSS sequencer 에뮬레이션 기능
기능동작/제약
Normal/MIDI eventALSA sequencer event로 변환
Timer100 Hz 고정, /dev/music에서 base rate·tempo 조정
Patch loadingsynth driver callback 의존
I/O control대부분 지원, 일부 driver 의존
Queue처리 전 우선순위 queue
Multiple apps가능, 단 MIDI 장치는 exclusive
Real-timeABSTIME 0으로 시작, RELTIME 0으로 종료
상태 조회/proc/asound/seq/oss

기본 OSS 동작과 ALSA 계층이 제공하는 확장 동작을 구분한다.

===============================
OSS Sequencer Emulation on ALSA
===============================

Copyright (c) 1998,1999 by Takashi Iwai

ver.0.1.8; Nov. 16, 1999

Description
===========

This directory contains the OSS sequencer emulation driver on ALSA. Note
that this program is still in the development state.

What this does - it provides the emulation of the OSS sequencer, access
via ``/dev/sequencer`` and ``/dev/music`` devices.
The most of applications using OSS can run if the appropriate ALSA
sequencer is prepared.

The following features are emulated by this driver:

* Normal sequencer and MIDI events:

    They are converted to the ALSA sequencer events, and sent to the
    corresponding port.

* Timer events:

    The timer is not selectable by ioctl. The control rate is fixed to
    100 regardless of HZ. That is, even on Alpha system, a tick is always
    1/100 second. The base rate and tempo can be changed in ``/dev/music``.

* Patch loading:

    It purely depends on the synth drivers whether it's supported since
    the patch loading is realized by callback to the synth driver.

* I/O controls:

    Most of controls are accepted. Some controls
    are dependent on the synth driver, as well as even on original OSS.

Furthermore, you can find the following advanced features:

* Better queue mechanism:

    The events are queued before processing them.

* Multiple applications:

    You can run two or more applications simultaneously (even for OSS
    sequencer)!
    However, each MIDI device is exclusive - that is, if a MIDI device
    is opened once by some application, other applications can't use
    it. No such a restriction in synth devices.

* Real-time event processing:

    The events can be processed in real time without using out of bound
    ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
    events will be processed in real-time without queued. To switch off the
    real-time mode, send RELTIME 0 event.

* ``/proc`` interface:

    The status of applications and devices can be shown via
    ``/proc/asound/seq/oss`` at any time. In the later version,
    configuration will be changed via ``/proc`` interface, too.

설치, port 감시와 장치 번호

70-115

빌드 시 configure script에 sequencer 지원 `--with-sequencer=yes`와 OSS emulation `--with-oss=yes`를 모두 지정하면 `snd-seq-oss.o` 모듈이 생성된다. Sound card의 synth 모듈이 OSS emulation을 지원하면 문서 작성 당시 Emu8000처럼 자동 적재되고, 그렇지 않으면 수동으로 적재해야 한다.

모듈은 시작할 때 이미 sequencer에 연결된 모든 MIDI port를 probe한다. 그 뒤에는 ALSA sequencer announcement mechanism으로 port 생성과 삭제를 감시한다.

사용 가능한 synth와 MIDI 장치는 `cat /proc/asound/seq/oss`로 확인한다. 출력에는 emulation 버전, ALSA client/receiver port, 애플리케이션 수, synth type·subtype·voice·capability, MIDI 장치의 ALSA port·입출력 capability·open 상태가 포함된다.

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 driver의 번호와 다를 수 있다. OSS sequencer emulation으로 재생할 때는 반드시 `/proc/asound/seq/oss`에 표시된 번호를 사용한다.

OSS sequencer 장치 발견
snd-seq-oss 적재기존 MIDI port 전체 probe/proc/asound/seq/oss에 번호 부여
ALSA port 생성/삭제announcement 수신OSS MIDI 장치 목록 갱신

초기 probe 이후에는 announcement로 port 수명 주기를 추적한다.


Installation
============

Run configure script with both sequencer support (``--with-sequencer=yes``)
and OSS emulation (``--with-oss=yes``) options. A module ``snd-seq-oss.o``
will be created. If the synth module of your sound card supports for OSS
emulation (so far, only Emu8000 driver), this module will be loaded
automatically.
Otherwise, you need to load this module manually.

At beginning, this module probes all the MIDI ports which have been
already connected to the sequencer. Once after that, the creation and deletion
of ports are watched by announcement mechanism of ALSA sequencer.

The available synth and MIDI devices can be found in proc interface.
Run ``cat /proc/asound/seq/oss``, and check the devices. For example,
if you use an AWE64 card, you'll see like the following:
::

    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

Note that the device number may be different from the information of
``/proc/asound/oss-devices`` or ones of the original OSS driver.
Use the device number listed in ``/proc/asound/seq/oss``
to play via OSS sequencer emulation.

Synth·MIDI 사용과 모듈 옵션

116-149

Synth 장치는 일반 OSS 프로그램으로 사용할 수 있다. 문서는 `playmidi-2.4`, `awemidi-0.4.3`, `gmod-3.1`, `xmp-1.1.5`를 시험했으며 `sfxload`처럼 `/dev/sequencer`를 통해 sample도 적재할 수 있다고 설명한다.

Emu8000처럼 low-level driver가 synth 장치의 multiple access를 지원하면 둘 이상의 애플리케이션을 동시에 실행할 수 있다.

문서 작성 시점에는 MIDI output만 시험했고 input은 확인하지 않았다. MIDI를 사용할 때는 `/proc/asound/seq/oss`의 장치 번호를 사용해야 하며 이 번호는 대개 `/proc/asound/oss-devices` 목록과 다르다.

`maxqlen`은 OSS sequencer 전용 read/write queue 최대 길이를 지정한다. ALSA sequencer queue 길이와 독립적이며 기본값은 1024다. `seq_oss_debug`는 debug level로 0이면 메시지를 끄고 양의 정수면 해당 level을 사용하며 기본값은 0이다.

snd-seq-oss 모듈 옵션
옵션의미기본값
maxqlenOSS read/write queue 최대 길이1024
seq_oss_debug0 또는 양의 debug level0

OSS 전용 queue와 debug 출력의 한계를 조정한다.

Using Synthesizer Devices
=========================

Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
and xmp-1.1.5. You can load samples via ``/dev/sequencer`` like sfxload,
too.

If the lowlevel driver supports multiple access to synth devices (like
Emu8000 driver), two or more applications are allowed to run at the same
time.

Using MIDI Devices
==================

So far, only MIDI output was tested. MIDI input was not checked at all,
but hopefully it will work. Use the device number listed in
``/proc/asound/seq/oss``.
Be aware that these numbers are mostly different from the list in
``/proc/asound/oss-devices``.

Module Options
==============

The following module options are available:

maxqlen
  specifies the maximum read/write queue length. This queue is private
  for OSS sequencer, so that it is independent from the queue length of ALSA
  sequencer. Default value is 1024.

seq_oss_debug
  specifies the debug level and accepts zero (= no debug message) or
  positive integer. Default value is 0.

Queue와 real-time 처리

150-173

OSS sequencer emulation은 ALSA priority queue를 사용한다. `/dev/sequencer`의 event를 먼저 parse한 뒤 모듈 옵션으로 지정한 queue에 넣는다. Timing event도 처음에 parse하므로 실시간 처리가 가능하다.

`ABSTIME 0`을 보내면 real-time mode로 전환되어 모든 event가 즉시 dispatch되고, `RELTIME 0`을 보내면 이를 끈다. Queue에 들어간 event는 예약 시간이 지난 뒤 ALSA sequencer dispatcher가 대응 port로 보낸다.

Write queue가 가득 찬 blocking mode에서는 기본적으로 절반이 빌 때까지 애플리케이션이 sleep한다. Write timing 동기화도 구현되어 있다. MIDI input이나 echo-back event는 read FIFO에 저장되며, 애플리케이션이 `/dev/sequencer`를 blocking read 중이면 process를 깨운다.

OSS event queue
/dev/sequencer event초기 parsepriority queue예약 시간ALSA port dispatch
ABSTIME 0real-time mode즉시 dispatch
RELTIME 0queued mode 복귀
MIDI input/echoread FIFOblocking reader wake-up

일반 예약 처리와 ABSTIME/RELTIME 실시간 전환을 나타낸다.

Queue Mechanism
===============

OSS sequencer emulation uses an ALSA priority queue. The
events from ``/dev/sequencer`` are processed and put onto the queue
specified by module option.

All the events from ``/dev/sequencer`` are parsed at beginning.
The timing events are also parsed at this moment, so that the events may
be processed in real-time. Sending an event ABSTIME 0 switches the operation
mode to real-time mode, and sending an event RELTIME 0 switches it off.
In the real-time mode, all events are dispatched immediately.

The queued events are dispatched to the corresponding ALSA sequencer
ports after scheduled time by ALSA sequencer dispatcher.

If the write-queue is full, the application sleeps until a certain amount
(as default one half) becomes empty in blocking mode. The synchronization
to write timing was implemented, too.

The input from MIDI devices or echo-back events are stored on read FIFO
queue. If application reads ``/dev/sequencer`` in blocking mode, the
process will be awaked.

OSS synth 장치 등록과 해제

174-198

OSS synthesizer 장치를 등록하려면 `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)

`name`, `type`, `subtype`, `nvoices`는 ioctl용 `synth_info` 구조체를 구성하는 데 사용된다. 성공하면 장치 index를 반환하며 해제할 때 필요하므로 저장해야 한다. 등록 실패 시 `-errno`를 반환한다.

장치를 해제할 때는 등록 함수가 반환한 index로 `snd_seq_oss_synth_unregister()`를 호출한다.

int snd_seq_oss_synth_unregister(int index)
OSS synth 등록 수명 주기
name/type/subtype/nvoicessnd_seq_oss_synth_registerindex 반환장치 사용snd_seq_oss_synth_unregister(index)

등록 index가 ioctl 정보와 해제의 식별자가 된다.

Interface to Synthesizer Device
===============================

Registration
------------

To register an OSS synthesizer device, use snd_seq_oss_synth_register()
function:
::

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

The arguments ``name``, ``type``, ``subtype`` and ``nvoices``
are used for making the appropriate synth_info structure for ioctl. The
return value is an index number of this device. This index must be remembered
for unregister. If registration is failed, -errno will be returned.

To release this device, call snd_seq_oss_synth_unregister() function:
::

  int snd_seq_oss_synth_unregister(int index)

where the ``index`` is the index number returned by register function.

Callback ABI와 snd_seq_oss_arg_t

199-249

OSS synthesizer는 sample download와 sample reset 같은 ioctl capability를 가진다. 에뮬레이션은 등록 인수 `oper`에 지정한 callback으로 이 기능을 구현한다. `open`과 `close`는 필수이며 나머지는 `NULL`일 수 있다.

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);

각 callback의 첫 인수는 `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_index`, `file_mode`, `seq_mode`는 OSS sequencer가 초기화한다. `app_index`는 OSS sequencer를 연 애플리케이션마다 고유하고, `file_mode`는 file operation mode bit flag이며 의미는 `seq_oss.h`에 있다. 현재 `seq_mode`에는 `SND_OSSSEQ_MODE_SYNTH`만 사용한다.

`addr`와 `private_data`는 synth driver가 open callback에서 채운다. `addr`는 장치에 할당된 ALSA sequencer port 주소다. Driver가 `private_data` 메모리를 할당했다면 close callback에서 직접 해제해야 한다.

`event_passing`은 note-on/off 변환 방식을 정한다. `PROCESS_EVENTS`에서는 note 255를 velocity change로 보고 key pressure를 port로 보낸다. `PASS_EVENTS`는 모든 note on/off를 수정 없이 전달한다. `PROCESS_KEYPRESS`는 note 128 초과를 key pressure로 간주하며 주로 Emu8000 driver용이다.

snd_seq_oss_arg_t field
Field설정 주체의미
app_indexOSS sequencer애플리케이션 고유 index
file_modeOSS sequencerfile operation bit flags
seq_modeOSS sequencer현재 SND_OSSSEQ_MODE_SYNTH
addrsynth open callbackALSA sequencer port 주소
private_datasynth open callbackdriver 전용 data
event_passingdrivernote/key pressure 변환 방식

초기화 주체와 의미를 구분한다.

Callbacks
---------

OSS synthesizer devices have capability for sample downloading and ioctls
like sample reset. In OSS emulation, these special features are realized
by using callbacks. The registration argument oper is used to specify these
callbacks. The following callback functions must be defined:
::

  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);

Except for ``open`` and ``close`` callbacks, they are allowed to be NULL.

Each callback function takes the argument type ``snd_seq_oss_arg_t`` as the
first argument.
::

  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;
  };

The first three fields, ``app_index``, ``file_mode`` and ``seq_mode``
are initialized by OSS sequencer. The ``app_index`` is the application
index which is unique to each application opening OSS sequencer. The
``file_mode`` is bit-flags indicating the file operation mode. See
``seq_oss.h`` for its meaning. The ``seq_mode`` is sequencer operation
mode. In the current version, only ``SND_OSSSEQ_MODE_SYNTH`` is used.

The next two fields, ``addr`` and ``private_data``, must be
filled by the synth driver at open callback. The ``addr`` contains
the address of ALSA sequencer port which is assigned to this device. If
the driver allocates memory for ``private_data``, it must be released
in close callback by itself.

The last field, ``event_passing``, indicates how to translate note-on
/ off events. In ``PROCESS_EVENTS`` mode, the note 255 is regarded
as velocity change, and key pressure event is passed to the port. In
``PASS_EVENTS`` mode, all note on/off events are passed to the port
without modified. ``PROCESS_KEYPRESS`` mode checks the note above 128
and regards it as key pressure event (mainly for Emu8000 driver).

Open callback과 port capability 규칙

250-268

`open` callback은 애플리케이션이 OSS sequencer로 이 장치를 열 때마다 호출되며 `NULL`일 수 없다. 일반적으로 private data record를 할당하고 ALSA sequencer port를 만든 뒤 새 port 주소를 `arg->addr`, private data pointer를 `arg->private_data`에 기록한다.

이 synth port의 `port_info` type bit flag에는 `TYPE_MIDI_GENERIC`을 넣으면 안 되고 대신 `TYPE_SPECIFIC`을 사용해야 한다. `CAP_SUBSCRIPTION`도 포함하면 안 된다. 일반 MIDI 장치와 구별하기 위한 규칙이다.

Open 절차가 성공하면 0, 실패하면 `-errno`를 반환한다.

Synth open callback
open 호출private data 할당ALSA port 생성arg->addr 설정arg->private_data 설정0 반환
port_infoTYPE_SPECIFICTYPE_MIDI_GENERIC 제외CAP_SUBSCRIPTION 제외

필수 자원 준비와 port 식별 규칙을 순서대로 적용한다.

Open Callback
-------------

The ``open`` is called at each time this device is opened by an application
using OSS sequencer. This must not be NULL. Typically, the open callback
does the following procedure:

#. Allocate private data record.
#. Create an ALSA sequencer port.
#. Set the new port address on ``arg->addr``.
#. Set the private data record pointer on ``arg->private_data``.

Note that the type bit-flags in port_info of this synth port must NOT contain
``TYPE_MIDI_GENERIC``
bit. Instead, ``TYPE_SPECIFIC`` should be used. Also, ``CAP_SUBSCRIPTION``
bit should NOT be included, too. This is necessary to tell it from other
normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
return -errno.

Ioctl, patch, close와 reset callback

269-313

`ioctl` callback은 sequencer가 장치 고유 ioctl을 받았을 때 호출된다. `IOCTL_SEQ_RESET_SAMPLES`는 memory의 모든 sample을 reset하고 0을 반환해야 한다. `IOCTL_SYNTH_MEMAVL`은 사용 가능한 memory 크기를 반환한다. `FM_4OP_ENABLE`은 보통 무시할 수 있다. 다른 ioctl은 low-level driver로 전달하지 않고 sequencer 내부에서 처리한다.

`load_patch`는 sample download에 사용한다. User space의 data를 읽어 각 장치로 전송하고 성공 시 0, 실패 시 `-errno`를 반환한다. `format`은 `patch_info` record의 patch key, `buf`는 그 record가 저장된 user-space pointer, `count`는 sample data 전체 크기다. `offs`는 무시할 수 있다.

필수 `close` callback은 애플리케이션이 장치를 닫을 때 호출된다. Open에서 할당한 private data를 해제하고 ALSA port도 여기서 삭제해야 한다.

`reset`은 애플리케이션이 sequencer 장치를 reset하거나 닫을 때 호출된다. 관련 port의 sound를 즉시 끄고 port 상태를 초기화해야 한다. Callback이 정의되지 않으면 OSS sequencer가 port로 `HEARTBEAT` event를 보낸다.

Synth callback 반환과 책임
Callback책임반환/대체
ioctlRESET_SAMPLES, SYNTH_MEMAVL, FM_4OP_ENABLE명령별 값
load_patchuser sample을 장치로 전송0 / -errno
closeprivate data 해제, ALSA port 삭제필수
resetsound off, port 초기화미정의 시 HEARTBEAT

각 callback이 처리해야 하는 자원과 결과다.

Ioctl Callback
--------------

The ``ioctl`` callback is called when the sequencer receives device-specific
ioctls. The following two ioctls should be processed by this callback:

IOCTL_SEQ_RESET_SAMPLES
    reset all samples on memory -- return 0

IOCTL_SYNTH_MEMAVL
    return the available memory size

FM_4OP_ENABLE
    can be ignored usually

The other ioctls are processed inside the sequencer without passing to
the lowlevel driver.

Load_Patch Callback
-------------------

The ``load_patch`` callback is used for sample-downloading. This callback
must read the data on user-space and transfer to each device. Return 0
if succeeded, and -errno if failed. The format argument is the patch key
in patch_info record. The buf is user-space pointer where patch_info record
is stored. The offs can be ignored. The count is total data size of this
sample data.

Close Callback
--------------

The ``close`` callback is called when this device is closed by the
application. If any private data was allocated in open callback, it must
be released in the close callback. The deletion of ALSA port should be
done here, too. This callback must not be NULL.

Reset Callback
--------------

The ``reset`` callback is called when sequencer device is reset or
closed by applications. The callback should turn off the sounds on the
relevant port immediately, and initialize the status of the port. If this
callback is undefined, OSS seq sends a ``HEARTBEAT`` event to the
port.

OSS event에서 ALSA event로의 변환

314-347

대부분의 OSS event는 sequencer가 적절한 ALSA sequencer event로 바꾸므로 synth driver는 ALSA port의 `input_event` callback으로 이를 받는다. Driver가 구현해야 할 변환은 다음 표와 같다.

OSS event 변환표
ALSA eventOriginal OSS events
NOTEONSEQ_NOTEON, MIDI_NOTEON
NOTESEQ_NOTEOFF, MIDI_NOTEOFF
KEYPRESSMIDI_KEY_PRESSURE
CHANPRESSSEQ_AFTERTOUCH, MIDI_CHN_PRESSURE
PGMCHANGESEQ_PGMCHANGE, MIDI_PGM_CHANGE
PITCHBENDSEQ_CONTROLLER(CTRL_PITCH_BENDER), MIDI_PITCH_BEND
CONTROLLERMIDI_CTL_CHANGE, SEQ_BALANCE (with CTL_PAN)
CONTROL14SEQ_CONTROLLER
REGPARAMSEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)
SYSEXSEQ_SYSEX

원래 OSS event를 low-level driver가 받는 ALSA event에 대응시킨다.

이 동작의 대부분은 문서 작성 당시 Emu8000 low-level driver에 포함된 MIDI emulation driver로 구현할 수 있었고, 향후에는 독립 모듈로 만들 계획이었다.

`SEQ_PRIVATE`과 `SEQ_VOLUME` 같은 일부 OSS event는 `SND_SEQ_OSS_PRIVATE` type으로 전달된다. OSS sequencer는 이 8byte packet을 수정하지 않으므로 low-level driver가 적절히 처리해야 한다.

Events
======

Most of the events are processed by sequencer and translated to the adequate
ALSA sequencer events, so that each synth device can receive by input_event
callback of ALSA sequencer port. The following ALSA events should be
implemented by the driver:

=============        ===================
ALSA event        Original OSS events
=============        ===================
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 (with CTL_PAN)
CONTROL14        SEQ_CONTROLLER
REGPARAM        SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)
SYSEX                SEQ_SYSEX
=============        ===================

The most of these behavior can be realized by MIDI emulation driver
included in the Emu8000 lowlevel driver. In the future release, this module
will be independent.

Some OSS events (``SEQ_PRIVATE`` and ``SEQ_VOLUME`` events) are passed as event
type SND_SEQ_OSS_PRIVATE.  The OSS sequencer passes these event 8 byte
packets without any modification. The lowlevel driver should process these
events appropriately.

MIDI port의 자동 등록 조건

348-366

OSS emulation은 ALSA sequencer announcement를 받아 MIDI sequencer port 생성과 삭제를 자동으로 probe하므로 synth 장치와 달리 MIDI 장치를 명시적으로 등록할 필요가 없다.

다만 ALSA sequencer에 등록한 MIDI `port_info`에는 group 이름 `SND_SEQ_GROUP_DEVICE`와 `CAP_READ` 또는 `CAP_WRITE` capability bit가 있어야 한다. Subscription capability인 `CAP_SUBS_READ` 또는 `CAP_SUBS_WRITE`도 정의해야 한다. 이 조건을 만족하지 않으면 OSS sequencer MIDI 장치로 등록되지 않는다.

MIDI 장치를 통한 event는 OSS sequencer가 parse해 대응 ALSA sequencer event로 바꾼다. MIDI sequencer input도 OSS sequencer가 MIDI byte event로 변환하며, 이는 `seq_midi` 모듈의 반대 방향 동작이다.

OSS MIDI port 등록 조건
항목필수 값
groupSND_SEQ_GROUP_DEVICE
I/O capabilityCAP_READ 또는 CAP_WRITE
subscriptionCAP_SUBS_READ 또는 CAP_SUBS_WRITE
등록 방식ALSA announcement 기반 자동 probe

자동 probe 대상이 되기 위한 `port_info` 필수 항목이다.

Interface to MIDI Device
========================

Since the OSS emulation probes the creation and deletion of ALSA MIDI
sequencer ports automatically by receiving announcement from ALSA
sequencer, the MIDI devices don't need to be registered explicitly
like synth devices.
However, the MIDI port_info registered to ALSA sequencer must include
a group name ``SND_SEQ_GROUP_DEVICE`` and a capability-bit
``CAP_READ`` or ``CAP_WRITE``. Also, subscription capabilities,
``CAP_SUBS_READ`` or ``CAP_SUBS_WRITE``, must be defined, too. If
these conditions are not satisfied, the port is not registered as OSS
sequencer MIDI device.

The events via MIDI devices are parsed in OSS sequencer and converted
to the corresponding ALSA sequencer events. The input from MIDI sequencer
is also converted to MIDI byte events by OSS sequencer. This works just
a reverse way of seq_midi module.

알려진 미구현 항목

367-371

알려진 문제이자 TODO는 ALSA instrument layer를 통한 patch loading이 아직 구현되지 않았다는 점이다.

seq-oss TODO
항목상태
ALSA instrument layer를 통한 patch loading미구현

문서에 명시된 남은 구현 항목이다.

Known Problems / TODO's
=======================

* Patch loading via ALSA instrument layer is not implemented yet.