^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ BE ENGINEERING INSIGHTS: Farewell BSound and BSoundFile (All Hail BGameSound and BMediaFile) By Jon Watte -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Among other important improvements in BeOS Release 4.5 is the BMediaFile, which gives access to various kinds of media file formats, and BGameSound (with subclasses), which allows simple but efficient playback of sound effects and background sounds. The BSoundFile class has been with us for a long time, and was starting to show its age. Many older programs that still run on PowerPC depend on idiosyncrasies of this class, so rather than make it use the same mechanism as BMediaFile to access data, which would break the previous semantic of the file (we tried this), we decided to stay compatible, and suggest that all newer applications use BMediaFile for all their media reading/writing needs. However, if you have an application which uses BSoundFile, you may need some features that BMediaFile and BMediaTrack don't provide. Most notably, BMediaTrack reads audio frames in blocks of a predetermined size, whereas BSoundFile lets you read any number of frames at any time. BMediaTrack also may not be precise in seeking to a specified frame location (because of compression algorithm constraints). I present here a simple wrapper for BMediaTrack, known as ATrackReader. It lets you treat a generic media file, accessed internally through a BMediaFile object, much like a BSoundFile. It's also a good introduction to using BMediaFile/BMediaTrack to read data in general. If you use a BSoundPlayer with a number of BSounds to play sound effects, you'll probably want to change over to the new BGameSound system the next time you overhaul your code. BGameSound is designed to allow for hardware acceleration in a future version of BeOS (when this will happen is TBD), and it's also designed to be really simple to use! If you used BSound with a chunk of data in memory as your data, you now create a BSimpleGameSound object. If you use BSound with a large-ish sound file on disk for background music or other something similar, you now create a BFileGameSound. BSimpleGameSound can be created either with a pointer to data and a description of the data pointed to (it should be uncompressed PCM sample data), or with an entry_ref, in which case it will load the sound file from disk (uncompressing, if necessary) into memory so it's always readily available to be played. The BGameSound system makes a copy of the data you provide it, so you can free that memory as soon as the object is created. If you need more than one copy of the same sound running, you can call Clone() to get a second BSimpleGameSound which references the same data as the first. When you make a Clone(), that clone references the same internal copy with a reference count, so no extra memory is wasted. The Be Book accidentally documents an earlier behaviour where data was copied inside Clone(). To play the sound, just call StartPlaying() on it. BFileGameSound is created with an entry_ref as argument, and can optionally be set to looping or non-looping mode. When you call StartPlaying(), it will start playing, and keep going until you stop it with StopPlaying(), or, if it's not looping, until it reaches the end of the file. It's important to note that the first BGameSound instance you create determines the format of the connection between BGameSound and the Audio Mixer. In our sample program, we create a dummy 44 kHz stereo sound and immediately delete it to establish the connection in a known format, since otherwise the first file the user drags into the program will determine the format that all files will be played back as. All BGameSound instances that are playing are mixed into one connection to the Audio Mixer; this connection is currently named after your application with no way of changing it. In some future version of the API, we may let you create more than one connection, and name these connections. That's what the BGameSoundDevice argument is for in the constructors for these classes; however, we currently only support the default (NULL) device, so you can leave it to the default value without worrying about it. If you want to set the pan position or gain (volume) of a BGameSound, you do that by calling SetPan() and SetGain(). The "duration" parameter (which is optional) allows you to specify that the change should take place over some amount of time, if the sound is currently playing. Thus, if a file was playing, and you wanted to fade it out over the course of two seconds for a soft ending, you could call SetGain(0.0, 2000000LL). You can also change the effective sampling rate of a BGameSound. This changes both the pitch and duration of the sound. The BGameSound system contains a built-in software resampler which uses a fast, reasonable quality 0-th order resampler. There is no additional overhead of playing a sound at some other sampling frequency than the one you initially specify. However, there is no SetSamplingRate() function; instead, you have to use the low-level SetAttributes() function to change the B_GS_SAMPLING_RATE attribute. Again, you can specify a duration during which the change ramps in. Thus, if you're playing a sound at a 22000 Hz sampling rate, and ramp it to 12000 Hz with a duration of 500000, it will take approximately half a second for the full change to take effect. The resulting sound effect is similar to a tape deck or record slowing down. Specific details are found in the gameplay.cpp file in the source code that goes with this article: . To build the sample code, just "cd" to the directory where you unpacked it in Terminal, and type "make". Run it with obj.x86/gameplay (or obj.ppc/gameplay) from the command line, or double-click it. You can drag a sound file into the lower half of the window, and the program will load it as a BSimpleGameSound or a BFileGameSound. You can then start playing with the "Start" button, and play with volume/sampling rate with the sliders in the window. Note that the pop-up menu for sound kind (SimpleGameSound or FileGameSound) only decides what kind of object to create the next time you drag a file to the window; it does not change the type of the current sound.