Version 0.021 (12 dec 1998)

By NooTe (aka Nathaniel Saint Martin)

noote@bigfoot.com

http://www.bigfoot.com/~noote/


Sound System for CrystalSpace.

A big WWAARRNNIINNGG... Module player is bugged a lot. Also, don't try to play mod !

OS supported :

I have made a win32 driver using waveOut functions (standard win32 api).

Gert Steenssens gsteenss@eps.agfa.be have made a (experimental) linux driver.

(I cannot do a linux/solaris driver because my pnp awe64 isn't recognize yet, if you have info/solution about this problem, well : email me :-)).

I planed to add DirectSound with hardware mixing when this sound system will be stabilized.

File format supported :

it can read :

sun standard .au (or .snd), 8 and 16 bit PCM, 8 bit G.711 u-Law (no-compressed) ;

microsoft .wav, 8 and 16 bit PCM ;

amiga .8svx/.iff, 8 bit PCM ;

mac .aiff, 8 and 16 bit PCM.

I'm searching about other usual file format (http://www.wotsit.org don't handle or give (good) information about mac .aiff format).

Does some one know about 'Fibonacci-Delta encoding' compression in .8svx/.iff format ?

Or about G.721 a-Law ADPCM compression ?

Module file supported :

currently, my module player don't work correctly but I can read .mod file and play (more or less) it :

.mod, old 4 channel mod format, protracker, fastracker, oktalizer, taketracker and startracker : 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28 and 32 channels and 31/15 instruments.

I try to made all specific effects in some general effects for all (and future) supported module format (it, s3m...).

Where can get it ?

In CrystalSpace. distribution at http://crystal.linuxgames.com !

or on http://www.bigfoot.com/~noote/CrystalSpace/Sound for latest development, fix and others things...

How it work ?

csSoundDriver class is the interface driver, you might use this for handle you sound driver.

This class mix sound in a alone output.

I call 'Wave' : the sound get from sound file (not module), 'Module' is... yes, a module get from module file :-). A 'Channel' contient a Wave or a Module output, csSoundDriver mix several Channel (you can define number of channel in properties, see 'How configure sound system ?').

csSoundDriver handle a list of Channel, it choice the 'MAX_CHANNELS' channels to mix. The selection of happy channels can be done with a priority function : then you add a Channel in the list, you can set a priority on it.

Each module is a channel, so you can add several module in channel list and play it simultaneous, but you cpu free time can decrease a lot !

Currently, you can play simultaneous several time one Wave : csSoundDriver handle each with a different... handle. For Modules, its a bit different, you can play only once a Module, you cannot play two time the same Module simultaneous.

Well, there are to type of wave control, one is ephemeral : you put a wave in the list of channel, mixing play until the end and kill him (delete), second is a Channel control, you can stop, resume, kill, mute, loop... if you arrive to the end you need to kill him because it wait in the list (but he's desactived).
You can control the volume/3d position of the two waves categories (and maybe later effects like reverb, echo...).

The first category is best for random sound like ambiance (in a sector or the world) or for other stuff with gui, menu...
The second is for entities sounds (sprites, moving things...).
An example : for missile, the 'whoosh' must be a second category but the 'boom' can be first category (we don't need to control him).

How configure sound system ?

in your configuration file (cryst.cfg) you might have a [SoundDriver] section else make it :-) like this :

[SoundDriver]
; MAX_CHANNELS set the maximum of channels we can mix
MAX_CHANNELS=16
; FREQUENCY set frequency supported by sound device (44100, 22050, 11025...)
FREQUENCY=11025
; 16BITS set if sound device may use 16 bits (if it supported)
16BITS=false
; STEREO enable stereo on sound device (if it supported) (for a 3d sound it
; can be necessary)
STEREO=true
; Active sound driver
ACTIVE=true
; Set general volume [0..1]
; If you put -1 or a value inferior to 0, current device volume is kept.
VOLUME=-1

MAX_CHANNELS is the maximum of channels you can mix (only for software mixing, for a hardware multi voice, it the sound card whose fix this) (more is this value, more it can take cpu).

FREQUENCY is the sample frequency for playing (more is this value, more it can take cpu), this value can be fixed by hardware limit, verify it from your manual/driver/manufacturer).

16BITS is for use 16 bits else it use 8 bits playing (depend of you sound card capabilities)

STEREO is for use of... stereo ? YES, you're right, (it depend of your sound card too). this one can be usefully for 3d sound.

ACTIVE, so, you want ear sound, well, set this one to true and it activate your sound driver.

VOLUME is a software or hardware value, from 0 (empty) to 1 (full), it depend of you sound card and/or driver.

waveOut win32 driver configuration ?

the waveOut win32 driver have is own configuration in addition to general sound driver configuration  (see 'How configure sound system ?')

[SoundDriver.waveOut]
; CALLBACK can be 'function' or 'thread'
CALLBACK=thread
; THREAD_PRIORITY can be 'lowest', 'normal' or 'highest'
THREAD_PRIORITY=highest
; 16BITS set if sound device may use 16 bits (if it supported)
REFRESH=10

CALLBACK method have two choice : 'thread' or 'function'. Thread method start a process whose fill sound data when it receive order (by waveOut). Function callback 'block' program for filling sound data, the call of function is done by waveOut but if us fps (Frame Per Second) is low or system idle is very low, calls to function can't be done (it unstable). I preconize thread method, (theorically) independent of main process idle.

THREAD_PRIORITY is only for thread method, it set the priority of thread : 'lowest' mean than sound thread have a lowest priority than main process, 'normal' is equal priority for main process and sound thread, and 'highest' mean than thread priority is... highest than main process ! Better is 'highest' but it might not work in full screen some time (maybe a little bug from me).

REFRESH is the time of refresh of sound data, a '10' value mean refresh sound data 10 times per second. But here, a warning (erh, it's stay an experimental stuff yet ;-)), if you get an fps inferior to this refresh value, it can crash for function callback or cut sound for thread method !

How make a specific driver ?

the csSoundDriver class is made for a sound card which have only one digital output (like a sb16), if you want add support for multi digital outputs (like a sbawe or a gus), you need to overload csSoundDriver::functionMixing() but it an other thing...

For made you own sound driver for CrystalSpace (assume it have one ouput) :

- you must do a class whose inherit of csSoundDriver class, some thing like : 'class MyOSSoundDriver : private csSoundDriver' ;

- you need to overload csSoundDriver::Open(int Frequency, bool 16bit, bool stereo), for open your OS sound driver  ;

- you need to overload csSoundDriver::Close(), for close you OS sound driver ;

- you need to overload csSoundDriver::setVolume(float volume), for setting volume in you hardware (value is [0...1], so you certainly need to convert it) ;

- you need to overload csSoundDriver::nextMemory(), for preparing your next buffer sound system ;

- you need to set correctly csSoundDriver::Background value : true if you have you own handler for putting output data, false if you wait a CrystalSpace event (csSystem::NextFrame()) for fill sound memory ;

- if you have you own callback function (timer, callback...), you to do fill in this order :

1° set size in csSoundDriver::MemorySize (remember this size correspond to number of bytes not to number of samples and set pointer for csSoundDriver::Memory ;

2° call csSoundDriver::functionMixing() ;

3° (depending of your OS sound driver), write csSoundDriver::Memory in your OS sound driver (like OSS)

- if you're waiting for CrystalSpace event (csSystem::NextFrame()), you need to overload csSoundDriver::update() and do :

1° verify if you have finish to play current buffer sound memory ;

2° prepare next buffer

3° call csSoundDriver::functionMixing() ;

4° put new data in you OS sound driver

-(...)

Why it don't work ?

hum... :

first, are you sure to have a sound card ? :-)

second, are you sure that sound card is supported by your OS ?

three, are you sure CrystalSpace have a sound driver for your OS ?

fourth, are you sure ? see debug.txt, if return a error from sound driver, try an other configuration by changing FREQUENCY, STEREO, 16 BITS, VOLUME and check if ACTIVE is 'on/true/1'

fifth... bin, p'tęt' qu'c'est un bogue ? (well, maybe it's a bug ?)