409 lines
8.5 KiB
C++
409 lines
8.5 KiB
C++
//------------------------------------------------------------------------------
|
|||
|
|
// Copyright (c) 2001-2002, OpenBeOS
|
||
|
|
//
|
||
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
|
// copy of this software and associated documentation files (the "Software"),
|
||
|
|
// to deal in the Software without restriction, including without limitation
|
||
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||
|
|
// Software is furnished to do so, subject to the following conditions:
|
||
|
|
//
|
||
|
|
// The above copyright notice and this permission notice shall be included in
|
||
|
|
// all copies or substantial portions of the Software.
|
||
|
|
//
|
||
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
|
// DEALINGS IN THE SOFTWARE.
|
||
|
|
//
|
||
|
|
// File Name: SimpleGameSound.h
|
||
|
|
// Author: Christopher ML Zumwalt May ([email protected])
|
||
|
|
// Description: BSimpleGameSound is a class for sound effects that are
|
||
|
|
// short, and consists of non-changing samples in memory.
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
#include <malloc.h>
|
||
|
|
#include <memory.h>
|
||
|
|
|
||
|
|
#include <Entry.h>
|
||
|
|
#include <MediaFile.h>
|
||
|
|
#include <MediaTrack.h>
|
||
|
|||
#include "GameSoundDefs.h"
|
|||
|
|
#include "GameSoundBuffer.h"
|
||
|
|
#include "GameSoundDevice.h"
|
||
|
|
#include "GSUtility.h"
|
||
|
|||
#include <SimpleGameSound.h>
|
|||
|
|
|
||
|
|
BSimpleGameSound::BSimpleGameSound(const entry_ref *inFile,
|
||
|
|
BGameSoundDevice *device)
|
||
: BGameSound(device)
|
|||
{
|
|||
if (InitCheck() == B_OK) SetInitError(Init(inFile));
|
|||
}
|
|||
|
|
|
||
|
|
|
||
|
|
BSimpleGameSound::BSimpleGameSound(const char *inFile,
|
||
|
|
BGameSoundDevice *device)
|
||
: BGameSound(device)
|
|||
{
|
|||
if (InitCheck() == B_OK)
|
|||
|
|
{
|
||
|
|
entry_ref file;
|
||
|
|
|
||
|
|
if (get_ref_for_path(inFile, &file) != B_OK)
|
||
|
|
SetInitError(B_ENTRY_NOT_FOUND);
|
||
|
|
else
|
||
|
|
SetInitError(Init(&file));
|
||
|
|
}
|
||
}
|
|||
|
|
|
||
|
|
|
||
|
|
BSimpleGameSound::BSimpleGameSound(const void *inData,
|
||
|
|
size_t inFrameCount,
|
||
|
|
const gs_audio_format *format,
|
||
|
|
BGameSoundDevice *device)
|
||
: BGameSound(device)
|
|||
{
|
|||
if (InitCheck() == B_OK) SetInitError(Init(inData, inFrameCount, format));
|
|||
}
|
|||
|
|
|
||
|
|
|
||
|
|
BSimpleGameSound::BSimpleGameSound(const BSimpleGameSound &other)
|
||
: BGameSound(other)
|
|||
|
|
{
|
||
|
|
gs_audio_format format;
|
||
|
|
void * data;
|
||
|
|
|
||
|
|
status_t error = other.Device()->Buffer(other.ID(), &format, data);
|
||
|
|
if (error != B_OK) SetInitError(error);
|
||
|
|
|
||
|
|
Init(data, 0, &format);
|
||
|
|
free(data);
|
||
}
|
|||
|
|||
BSimpleGameSound::~BSimpleGameSound()
|
|||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
BGameSound *
|
||
|
|
BSimpleGameSound::Clone() const
|
||
|
|
{
|
||
gs_audio_format format;
|
|||
|
|
void * data;
|
||
|
|
|
||
|
|
status_t error = Device()->Buffer(ID(), &format, data);
|
||
|
|
if (error != B_OK) return NULL;
|
||
|
|
|
||
|
|
BSimpleGameSound * clone = new BSimpleGameSound(data, 0, &format, Device());
|
||
|
|
|
||
|
|
free(data);
|
||
|
|
|
||
|
|
return clone;
|
||
}
|
|||
|
|
|
||
|
|
status_t
|
||
BSimpleGameSound::SetIsLooping(bool looping)
|
|||
{
|
|||
gs_attribute attribute;
|
|||
|
|
|
||
|
|
attribute.attribute = B_GS_LOOPING;
|
||
|
|
attribute.value = (looping) ? -1.0 : 0.0;
|
||
|
|
attribute.duration = bigtime_t(0);
|
||
|
|
attribute.flags = 0;
|
||
|
|
|
||
|
|
return Device()->SetAttributes(ID(), &attribute, 1);
|
||
}
|
|||
|
|
|
||
|
|
|
||
bool
|
|||
|
|
BSimpleGameSound::IsLooping() const
|
||
|
|
{
|
||
|
|
gs_attribute attribute;
|
||
|
|
|
||
|
|
attribute.attribute = B_GS_LOOPING;
|
||
|
|
attribute.flags = 0;
|
||
|
|
|
||
|
|
if (Device()->GetAttributes(ID(), &attribute, 1) != B_OK)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
return bool(attribute.value);
|
||
|
|
}
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::Init(const entry_ref* inFile)
|
||
|
|
{
|
||
|
|
BMediaFile file(inFile);
|
||
|
|
gs_audio_format gsformat;
|
||
|
|
media_format mformat;
|
||
|
|
int64 framesRead, framesTotal = 0;
|
||
|
|
|
||
|
|
if (file.InitCheck() != B_OK) return file.InitCheck();
|
||
|
|
|
||
|
|
BMediaTrack* audioStream = file.TrackAt(0);
|
||
|
|
audioStream->EncodedFormat(&mformat);
|
||
|
|
if (!mformat.IsAudio()) return B_ERROR;
|
||
|
|
|
||
|
|
int64 frames = audioStream->CountFrames();
|
||
|
|
|
||
|
|
memset(&mformat, 0, sizeof(media_format));
|
||
|
|
mformat.type = B_MEDIA_RAW_AUDIO;
|
||
// mformat.u.raw_audio.byte_order = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
|
|||
|
|
status_t error = audioStream->DecodedFormat(&mformat);
|
||
|
|
if (error != B_OK) return error;
|
||
|
|||
|
|
memset(&gsformat, 0, sizeof(gs_audio_format));
|
||
media_to_gs_format(&gsformat, &mformat.u.raw_audio);
|
|||
|
|||
|
|
if (mformat.u.raw_audio.format == media_raw_audio_format::B_AUDIO_CHAR)
|
||
|
|
{
|
||
|
|
// The GameKit doesnt support this format so we will have to reformat
|
||
|
|
// the data into something the GameKit does support.
|
||
|
|
char * buffer = new char[gsformat.buffer_size];
|
||
|
|
uchar * data = new uchar[frames * gsformat.channel_count];
|
||
|
|
|
||
|
|
while (framesTotal < frames)
|
||
|
|
{
|
||
|
|
// read the next chunck from the stream
|
||
|
|
memset(buffer, 0, gsformat.buffer_size);
|
||
|
|
audioStream->ReadFrames(buffer, &framesRead);
|
||
|
|
|
||
|
|
// refomat the buffer from
|
||
|
|
int64 position = framesTotal * gsformat.channel_count;
|
||
|
|
for(int32 i = 0; i < (int32)gsformat.buffer_size; i++)
|
||
|
|
data[i + position] = buffer[i] + 128;
|
||
|
|
|
||
|
|
framesTotal += framesRead;
|
||
|
|
}
|
||
|
|
|
||
|
|
gsformat.format = gs_audio_format::B_GS_U8;
|
||
|
|
|
||
error = Init(data, frames, &gsformat);
|
|||
|
|||
|
|
// free the buffers we no longer need
|
||
|
|
delete [] buffer;
|
||
|
|
delete [] data;
|
||
|
|
}
|
||
else
|
|||
{
|
|||
// We need to detriman the size, in bytes, of a single sample.
|
|||
|
|
// At the same time, we will store the format of the audio buffer
|
||
|
|
size_t frameSize = get_sample_size(gsformat.format) * gsformat.channel_count;
|
||
|
|
char * data = new char[frames * frameSize];
|
||
|
|
gsformat.buffer_size = frames * frameSize;
|
||
|
|||
while(framesTotal < frames)
|
|||
|
|
{
|
||
|
|
char * position = &data[framesTotal * frameSize];
|
||
|
|
audioStream->ReadFrames(position, &framesRead);
|
||
|
|||
framesTotal += framesRead;
|
|||
|
|
}
|
||
|
|||
error = Init(data, frames, &gsformat);
|
|||
|
|||
delete [] data;
|
|||
|
|
}
|
||
|
|
|
||
file.ReleaseTrack(audioStream);
|
|||
return error;
|
|||
}
|
|||
|
|
|
||
|
|||
status_t
|
|||
|
|
BSimpleGameSound::Init(const void* inData,
|
||
|
|
int64 inFrameCount,
|
||
|
|
const gs_audio_format* format)
|
||
{
|
|||
gs_id sound;
|
|||
|
|
|
||
|
|
status_t error = Device()->CreateBuffer(&sound, format, inData, inFrameCount);
|
||
|
|
if (error != B_OK) return error;
|
||
|
|
|
||
|
|
BGameSound::Init(sound);
|
||
|
|
|
||
|
|
return B_OK;
|
||
}
|
|||
|
|
|
||
|
|
|
||
|
|
/* unimplemented for protection of the user:
|
||
|
|
*
|
||
|
|
* BSimpleGameSound::BSimpleGameSound()
|
||
|
|
* BSimpleGameSound &BSimpleGameSound::operator=(const BSimpleGameSound &)
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_0(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_1(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_2(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_3(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_4(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_5(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_6(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_7(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_8(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_9(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_10(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_11(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_12(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_13(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_14(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_15(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_16(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_17(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_18(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_19(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_20(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_21(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_22(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
status_t
|
||
|
|
BSimpleGameSound::_Reserved_BSimpleGameSound_23(int32 arg, ...)
|
||
|
|
{
|
||
|
|
return B_ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|