Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Sounds proposal (long!)




Here is my new proposal for the sounds in Crossfire.  I tried to take into
account the various comments and suggestions that were posted on this list
or e-mailed directly to me by Tero Haatanen and others.  Note that I won't
start implementing this now, but I will keep this proposal (and the other
ideas sitting in my brain) for later, when the code will be split between
an idependant client and a server and when the old "false client/server"
code will not be supported anymore.  :-)

I'm not sure if it is interesting for you to reply to this message, because
this proposal will not be implemented soon.  But if you choose to reply to
me or to the list, *PLEASE* do not quote the whole message: all members of
the list will have seen it already.  Select only the relevant parts and save
some bandwidth...

Disclaimer: I'm not claiming that I know the best way to handle sounds in
the game.  In fact, I could be totally wrong...  :-)

---------- cut here ---------- cut here ---------- cut here ----------

            PROPOSAL FOR A NEW SOUND SYSTEM IN CROSSFIRE
            ============================================

1) Background information
-------------------------

I assume that Crossfire will be split between a client (for the user) and
a server (without any graphical output).  A typical setup would have the
client running on a "local host" and the server running somewhere else on
the Internet.  Furthermore, this client could display its windows and play
the sounds on a remote display, although most of the time the display will
be on the machine which runs the Crossfire client.

                  Internet                     Local network
 Crossfire    <--------------->   Crossfire  <--------------->  X terminal
  server        Crossfire c/s       client       X protocol
                  protocol                     Rplay protocol

If crossfire is going to have a rich audio environment, I expect that half
of the c/s traffic could be used by the sound commands.  Because of this,
I tried to minimize the amount of information that is sent during the game.
I always followed the rule: "if something can be done by the client, then
the server should not do it" (unless it would give too much information to
the client and allow the user to cheat).

I hope that we will see some clients for MS-Windows or Macintosh one day or
another.  That's why I tried to avoid UNIX-specific features in the
definition of the new sound system.  Although I will use RPlay in the client
because it is IMHO the best audio protocol under UNIX and the easiest to use,
it should be possible for someone to replace RPlay by another protocol, such
as NAS.

Here is a short glossary of the words that I will use in the following
paragraphs.  This will hopefully prevent confusion and clarify some things:
- "event type", "sound event", "sound type" or "sound": a symbolic name
  associated with an event (player or monster action, random event, ...).
  These names are used in the server code and in the maps, but are not
  actually used by the client.
- "sound file": the name of the file which contains the sound samples.  It
  will usually be a .au file, but some clients could use .wav or .voc files
  instead, or even .mod or .midi (if the client supports these formats).
- "sound index" or "index number": a number which is associated with an
  event type.  This number is generated by the server when it reads the
  config file and it is sent to the client during the game (see below).
- "priority": a number which helps the client in choosing which sounds
  should be played when the maximum number of simulateous sounds is exceeded.
- "maximum volume": the volume at which a sound file should be played if the
  source of the sound is at the same position as the player (if the relative
  position is (0, 0)).
- "volume": the volume at which a sound is actually played, including the
  attenuation caused by the distance.

2) Contents of the lib/sounds file
----------------------------------

The config file "lib/sounds" is stored on the server.  It contains the
mapping between the various events (sound types) and the sound files that
should be played.  This will be transferred to the client at startup and
it will be possible for the client to override some entries.

This file will contain lines which look like this:
 <event type> <priority> [<sound file> <max volume>] [<sound file> <vol>] ...
Comments begin with a "#" and can be inserted anywhere in the file.  Blank
lines and lines containing only a comment are ignored.  Several sound files
can be listed on the same line in order to create a more complex sound
effect (but this is still considered as a single sound effect).

The following example shows what kind of information is included in this
file, but the actual format may vary (i.e. by using different separators or
swapping the parameters).

  # <sound name>, <prio> = <file>, <max vol>; <file>, <max vol>; ...
  # player actions:
  player hits door,        200 = knock.au, 60
  player hits locked door, 200 = knock.au, 60    # same as above
  player opens door,       220 = creak.au, 80
  # monsters:
  dragon moves,            100 = rumble.au, 20
  dragon attacks,            0 =                 # no sound
  goblin dies,             150 = splat.au, 30
  # spells:
  firestorm,               210 = whoosh.au, 100  # usual dragon attack
  comet,                   230 = whoosh.au, 70; bang.au, 100, whoosh.au, 40
  # ambient sounds:
  ambient wind,             10 = wind.au, 10
  ambient woods,            10 = whoohoo.au, 20  # owls
  ambient cave,             10 = rumble.au, 10   # rocks moving
  ambient cave 2,           10 = drip.au, 20     # water dripping
  ambient well,             20 = drip.au, 30
  # music:
  music castle room,         0 = castlemusic.au, 10; ballad.au, 10
  music cave,                0 = cavemen.au, 15
  music silly example,       0 = Dsharp.au, 10, C.au, 10, Eflat.au, 15  # ...

At startup, the server reads this config file and associates an index number
with each line.  This index number is the only information that will be sent
to the client during the game.  The config file could be sorted or indexed
with a hash table in order to find the index numbers faster (since the server
will only know the sound name and will have to send the index number to the
client).

Each time a new client connects, the whole config file is sent to it, with
each sound prefixed by its index number.  The example above would be sent as:

  1: player hits door,        200 = knock.au, 60
  2: player hits locked door, 200 = knock.au, 60
  3: player opens door,       220 = creak.au, 80
  ...

3) How sounds are used in the game
----------------------------------

There are several kinds of sounds; each one is handled by a specific routine
and defined in a different way.  It is important to understand the
differences between these categories, because some of the suggestions that
have been posted to the mailing list did not take all of them into account.

* Sounds triggered by player actions: pushing a lever, opening or hitting
  a door, falling in a pit, ...  All these sounds names are prefixed by
  "player" and are included directly in the server code: when a player
  falls into a pit, the routine which deals with this action will send the
  message "You fell into a pit" and will also tell the client to play a
  sound called "player falls" (for example).
  Average priority for these sounds: 200.
* Sounds made by monsters: movement, attack, pain when hit, ...  The name
  of the sound will be built from the name of the monster and the name of
  the action.  For example, a giant will play the sounds "giant idle",
  "giant moves", "giant attacks", "giant pain" and "giant dies".  Likewise,
  a wyvern will play "wyvern idle", "wyvern moves", etc.
  (Note: the probability of playing the "idle" sound should be defined in
  the archetypes file, but it should also be possible to modify this
  attribute on the map).
  All monsters which have the same name will play the same sounds.  If you
  want to have a monster which plays different sounds, then you should
  change its name and define new entries for it in the lib/sounds file.
  (Note: the server should look first for the monster name in lib/sounds,
  then for the archetype name if there is no entry with the name of the
  monster).
  Average priority for these sounds: 100.
* Spells: players or monsters can cast spells, but I don't think it is
  necessary to have different sounds depending on who cast it.  The volume
  will already be different because player spells will always start from
  the relative position (0, 0).  The names of these sound events will be
  identical to the spell names.
  Average priority for these sounds: 200.
* Environmental sounds: these are played at random and their only purpose
  is to set the right athmosphere (games like Heretic and Hexen are good
  examples of this).  They do not give much information to the player,
  but they add more realism.  The sounds that are not associated with a
  well-defined object on the map are always played from the player's position
  and will have a constant volume (this should be the case for wind, owls in
  the woods, etc.).  Unlike the other sounds, the names of these events are
  not hardcoded in the server: they are included in the attributes of some
  objects on the maps.  The names of these events will always begin with
  "ambient".
  Fixed priority for these sounds: 10 for normal sounds, and 20 for the
  sounds that give a bit of information and are associated with an object
  (e.g. water dripping if there is a well nearby, rocks falling if the player
  is close to a pit).  Sounds with a priority of 10 will always be played
  from the player's position.
* Background music: long sequence of sounds which are played in a loop.  The
  format of the sound files doesn't matter: it could be a single .au file,
  multiple .wav files, a .mod or .midi file, ...  I don't think that we need
  background music if the environmental sounds are well done, but some people
  cannot live without this, so...  All music effects are prefixed with
  "music".
  Fixed priority for music: 0.

4) How the client plays the sounds
----------------------------------

At startup, the client receives the config file from the server.  Each
sound will have an index number associated with it for faster reference
(usually, this will be its line number in the config file).  After having
received the complete list, the client checks if the user wants to
override some entries.  This will be done by reading a local file which
has the same format as the lib/sounds file sent by the server.

The client parses this list of sounds and builds an array which associates
each index number with the list of sound files that should be played.  At
this stage, it is not necessary to keep the event names in memory, because
they will not be used any more.

If the client sees any sound that is not available on the local disk, it
could choose to prefetch them, or to let the RPlay server get them
automatically later.  It is recommended that the machines which have a
Crossfire server running also have a RPlay server ready to transfer sounds
using the RPTP sound transfer system.

During the game, the server sends the index number of every sound that
should be played by the client, as well as the relative position of the
sound source.  These three numbers (index and two coords) are the only
information that is sent when a sound has to be played.  Well, maybe they
should be preceded by a "play" command...

The client will then play the sound or list of sounds that are associated
with this index number.  The maximum volume of each sound will be lowered
according to the distance.  If the client supports stereo sound, the volume
of the left and right channels will be modified as appropriate.  An easy way
to do that is to calculate two distances: one for the left ear and one for
the right ear, like if they were one map unit away from the player in each
direction.

If there are already several sounds playing, and the maximum number of
simultaneous sounds has been reached, the client will only play the sounds
which have the highest priority.  The maximum number of simultaneous sound
effects is customizable by the user and should be between 2 and 8 (4 should
be the default value).  Mixing more than 8 sounds would give bad results.

5) Open issues
--------------

Most of the sound events for the lesser monsters will have no sound file
associated to them in the config file, otherwise the game would be too noisy.
Would it be a good idea to send the commands to play them anyway?  Although
they will probably have no effect on most clients, some user could have
defined a sound for these events (remember that the user can override all
sound definitions).  Note that in order to support this, the server would
have to generate index numbers for the sounds that are not in its config
file.  I think it is simpler to ignore the sounds that have no entry for
them in lib/sounds.

What attributes should be used in the archetypes file for defining how often
a monster should play its "idle" sound?

Same question for the "pain" sound: what is the minimum damage that the
monster should take before playing this sound?  Other idea for the "pain"
sound: define several levels of pain and use relative threshold that would
be the same for all monsters.  For example, there could be three levels:
"minor pain" for less than 10% damage, "pain" for less than 20% damage and
"major pain" for more.  Hmmm...  Maybe two levels would be enough.

What attributes should be used for "environmental sounds" in the maps?
There should be a way to define their name and how often they should be
repeated.  (Note: the repeat rate is a property of the object which plays
the sound, not a property of the sound event like it was suggested on the
mailing list).

Is it really a good idea to look for monster names before looking for
their archetype name?  This allows people to customize the sounds made by
a particular monster or group of monsters (as suggested by Tero), but it 
adds some overhead.  It would be simpler to sacrifice the customization
and use the same sounds for all monsters of a given kind.

If the NPC's are improved, there should be a way to add custom sounds for
them too.

---------- cut here ---------- cut here ---------- cut here ----------

That's all folks!

Merry Christmas and happy new year to everyone out there!  I'm not sure that
I will have the time to read my mail before next year, so I'd better send my
wishes now...

Remember: if you really want to reply, save some electrons by quoting only
the relevant parts of my message and dropping everything else.  Thanks! :-)

-Raphael