The Media Kit: BSoundPlayer

The Media Kit Table of Contents | The Media Kit Index

# BSoundPlayer

Derived from: (none)

Declared in: be/media/SoundPlayer.h

Library: libmedia.so

Allocation: Constructor only

###### Summary

The BSoundPlayer class plays sound, either from BSound objects or by directly filling audio buffers with data provided by a hook function you specify. A single BSoundPlayer can play multiple sounds at a time.

BSoundPlayer takes care of all the nitty-gritty details of instantiating the necessary sound player node and managing the time source. All you have to do is start up a BSoundPlayer and feed it sounds to play.

For simple audio playback, the sounds are specified using the BSound class. However, if you need to perform on-the-fly generation or alteration of sounds, you can implement a hook function that will be called for each audio buffer passed through the BSoundPlayer's playback node.

## Using BSoundPlayer

Once you've instantiated a BSoundPlayer object, you need to start it up before you can actually play sounds with it. This instantiates the sound player node, attaches it to an appropriate time source, and makes sure the time source is running. This is done by calling the `Start()` function.

When you're done using the BSoundPlayer, you can delete it if you don't plan to use it again, or, if you want to keep it around for reuse, you can just `Stop()` it. This deletes the sound node and cleans up the sounds.

In general, the process of using BSoundPlayer looks like this:

       BSoundPlayer player;
       player.Start();

       /* use the BSoundPlayer here */

       player.Stop();

You can find out the current time of the time source to which sounds are being synchronized by calling the `CurrentTime()` function.

By default, the audio format used by a BSoundPlayer is `BSoundPlayer::B_AUDIO_FLOAT`, which is to say that the audio is in floating-point format, where each sample ranges from -1.0 to 1.0. The Media Kit uses floating-point audio internally, so using floating-point audio whenever you can will improve your application's performance by cutting down on format conversions. However, if you want to use another format, you may do so by specifying a media_raw_audio_format when you instantiate the BSoundPlayer object.

In the current release of BeOS, all BSounds playing through a single BSoundPlayer must have the same sampling rate. This restriction may be lifted in the future. For the time being, just instantiate one BSoundPlayer for each sampling rate you need to support. In addition, only the `BSoundPlayer::B_AUDIO_FLOAT` audio format is supported.

### Playing Sound

A BSoundPlayer object plays sounds asynchronously, and can play as many sounds as you like. You start playback of a sound by passing a BSound pointer to `StartPlaying()`:

       play_id id = player->StartPlaying(sound);

`StartPlaying()` returns an ID number you can use to refer to the sound throughout its existence; other BSoundPlayer functions require this ID as an argument.

You can, optionally, specify a time at which to begin playback:

       play_id = player->StartPlaying(sound, 100000);

This starts playback at the performance time 100000 microseconds.

You can determine whether or not a sound is still playing by calling `IsPlaying()`:

       if (player->IsPlaying(id)) {
          /* the sound is playing */
       }

You can stop the sound by calling `StopSound()`:

       player->StopSound(id);

And the `WaitForSound()` function waits until the specified sound is finished playing:

       play_id id = player->StartPlaying(sound);
       player->WaitForSound(id);

And you can control the volume as well. Use the `Volume()` function to determine the current volume, and `SetVolume()` to change the volume. The volume is a floating-point number, and ranges from 0.0 (silence) to 1.0 (full volume). Here's a code snippet that halves the current volume:

       SetVolume(Volume()/2.0);

#### Example: Let's Play Around

Playing sound files using BSoundPlayer is very easy. Here's a function that will play a specified sound, waiting until the sound is finished playing before it returns:

       void playsound(char *path) {
          BSound *sound;
          BSoundPlayer player;
          entry_ref ref;
          BEntry entry(path, true);
          BSoundPlayer::play_id id;

          if (entry.InitCheck()) == B_OK) {
             if (entry.GetRef(&ref) == B_OK) {
                sound = new BSound(&ref);
                if (sound->InitCheck() == B_OK) {
                   player.Start();
                   player.SetVolume(1.0);
                   id = player.StartPlaying(sound);
                   sound->ReleaseRef();
                   player.WaitForSound(id);
                }
             }
          }
       }

An entry_ref is obtained for the specified sound file, then a BSound object is instantiated given that entry_ref. A BSoundPlayer object is started, the volume is set to 1.0 (full volume), and then the sound playback is started by calling `StartPlaying()`. The sound's reference count is decremented, and finally BSoundPlayer's `WaitForSound()` call is used to wait until playback is complete.

### Advanced Playback

If you have more advanced playback needs—for example, you need to play sounds that are being generated on-the-fly, or if you need to filter the sound you're playing.

If you specify a play buffer handler function, either when instantiating the BSoundPlayer object or by calling `SetCallbacks()` or `SetBufferPlayer()`, that function will be called once for each buffer that passes through the BSoundPlayer's sound playing node. Your play buffer handler can then fill the buffer with whatever data you wish.

| If you specify a play buffer function, BSound playback won't work. If you need to do both, you must use multiple BSoundPlayer objects.

The following code sets up a BSoundPlayer that will play a triangle wave.

       typedef struct cookie_record {
          float value;
          float direction;
       } cookie_record;

       ...
       cookie_record cookie;

       cookie.value = 0.0;
       cookie.direction = 1.0;

       BSoundPlayer player("wave_player", BufferProc, NULL, &cookie);
       player.Start();
       player.SetHasData(true);
       ...
       player.Stop();

This code establishes a record, cookie, that contains information the play buffer function will need to track, and creates a BSoundPlayer named "wave_player" that will use a function called `BufferProc()` to play sound, and uses the `cookie` we've created.

Then the player is started, and `SetHasData()` is called to let the sound player node know that there's data to be played. This will cause the play buffer function to start being called.

Once playback is over, the `Stop()` function is called to stop playback.

The `BufferProc()` function looks like this:

       void BufferProc(void *theCookie, void *buffer, size_t size,
                   const media_raw_audio_format &format) {
          size_t i, j;
          float *buf = (float *) buffer;
          size_t float_size = size/4;
          uint32 channel_count = format.channel_count;
          cookie_record *cookie = (cookie_record *) theCookie;

          // We>re going to be cheap and only work for floating-point audio

          if (format.format != media_raw_audio_format::B_AUDIO_FLOAT) {
             return;
          }

          // Now fill the buffer with sound!

          for (i=0; i<float_size; i+=channel_count) {
             for (j=0; j<channel_count; j++) {
                buf[i+j] = cookie->value;
             }
             if ((cookie->direction == 1.0) && (cookie->value >= 1.0)) {
                cookie->direction = -1.0;
             }
             else if ((cookie->direction == -1.0) && (cookie->value <= -1.0)) {
                cookie->direction = 1.0;
             }
             cookie->value += cookie->direction*(1.0/64.0);
          }
       }

This example play buffer function generates a triangle wave, ramping the wave up and down from 1.0 to -1.0 and back, over and over again, 1/64th at a time. The next value to store in the buffer and the direction in which the value is changing are kept in the cookie's fields.

| The buffers your play buffer function receives are empty. Do with them as you please (or do nothing at all).

## Hook Function

- `HasData()

  `

## Constructor and Destructor

### BSoundPlayer()

`BSoundPlayer(`

const char *name = NULL,
void (*PlayBuffer)(void *, void *buffer, size_t size, const media_raw_audio_format &format) = NULL,
void (*Notifier)(void *, sound_player_notification what, ...) = NULL,
void *cookie = NULL`)`

`BSoundPlayer(`const media_raw_audio_format * format,
const char *name = NULL,
void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format) = NULL,
void (*Notifier)(void *, sound_player_notification what, ...) = NULL,
void *cookie = NULL`)

`

`BSoundPlayer(`const media_node & toNode,
const media_multi_audio_format *format = NULL,
const char *name = NULL,
const media_input *input = NULL,
void (*PlayBuffer)(void *, void * buffer, size_t size, const media_raw_audio_format & format) = NULL,
void (*Notifier)(void *, sound_player_notification what, ...) = NULL,
void *cookie = NULL`)

`

Initializes the BSoundPlayer object. The name argument specifies the name to be assigned to the sound player node (if you specify `NULL`, a generic name will be assigned).

The PlayBuffer argument specifies a pointer to a member function that processes data and inserts it into buffers for playback; specify `NULL` if you want to use the BSoundPlayer for playing BSounds. The parameters to the PlayBuffer function are (in order):

- Pointer to the cookie.

- Pointer to the buffer to play.

- Size of the buffer.

- Format of the audio data in the buffer.

The Notifier parameter specifies a pointer to a member function that receives notifications when events of interest occur, such as playback starting or stopping. Specify `NULL` to use the default notification handler. There are three possible notifications:

- `B_STARTED` and `B_STOPPED` indicate that the BSoundPlayer was started or stopped. These receive a pointer to the BSoundPlayer object as an argument.

- `B_SOUND_DONE` indicates that a sound has finished playing. In this case, there are two arguments: the first is a play_id indicating which sound finished playing, and the other is a boolean which is `true` if the sound played at all, and `false` if the sound never played.

| If the callback handlers are members of a class, they must be static members.

The cookie parameter is a pointer that you can use for your own purposes; it's most useful if you're using a custom PlayBuffer or Notifier.

The second form of the constructor lets you specify in the format argument the format of the audio that the BSoundPlayer will perform. Since BSoundPlayer can only play raw sound formats, this is specified using the `media_raw_audio_format` structure.

The third form of the constructor lets you specify a node through which the sound should be played, and also uses a media_multi_audio_format to specify the sound's format, instead of the older media_raw_audio_format.

You should call `InitCheck()` before using your BSoundPlayer object; this will let you determine whether or not the object was successfully constructed. One situation in which `InitCheck()` might indicate an error is if the user doesn't have a sound card installed.

### ~BSoundPlayer()

`~BSoundPlayer()`

Stops playback, if sound is playing, releases references to any BSound objects that are in use by the BSoundPlayer, and frees all memory used by the BSoundPlayer.

## Member Functions

### BufferPlayer() , SetBufferPlayer()

BufferPlayerFunc `BufferPlayer(`void`)` const
void `SetBufferPlayer(`void (*PlayBuffer)(void *, void *buffer, size_t size, const media_raw_audio_format &format)`) `

`BufferPlayer()` returns a pointer to the current play buffer function, or `NULL` if the default player is in use.

`SetBufferPlayer()` lets you change the play buffer function.

### Cookie() , SetCookie()

void *`Cookie(`void`)` const
void `SetCookie(`void *cookie`) `

`Cookie()` returns the current cookie assigned to the BSoundPlayer.

`SetCookie()` lets you change the cookie assigned to the BSoundPlayer.

### CurrentTime() , PerformanceTime()

bigtime_t `CurrentTime(`void`) `
bigtime_t `PerformanceTime(`void`) `

`CurrentTime()` returns the current media time, and `PerformanceTime()` returns the current performance time of the sound player node being used by the BSoundPlayer.

`PerformanceTime()` will return `B_ERROR` if the BSoundPlayer object hasn't been properly initialized.

### EventNotifier() , SetEventNotifier()

EventNotifierFunc `EventNotifier(`void`)` const
void `SetNotifier(`void (*Notifier)(void *, sound_player_notification what, ...)`) `

`EventNotifier()` returns a pointer to the current event notification handler function, or `NULL` if the default player is in use.

`SetNotifier()` lets you change the event notification handler function.

### Format()

media_raw_audio_format `Format(`void`)` const

Returns the BSoundPlayer's format. Since the sound is always a raw sound format, the `media_raw_audio_format` structure is used.

### GetVolumeInfo()

status_t `GetVolumeInfo(`media_node *outNode, int32 *outParameter, float *outMinDB, float *outMaxDB`)` const

Returns information about the BSoundPlayer's volume control. Pass pointers to variables to be filled (`NULL` is not permitted), and on return these values will be set to describe the player as follows:

- outNode is the node to which the BSoundPlayer's audio output will be directed.

- outParameter is the parameter ID for the volume control.

- outMinDB is the minimum volume in decibels.

- outMaxDB is the maximum volume in decibels.

### HasData() , SetHasData()

bool `HasData(`void`) `
void `SetHasData(`bool hasData`) `

`HasData()` returns `true` if there's sound queued for playback, or `false` otherwise.

`SetHasData()` specifies whether or not there's sound scheduled for playback.

The purpose of these functions is to optimize the BSoundPlayer; if there's no data queued for playback, the sound player node is told this, which lets it optimize its performance. If you're using a buffer player function, you must use `SetHasData()` to indicate that there's data to play:

       SetHasData(true);

### InitCheck()

status_t `InitCheck(`void`) `

Returns the status code resulting from constructing the BSoundPlayer object. You should call this after constructing the object; if the returned value is anything other than `B_OK`, you shouldn't use the object.

### IsPlaying() see StartPlaying()

### Latency()

bigtime_t `Latency(`void`)`

Returns the BSoundPlayer's latency.

### PerformanceTime() see CurrentTime()

### SetCookie() see Cookie()

### SetBufferPlayer() see BufferPlayer()

### SetCallbacks()

void `SetCallbacks(`void (*PlayBuffer)(void *, void *buffer, size_t size, const media_raw_audio_format &format) = NULL, void (*Notifier)(void *, sound_player_notification what, ...) = NULL, void *cookie = NULL`)`

Sets the play buffer handler function, the event notification handler function, and the cookie all in one atomic operation.

### SetCookie() see Cookie()

### SetHasData() see HasData()

### SetInitError()

protected:

void `SetInitError(`status_t inError`)`

Sets the status code that will be returned by `InitCheck()`.

### SetNotifier() see EventNotifier()

### SetSoundVolume()

status_t `SetSoundVolume(`play_id sound, float volume`) `

Sets the volume (from 0.0 to 1.0) of the specified sound.

### SetVolume() see Volume()

### SetVolumeDB() see VolumeDB()

### Start() , Stop()

status_t `Start(`void`) `
void `Stop(`bool block = true, bool flush = true`) `

`Start()` activates the BSoundPlayer by starting the time source and the sound player node. The `B_STARTED` notification is sent to the BSoundPlayer's notification handler.

`Stop()` deactivates the BSoundPlayer by stopping the player node (if block is `true`, the `Stop()` function blocks until the node is stopped). If flush is `true`, the queued sounds are all deleted from memory.

While the BSoundPlayer is running, the play buffer function (if you've specified one) will be called for each buffer that passes through the BSoundPlayer's playback node. This hook function can be used to implement code that performs more advanced playback of sound, such as sound that's generated on-the-fly, or is filtered before playback.

RETURN CODES

`B_OK`. The sound playback was started.

- Other errors. As returned by the sound player's `StartNode()` function.

### StartPlaying() , StopPlaying() , WaitForSound() , IsPlaying()

play_id `StartPlaying(`BSound *sound, bigtime_t atTime = 0`) `
play_id `StartPlaying(`BSound *sound, bigtime_t atTime, float withVolume`) `
status_t `StopPlaying(`play_id id`) `
status_t `WaitForSound(`play_id id`) `
bool `IsPlaying(`play_id id`) `

`StartPlaying()` schedules the specified BSound to begin playback at the performance time specified by atTime; if atTime is 0, the sound begins playing immediately (or as soon as `Start()` is called, if the BSoundPlayer hasn't been started yet). The play_id returned by this function is used to identify the sound later. If it's negative, an error occurred (see the list below for possible values). The second form of `StartPlaying()` lets you specify a volume at which the sound should play.

`StopPlaying()` stops playing the sound specified by the given id.

`WaitForSound()` waits until the specified sound stops playing.

`IsPlaying()` returns `true` if the specified sound is playing; otherwise, it returns `false`.

RETURN CODES

`B_OK`. No error.

- `B_MEDIA_BAD_FORMAT`. The audio isn't in a supported format (`StartPlaying()`).

- `B_BAD_VALUE`. The specified id doesn't exist (`WaitForSound()` and `IsPlaying()`).

### StopPlaying() see StartPlaying()

### Volume() , SetVolume()

float `Volume(`void`) `
void `SetVolume(`float newVolume`) `

`Volume()` returns the current playback volume.

`SetVolume()` changes the playback volume.

This volume is the overall volume of all the sounds being played by the BSoundPlayer. To control the volumes of individual sounds, use the `SetSoundVolume()` function.

| The volume can range from 0.0 to 1.0, where 0.0 is silent and 1.0 is maximum loudness.

If you'd rather handle the volume using decibels instead of the percentage range, you can use the `VolumeDB()` and `SetVolumeDB()` functions.

See also: `VolumeDB()` and `SetVolumeDB()`

### VolumeDB() , SetVolumeDB()

float `VolumeDB(`void`) `
void `SetVolumeDV(`float newVolumeDB`) `

`VolumeDB()` returns the current playback volume in decibels.

`SetVolumeDB()` sets the playback volume, in decibels.

This volume is the overall volume of all the sounds being played by the BSoundPlayer. To control the volumes of individual sounds, use the `SetSoundVolume()` function.

| The possible range of volumes can be obtained by calling `GetVolumeInfo()`.

If you'd rather handle the volume using a percentage range instead of decibels, you can use the `Volume()` and `SetVolume()` functions.

See also: `Volume()` and `SetVolume()`

### WaitForSound() see StartPlaying()

## Constants

### sound_player_notification

Declared in: <be/media/SoundPlayer.h>

Constant | Meaning
--- | ---
`B_STARTED` | The BSoundPlayer has been started via the `Start()` function.
`B_STOPPED` | The BSoundPlayer's `Stop()` function has been called.
`B_SOUND_DONE` | A sound has finished playing.

These constants are passed to event notification handler functions to indicate what sort of interesting event has occurred.

## Defined Types

### play_id

Declared in: <be/media/SoundPlayer.h>

    typedef int32 play_id;

Identifies a particular sound that's being played by the BSoundPlayer; `StartPlaying()` returns values of this type.

The Media Kit Table of Contents | The Media Kit Index

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

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