The Game Kit: BGameSound

The Game Kit Table of Contents | The Game Kit Index

# BGameSound

Derived from: none

Declared in: be/game/GameSound.h

Library: libgame.so

Allocation: Constructor only

###### Summary

The BGameSound class is the base class for other game sound classes. You never use this class directly; instead, you should use the derived classes.

## The Sound of Explosions in the Morning

Nothing makes the player happy like the sound of lots of explosions, weird alien things, and other thrilling audio pleasures. The various BGameSound-derived classes make this a snap.

### Choosing a Player Class

Playing a sound is as simple as instantiating an object derived from the most appropriate class and calling `StartPlaying()` on it. How do you determine the most appropriate class? Here are some hints:

- If you have a sound effect that's short and is likely to be played often, or needs to be played with minimal latency, use the BSimpleGameSound class. An arcade game's explosions definitely fit into this class.

- If you have a sound effect that's very long, or doesn't need to be played very often, or whose latency doesn't matter much, use the BFileGameSound class. Music loops can take advantage of this class.

- If you want to be able to push audio buffers at the system, instead of having a callback that fills buffers, use the BPushGameSound class.

  Most games' needs will be filled by the BSimpleGameSound and BFileGameSound classes. And, of course, you can write your own derived classes if none of these classes meet your requirements.

  ### Polyphony

  Sometimes the player needs to hear multiple copies of the same sound at the same time; for instance, if they shoot a three-way splitting weapon and hit two targets, they need to hear two explosions at once. Each BGameSound (or BGameSound-derived) object can play only once at a time, so you'll need to use cloned copies of the sound, one for each channel of polyphony you allow.

  This can be done with ease using a simple class like this:

         class MultipleEffect {
         public:
            MultipleEffect(BGameSound * sound, int polyphony) {
               m_fx = new BGameSound *[polyphony];
               m_fx[0] = sound;
               for (int ix=1; ix<polyphony; ix++) {
                  m_fx[ix] = sound->Clone();
               }
               m_current = 0;
               m_polyphony = polyphony;
            }
            void StartPlaying() {
               int id = atomic_add(&m_current, 1) % m_polyphony;
               m_fx[id]->StartPlaying();
            }

         private:
            int32 m_current;
            int32 m_polyphony;
            BGameSound *m_fx;
         };

  This class' constructor lets you specify a BGameSound-derived sound and the maximum number of times it can be playing at once. It creates the appropriate number of clones, and its `StartPlaying()` implementation automatically selects the oldest one and reuses it. Since `StartPlaying()` restarts a sound from the beginning if it's called on a playing sound, this works out well—if polyphony is 3, and there are already three sounds playing, the oldest one will be reset and played from the beginning.

  In the current version of the BeOS, when you clone a BSimpleGameSound, the sound data buffer is also cloned, so you'll have multiple copies of the sound effect in memory. Keep this in mind as you write your code, as you can rapidly use a lot of memory this way.

  ### Performance Verification

  There are a wide variety of performance concerns, and of course you want your game to work on as many systems as possible. Be recommends that you test your application in at least these three situations:

  - Real-time audio disabled, using an ISA sound card (such as an AWE64 or equivalent card).

  - Real-time audio enabled, using a PCI sound card (SoundBlaster PCI 64 or equivalent).

  - Real-time audio enabled, using an E-mu 10k sound card. This sound card has its own node, so its behavior is a little different, and is therefore worth special testing attention.

  This isn't intended to be an exhaustive list; you should always test your software in as many configurations as possible.

  ## Constructor and Destructor

  ### BGameSound()

  `BGameSound(`BGameSoundDevice *device = NULL`)`

  Initializes the sound object.

  | Currently, device must always be `NULL`.

  ### ~BGameSound

  virtual `~BGameSound()`

  Releases any memory used by the BGameSound.

  If your node has created and set BBufferGroups for any producers, you should delete them in the destructor.

  ## Member Functions

  ### Clone()

  virtual BGameSound *`Clone(`void`)` const = 0` `

  Returns a copy of the game sound object. Not implemented in this base class; derived classes must implement it.

  ### Device()

  BGameSoundDevice *`Device(`void`)` const` `

  Returns a pointer to the BGameSoundDevice responsible for playing the sound. This is `NULL` if the default device is being used.

  ### Format()

  const gs_audio_format &`Format(`void`)` const

  Returns a `gs_audio_format` structure describing the format of the sound.

  ### Gain() see SetGain()

  ### GetAttributes() see SetAttributes()

  ### ID()

  gs_id `ID(`void`)` const

  Returns the ID of the sound attached to the BGameSound object. This is 0 if no sound has been selected.

  ### Init()

  protected:

  status_t `Init(`gs_id soundHandle`) `

  Specifies the sound to be played by the object.

  RETURN CODES

  `B_OK`. The initialization was successful.

  - `B_ERROR`. The constructor failed.

  - Other errors. The player may return other errors.

  ### InitCheck()

  status_t `InitCheck(`void`)` const` `

  Returns a status_t indicating whether or not the object was successfully initialized. A return value of `B_OK` means everything's fine; any other value means an error occurred in the constructor.

  ### IsPlaying()

  virtual bool `IsPlaying(`void`)`

  Returns `true` if the sound is currently playing; otherwise this function returns `false`.

  ### LockMemoryPool()

  static status_t `LockMemoryPool(`bool lockInCore`) `

  This function lets you specify whether or not the BGameSound's memory pool (from which buffers are drawn) is locked in memory. Locking the pool may increase performance, but will increase your memory requirements and may reduce the ability of the computer to use virtual memory efficiently.

  | You can only set the lock state from within the constructor of a derived class. Once the state has been set, it can't be changed.

  RETURN CODES

  `B_OK`. The pool's lock state has been set.

  - `EALREADY`. The lock state has already been set.

  ### Pan() see SetPan()

  ### SetAttributes() , GetAttributes()

  virtual status_t `SetAttributes(`gs_attribute *inAttributes, size_t inAttributeCount`) `
  virtual status_t `GetAttributes(`gs_attribute *ioAttributes, size_t inAttributeCount`) `

  `SetAttributes()` sets the sound's attributes to match those in the inAttributes array; inAttributeCount indicates how many attributes are in the list.

  `GetAttributes()` returns the sound's current attributes. The ioAttributes list contains a list of inAttributeCount `gs_attribute` structures; each entry indicates in its `attribute` field which attribute is to be stuffed into that slot in the array. On return, these attributes are filled out.

  RETURN CODES

  `B_OK`. The attribute changes were recorded.

  - `B_ERROR`. The player wasn't initialized properly.

  ### SetGain() , Gain()

  status_t `SetGain(`float gain, bigtime_t rampDuration = 0`) `
  float `Gain(`void`) `

  `SetGain()` sets the sound's gain (volume). If rampDuration is nonzero, the change in gain will take rampDuration to occur—the gain will fade between the current value and the new value over the specified number of microseconds. If rampDuration is 0, the change will be immediate.

  `Gain()` returns the sound's current gain.

  The gain ranges from 0.0 (silent) to 1.0 (maximum gain).

  RETURN CODES

  `B_OK`. The gain change was recorded.

  - `B_ERROR`. The object hasn't been initialized properly.

  - Other errors. The derived class may return other appropriate errors.

  ### SetInitError()

  protected:

  status_t `SetInitError(`status_t initError`) `

  Sets the error code that `InitCheck()` will return. Derived classes should call this from their constructors.

  ### SetMaxSoundCount()

  static int32 `SetMaxSoundCount(`int32 maxSoundCount`) `

  This function lets you specify the maximum number of BGameSound-derived objects that can be in use at once. This value must be between 32 and 1024; if it's outside this range, it gets pinned to 32 or 1024. The actual value set is returned.

  ### SetMemoryPoolSize()

  status_t `SetMemoryPoolSize(`size_t poolSize`) `

  Sets the size of the memory pool from which sound buffers can be obtained to the number of bytes specified by poolSize. This value must be between 128kB and 4MB, or `B_BAD_VALUE` will be returned.

  | You can't change the size of the memory pool once it's been allocated.

  In general you'll only call this function if you're implementing a new BGameSound subclass.

  RETURN CODES

  `B_OK`. The memory pool size has been set.

  - `B_BAD_VALUE`. The requested pool size is invalid.

  - `EALREADY`. The memory pool has already been allocated; you can't change its size.

  ### SetPan() , Pan()

  status_t `SetPan(`float pan, bigtime_t rampDuration = 0`) `
  float `Pan(`void`) `

  `SetPan()` sets the sound's pan. This value, which ranges from -1.0 to 1.0, indicates the apparent position of the sound (from absolute left to absolute right). A value of 0 indicates that the sound should appear to come from directly in front of the user. If rampDuration is nonzero, the change in position will take rampDuration to occur—the sound will seem to move from the initial position to the new position over the specified number of microseconds. If rampDuration is 0, the change will be immediate.

  `Pan()` returns the sound's current pan.

  RETURN CODES

  `B_OK`. The pan change was recorded.

  - `B_ERROR`. The object hasn't been initialized properly.

  - Other errors. The derived class may return other appropriate errors.

  ### StartPlaying() , StopPlaying()

  virtual status_t `StartPlaying(`void`)`
  virtual status_t `StopPlaying(`void`) `

  `StartPlaying()` begins playback of the sound. `StopPlaying()` ends playback.

  If you call `StartPlaying()` on a sound that's already playing, it stops and restarts from the beginning.

  These return `B_OK` if all is well, or an appropriate error code if not; the error depends on the derived class being used.

  RETURN CODES

  `B_OK`. No error.

  - `EALREADY`. The sound is already playing (if you called `StartPlaying()`) or not playing (if you called `StopPlaying()`).

  - Other errors, as determined by the subclass.

  The Game Kit Table of Contents | The Game Kit Index

  The Be Book,
  ...in lovely HTML...
  for BeOS Release 5.

  Copyright © 2000 Be, Inc. All rights reserved..