The Be Book The Game Kit The Game Kit Index

BPushGameSound

Derived from: BStreamingGameSound
Declared in:  be/game/PushGameSound.h
Library: libgame.so
Allocation: Constructor only
Summary:  more...


The BPushGameSound class lets you push buffers of audio data, instead of waiting to be asked for them.


How It Works

The BPushGameSound class uses a single sound buffer, consisting of multiple pages, which play continuously in a loop. Each page is used to construct an audio BBuffer that eventually gets played, and is then recycled and reused again later.

For example, if the sound buffer is 256 kilobytes, and each page is 4 kilobytes, there are 64 pages of audio. When you start the BPushGameSound object, playback begins with the first page. A BBuffer is constructed using that page, then played, and then the buffer is recycled, and the next page is used to create another BBuffer, and so forth. This continues to the 64th page. Once that page is played, playback loops back to the first page again.

Your code pushes audio data into these audio pages. There are two ways you can do this.

Exclusive Access

The first way is to ask the BPushGameSound class to give you a page to fill with audio data. This is done by calling LockNextPage(). This gives you exclusive access to the next audio page that needs to be filled; you can fill it with whatever sound you want to push, then call UnlockPage() to release it. It won't be played while it's locked, so you need to stuff your sound into it and release it as quickly as possible.

The Neverending Story

The second way takes better planning, but can give you lower overhead. Call LockForCyclic() to request access to the entire sound buffer area. This doesn't give you exclusive access, so playback never stops—it keeps looping the entire time, while you write into it. The CurrentPosition() function tells you where in the buffer area playback is currently occurring.

Your mission (should you choose to accept it) is to stuff audio into the buffer, keeping ahead of this position far enough that playback never catches up to you. As a general rule, you should try to stay at least a page ahead of the current playback position. Keep in mind that when you reach the end of the buffer area, you need to wrap back to the beginning.

This takes more careful effort on your part, but once you have your code properly tuned, you can get very low overhead audio playback this way.


Constructor and Destructor


BPushGameSound()

BPushGameSound(size_t inBufferFrameCount,
      const gs_audio_format *format,
      size_t inBufferCount = 2,
      BGameSoundDevice *device = NULL)

Prepares the object to play audio pushed by your application. inBufferFrameCount specifies the number of frames each audio buffer should be able to hold. format indicates the audio format that will be streamed. inBufferCount specifies the number of buffers to use, and, as always, device is the sound device to use for playback.

Currently, device must always be NULL to indicate that the default playback device should be used.

By default, two audio buffers are used.

Be sure to call InitCheck() before using the BPushGameSound object.


~BPushGameSound

virtual ~BPushGameSound()

Deletes the semaphore used to lock the object.


Member Functions


CurrentPosition() see LockForCyclic()


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.


LockForCyclic() , UnlockCyclic() , CurrentPosition()

virtual lock_status LockForCyclic(void **outBasePtr, size_t *outSize)
virtual status_t UnlockCyclic(void)
virtual size_t CurrentPosition(void)

LockForCyclic() gives you access to the entire sound buffer; audio playback continues while you have access. Use CurrentPosition() to determine where the playback is currently located in the buffer area, and be sure to stay well ahead of it. See the overview for a more in-depth discussion. If lock_failed is returned, you can't access the audio area, but if lock_ok is returned, you can start pushing audio.

On return, outBasePtr points to the first byte of the audio buffer area, and outSize indicates the total size of the audio buffer area.

UnlockCyclic() releases the audio area.

RETURN CODES


UnlockCyclic() see LockForCyclic()


LockNextPage() , UnlockPage()

virtual lock_status LockNextPage(void **outPagePtr, size_t *outPageSize)
virtual status_t UnlockPage(void *inPagePtr)

LockNextPage() requests access to the next page of the sound buffer. The return value is lock_ok or lock_ok_frames_dropped if a valid page has been returned. If either of these values is returned, you can then write up to outPageSize bytes of audio data into the audio page returned in outPagePtr.

If lock_failed is returned, you can't access an audio page.

UnlockPage() releases the audio page pointed to by inPagePtr.

RETURN CODES


UnlockPage() see LockNextPage()


Constants


lock_status

Declared in:  be/game/PushGameSound.h

Constant Description
lock_failed Couldn't get the lock; it's not time to update yet.
lock_ok Locked; you can update.
lock_ok_frames_dropped Lccked; you can update, but you may have missed some buffers.

These values are returned by the locking functions in the BPushGameSound class (LockNextPage() and LockForCyclic()). If either function returns lock_failed, there isn't a buffer to be filled; your code is pushing buffers too fast.

If lock_ok is returned, the next buffer is ready. The lock_ok_frames_dropped result is received if a buffer is available but some buffers have been lost; this can happen if you're not pushing fast enough.


The Be Book The Game Kit The Game Kit Index

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

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