root/drivers/sound/experimental.txt

/* [previous][next][first][last][top][bottom][index][help] */
This version contains some features which is are NOT enabled by default. 
I'm trying to release an official/reliable version soon so that the
Linux version of Doom (and other games) becomes possible. For that reason
I have disabled some features which are not reliable enough to be
released for wide public. If you are interested to try them, please
read this file carefully.

There are currently following goodies which I have disabled:

1) ECHO PSS (Personal Sound System support)

This version contains support for soundcards based on the AD20msp614
chipset made by Analog Devices. This chipset consist of the
AD1848 codec, ADSP-21xx DSP chip and a ESC614 ASIC and is used in some
soundcards made by Orchid, Cardinal, Echo Speech Corporation, Western
Digital and Wearnes Technology. The PSS support is by Marc M. Hoffman
(marc.hoffman@analog.com). I received this stuff about a week ago and
have not been able to test it yet.
If you are interested, remove the B(OPT_PSS) from the DISABLED_OPTIONS
(see above).
You have also to enable the MSS support since I have not integrated
the AD1848 driver with the PSS one yet.

2) WSS/MSS (Microsoft Sound System) support

The MSS standard is based on the AD1848 codec by Analog Devices.
Since I don't know how the software configuration of the MSS works
so it's not supported yet. This driver should work if your card
has jumpers for the I/O base, IRQ and DMA or there is a way to configure
them using DOS. You could try this if you have a soundcard with
AD1848 codec. I have tried to use this with Aztech SG NX Pro 16 without
success. 
If you are interested, remove the B(OPT_MSS) from the DISABLED_OPTIONS
(see above).

3) /dev/sequencer2

This version has a new device file called /dev/sequence2. I have not
implemented all parts of it but it's there. It's only interesting if
you are writing a sequencer program yourself. Enable by creating
the device file /dev/sequencer (minor 8).

4) /dev/midi##

These are tty like raw devices for MIDI ports. Since there is a minor
incompatibility between different versions of Linux, I have disabled
this feature by default. You just need to create the device files yourself.
IMPORTANT!      If you get warning at line 64 of midibuf.c,
                don't try to use /dev/midi## files. Otherwise your
                system halts. You may also try to fix the
                DEFINE_TIMER() macro in os.h (just remove the 2nd NULL).
                This could happen with some earlier versions of Linux
                (before 1.1.0???).

5) Support for hardware based u-Law/A-Law and ADPCM formats.

The AD1848 (and compatibles) are able to do compression and
decompression by hardware. This version has experimental support
for some of them. Currently they are implemented just in the
AD1848 driver. The GUS MAX (and the 16 bit daughtercard) support
also 16->4 bit ADPCM (the IMA one) but it don't work yet.
The argument ioctl(SNDCTL_DSP_SAMPLESIZE) can have some new values
in addition to the 8 and 16 supported earlier. Look at soundcard.h
for more info.
(In case somebody dares to ask: The ASP chip of SB16 is not supported
so the hardware compression/decompression doesn't work with it. Also
the ADPCM format is different than the standard (IMA) one (I guess).
This feature is enabled by default.

5) Real time fix to /dev/dsp and /dev/audio drivers

The following feature should help game writers. This stuff is enabled
by default.
---------------- cut here ---------------------
There is a new ioctl called SNDCTL_DSP_SETFRAGMENT. It accepts a
int parameter which has format 0x00nn00ss where the nn is max number of 
buffer fragments (between 0x02 and 0xff) and the ss gives indirectly the 
size of a buffer fragment (fragment_size = (1 << ss)). Valid sizes are 
between (ss=0x07 -> 128 bytes and ss=0x11 (17 dec) -> 128k).

This ioctl must be used ONCE between open() and first call to 
read()/write() or ioctl(SNDCTL_DSP_GETBLKSIZE). 

You need just to force the fragment size to a value which is sufficiently 
short (gives the 1/20th of sec with the speed/#channels/#bits you are using).

Using a small number of fragments offers (I guess) a significant advantage.
For example with 2 fragments the driver works as the following (at least 
I hope so). Assuming that the process writes exactly 'fragment_size' of 
bytes each time (this is really important).

        1) When the process writes the first fragment, it will be copied to
        the DMA buffer area and the playback begins. The write() returns
        immediately and the process is free to continue.


        2a) If the fragment gets played before the application writes a new
        one, the device will be stopped and restarted which causes a click.
        When the process calls write next time, it will be processes as 
        in step 1.

        2b) If the process calls write before the buffer underflows, the
        data will be queued and the process is free to continue. (There
        is now one full and one partially played fragment in the kernel
        buffers. This gives average delay of 1.5*fragment_time (for 
        example 1/20th sec) before the last byte in the buffer gets played.


        3a) If the device gets both fragments played before the next write
        (underflow), there will be a click. The write will be processed as
        in step 1.

        3b) If the 1st fragment gets played before next write (the process
        calls write during playback of the second fragment), it will be
        processed as step 2b.

        3c) If the process writes 3rd fragment when there is already 2
        fragments in the queue (1 playing and 1 waiting), the process
        will block until the 1st fragment gets played. It will then be
        woken up and it continues as in step 2b. This means that
        the process blocks for at most the time required to play a
        buffer fragment.

This method synchronizes the process and the audio device together 
automatically. The process will block at most the 'fragment_time'. Usually 
less, depending on how much it needs time to do other things. The maximum
delay between writing a byte and the time when it finally plays is
at most 3 times the 'fragment_time'. 

The delay depends on how much time the program needs to do it's 
computations for the next sample (updating screen etc). If it's about
80% of the 'fragment_time' the game will run almost without delays. If it 
uses more time, there is a risk that the audio buffer gets empty.
        
The application code should be something like the following:

int frag = 0x00020008;  /* 2 fragments of 2^8=256 bytes */
int frag_size;

int fd=open("/dev/dsp");
ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);
ioctl(NDCTL_DSP_SPEED); /* And #channels & #bits if required */

/*
 * Query the actual fragment size since the driver may refuse
 * the requested one (unlikely but possible?)
 */

ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size);

while(True)
{
        do_computations();
        write(fd, buf, frag_size);      /* Always the same size!!!!!!! */
}

I have tested this with a modified version of str.c. The algorithm works 
as long as the playing program gets enough time to run. Hitting ENTER on 
another virtual console causes a pause/click (with 2 frags of 64 bytes).
------------------- cut here ---------------------

/* [previous][next][first][last][top][bottom][index][help] */