game kit: Style and whitespace cleanup. No functional change.

This commit is contained in:
Alexander von Gluck IV
2012-02-08 17:38:59 -06:00
parent 1b6bc2675f
commit 2066acfbc5
10 changed files with 547 additions and 477 deletions
+64 -47
View File
@@ -1,12 +1,13 @@
/* /*
* Copyright 2001-2007, Haiku Inc. * Copyright 2001-2012 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors: * Authors:
* Christopher ML Zumwalt May ([email protected]) * Christopher ML Zumwalt May ([email protected])
* Jérôme Duval * Jérôme Duval
*
* Distributed under the terms of the MIT License.
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -20,6 +21,7 @@
#include "GameSoundDevice.h" #include "GameSoundDevice.h"
#include "GSUtility.h" #include "GSUtility.h"
const int32 kPages = 20; const int32 kPages = 20;
struct _gs_media_tracker struct _gs_media_tracker
{ {
@@ -29,8 +31,10 @@ struct _gs_media_tracker
size_t position; size_t position;
}; };
// Local utility functions ----------------------------------------------- // Local utility functions -----------------------------------------------
bool FillBuffer(_gs_ramp * ramp, uint8 * data, uint8 * buffer, size_t * bytes) bool
FillBuffer(_gs_ramp * ramp, uint8 * data, uint8 * buffer, size_t * bytes)
{ {
int32 samples = *bytes / sizeof(uint8); int32 samples = *bytes / sizeof(uint8);
@@ -47,7 +51,9 @@ bool FillBuffer(_gs_ramp * ramp, uint8 * data, uint8 * buffer, size_t * bytes)
return false; return false;
} }
bool FillBuffer(_gs_ramp * ramp, int16 * data, int16 * buffer, size_t * bytes)
bool
FillBuffer(_gs_ramp * ramp, int16 * data, int16 * buffer, size_t * bytes)
{ {
int32 samples = *bytes / sizeof(int16); int32 samples = *bytes / sizeof(int16);
@@ -64,7 +70,9 @@ bool FillBuffer(_gs_ramp * ramp, int16 * data, int16 * buffer, size_t * bytes)
return false; return false;
} }
bool FillBuffer(_gs_ramp * ramp, int32 * data, int32 * buffer, size_t * bytes)
bool
FillBuffer(_gs_ramp * ramp, int32 * data, int32 * buffer, size_t * bytes)
{ {
size_t byte = 0; size_t byte = 0;
bool bytesAreReady = (*bytes > 0); bool bytesAreReady = (*bytes > 0);
@@ -85,7 +93,9 @@ bool FillBuffer(_gs_ramp * ramp, int32 * data, int32 * buffer, size_t * bytes)
return false; return false;
} }
bool FillBuffer(_gs_ramp * ramp, float * data, float * buffer, size_t * bytes)
bool
FillBuffer(_gs_ramp * ramp, float * data, float * buffer, size_t * bytes)
{ {
size_t byte = 0; size_t byte = 0;
bool bytesAreReady = (*bytes > 0); bool bytesAreReady = (*bytes > 0);
@@ -106,37 +116,38 @@ bool FillBuffer(_gs_ramp * ramp, float * data, float * buffer, size_t * bytes)
return false; return false;
} }
// BFileGameSound ------------------------------------------------------- // BFileGameSound -------------------------------------------------------
BFileGameSound::BFileGameSound(const entry_ref *file, BFileGameSound::BFileGameSound(const entry_ref *file, bool looping,
bool looping, BGameSoundDevice *device)
BGameSoundDevice *device) :
: BStreamingGameSound(device), BStreamingGameSound(device),
fAudioStream(NULL), fAudioStream(NULL),
fStopping(false), fStopping(false),
fLooping(looping), fLooping(looping),
fBuffer(NULL), fBuffer(NULL),
fPlayPosition(0), fPlayPosition(0),
fPausing(NULL), fPausing(NULL),
fPaused(false), fPaused(false),
fPauseGain(1.0) fPauseGain(1.0)
{ {
if (InitCheck() == B_OK) if (InitCheck() == B_OK)
SetInitError(Init(file)); SetInitError(Init(file));
} }
BFileGameSound::BFileGameSound(const char *file, BFileGameSound::BFileGameSound(const char *file, bool looping,
bool looping, BGameSoundDevice *device)
BGameSoundDevice *device) :
: BStreamingGameSound(device), BStreamingGameSound(device),
fAudioStream(NULL), fAudioStream(NULL),
fStopping(false), fStopping(false),
fLooping(looping), fLooping(looping),
fBuffer(NULL), fBuffer(NULL),
fPlayPosition(0), fPlayPosition(0),
fPausing(NULL), fPausing(NULL),
fPaused(false), fPaused(false),
fPauseGain(1.0) fPauseGain(1.0)
{ {
if (InitCheck() == B_OK) { if (InitCheck() == B_OK) {
entry_ref node; entry_ref node;
@@ -221,8 +232,7 @@ BFileGameSound::Preload()
void void
BFileGameSound::FillBuffer(void *inBuffer, BFileGameSound::FillBuffer(void *inBuffer, size_t inByteCount)
size_t inByteCount)
{ {
// Split or combine decoder buffers into mixer buffers // Split or combine decoder buffers into mixer buffers
// fPlayPosition is where we got up to in the input buffer after last call // fPlayPosition is where we got up to in the input buffer after last call
@@ -231,7 +241,8 @@ BFileGameSound::FillBuffer(void *inBuffer,
while (inByteCount > 0 && !fPaused) { while (inByteCount > 0 && !fPaused) {
if (!fPaused || fPausing) { if (!fPaused || fPausing) {
printf("mixout %ld, inByteCount %ld, decin %ld, BufferSize %ld\n",out_offset, inByteCount, fPlayPosition, fBufferSize); printf("mixout %ld, inByteCount %ld, decin %ld, BufferSize %ld\n",
out_offset, inByteCount, fPlayPosition, fBufferSize);
if (fPlayPosition == 0 || fPlayPosition >= fBufferSize) { if (fPlayPosition == 0 || fPlayPosition >= fBufferSize) {
Load(); Load();
} }
@@ -251,19 +262,27 @@ BFileGameSound::FillBuffer(void *inBuffer,
switch(Format().format) { switch(Format().format) {
case gs_audio_format::B_GS_U8: case gs_audio_format::B_GS_U8:
rampDone = ::FillBuffer(fPausing, (uint8*)&buffer[out_offset], (uint8*)&fBuffer[fPlayPosition], &bytes); rampDone = ::FillBuffer(fPausing,
(uint8*)&buffer[out_offset],
(uint8*)&fBuffer[fPlayPosition], &bytes);
break; break;
case gs_audio_format::B_GS_S16: case gs_audio_format::B_GS_S16:
rampDone = ::FillBuffer(fPausing, (int16*)&buffer[out_offset], (int16*)&fBuffer[fPlayPosition], &bytes); rampDone = ::FillBuffer(fPausing,
(int16*)&buffer[out_offset],
(int16*)&fBuffer[fPlayPosition], &bytes);
break; break;
case gs_audio_format::B_GS_S32: case gs_audio_format::B_GS_S32:
rampDone = ::FillBuffer(fPausing, (int32*)&buffer[out_offset], (int32*)&fBuffer[fPlayPosition], &bytes); rampDone = ::FillBuffer(fPausing,
(int32*)&buffer[out_offset],
(int32*)&fBuffer[fPlayPosition], &bytes);
break; break;
case gs_audio_format::B_GS_F: case gs_audio_format::B_GS_F:
rampDone = ::FillBuffer(fPausing, (float*)&buffer[out_offset], (float*)&fBuffer[fPlayPosition], &bytes); rampDone = ::FillBuffer(fPausing,
(float*)&buffer[out_offset],
(float*)&fBuffer[fPlayPosition], &bytes);
break; break;
} }
@@ -274,8 +293,8 @@ BFileGameSound::FillBuffer(void *inBuffer,
// We finished ramping // We finished ramping
if (rampDone) { if (rampDone) {
// We need to be able to stop asap when the pause flag is flipped. // Need to be able to stop asap when pause flag is flipped.
while(fPlayPosition < fBufferSize && (inByteCount > 0)) { while (fPlayPosition < fBufferSize && (inByteCount > 0)) {
buffer[out_offset++] = fBuffer[fPlayPosition++]; buffer[out_offset++] = fBuffer[fPlayPosition++];
inByteCount--; inByteCount--;
} }
@@ -289,8 +308,9 @@ BFileGameSound::FillBuffer(void *inBuffer,
char * buffer = (char*)inBuffer; char * buffer = (char*)inBuffer;
// We need to be able to stop asap when the pause flag is flipped. // Need to be able to stop asap when the pause flag is flipped.
while(fPlayPosition < fBufferSize && (!fPaused || fPausing) && (inByteCount > 0)) { while (fPlayPosition < fBufferSize && (!fPaused || fPausing)
&& (inByteCount > 0)) {
buffer[out_offset++] = fBuffer[fPlayPosition++]; buffer[out_offset++] = fBuffer[fPlayPosition++];
inByteCount--; inByteCount--;
} }
@@ -309,8 +329,7 @@ BFileGameSound::Perform(int32 selector,
status_t status_t
BFileGameSound::SetPaused(bool isPaused, BFileGameSound::SetPaused(bool isPaused, bigtime_t rampTime)
bigtime_t rampTime)
{ {
if (fPaused != isPaused) { if (fPaused != isPaused) {
Lock(); Lock();
@@ -429,7 +448,7 @@ BFileGameSound::Load()
{ {
if (!fAudioStream || !fAudioStream->stream) if (!fAudioStream || !fAudioStream->stream)
return false; return false;
// read a new buffer // read a new buffer
int64 frames = 0; int64 frames = 0;
fAudioStream->stream->ReadFrames(fBuffer, &frames); fAudioStream->stream->ReadFrames(fBuffer, &frames);
@@ -632,5 +651,3 @@ BFileGameSound::_Reserved_BFileGameSound_23(int32 arg, ...)
{ {
return B_ERROR; return B_ERROR;
} }
+30 -29
View File
@@ -1,62 +1,63 @@
/* /*
* Copyright 2001-2002, Haiku Inc. * Copyright 2001-2012 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors: * Authors:
* Christopher ML Zumwalt May ([email protected]) * Christopher ML Zumwalt May ([email protected])
*
* Distributed under the terms of the MIT License.
*/ */
#include "GSUtility.h"
#include <GameSoundDefs.h> #include <GameSoundDefs.h>
#include <MediaDefs.h> #include <MediaDefs.h>
#include <new> #include <new>
#include "GSUtility.h"
_gs_ramp*
_gs_ramp*
InitRamp(float* value, float set, float frames, bigtime_t duration) InitRamp(float* value, float set, float frames, bigtime_t duration)
{ {
float diff = (set > *value) ? set - *value : *value - set; float diff = (set > *value) ? set - *value : *value - set;
bigtime_t sec = bigtime_t(duration / 1000000.0); bigtime_t sec = bigtime_t(duration / 1000000.0);
float inc = diff * 200; float inc = diff * 200;
_gs_ramp* ramp = new (std::nothrow) _gs_ramp; _gs_ramp* ramp = new (std::nothrow) _gs_ramp;
if (ramp != NULL) { if (ramp != NULL) {
ramp->value = value; ramp->value = value;
ramp->frame_total = frames * sec; ramp->frame_total = frames * sec;
ramp->frame_inc = int(ramp->frame_total / inc); ramp->frame_inc = int(ramp->frame_total / inc);
ramp->inc = (set - *value) / inc; ramp->inc = (set - *value) / inc;
ramp->frame_count = 0; ramp->frame_count = 0;
ramp->frame_inc_count = 0; ramp->frame_inc_count = 0;
ramp->duration = duration; ramp->duration = duration;
} }
return ramp; return ramp;
} }
bool
bool
ChangeRamp(_gs_ramp* ramp) ChangeRamp(_gs_ramp* ramp)
{ {
if (ramp->frame_count > ramp->frame_total) if (ramp->frame_count > ramp->frame_total)
return true; return true;
if (ramp->frame_inc_count >= ramp->frame_inc) { if (ramp->frame_inc_count >= ramp->frame_inc) {
ramp->frame_inc_count = 0; ramp->frame_inc_count = 0;
*ramp->value += ramp->inc; *ramp->value += ramp->inc;
} else } else
ramp->frame_inc_count++; ramp->frame_inc_count++;
ramp->frame_count++; ramp->frame_count++;
return false; return false;
} }
size_t size_t
get_sample_size(int32 format) get_sample_size(int32 format)
{ {
size_t sample; size_t sample;
@@ -65,38 +66,38 @@ get_sample_size(int32 format)
case media_raw_audio_format::B_AUDIO_CHAR: case media_raw_audio_format::B_AUDIO_CHAR:
sample = sizeof(char); sample = sizeof(char);
break; break;
case gs_audio_format::B_GS_U8: case gs_audio_format::B_GS_U8:
sample = sizeof(uint8); sample = sizeof(uint8);
break; break;
case gs_audio_format::B_GS_S16: case gs_audio_format::B_GS_S16:
sample = sizeof(int16); sample = sizeof(int16);
break; break;
case gs_audio_format::B_GS_S32: case gs_audio_format::B_GS_S32:
sample = sizeof(int32); sample = sizeof(int32);
break; break;
case gs_audio_format::B_GS_F: case gs_audio_format::B_GS_F:
sample = sizeof(float); sample = sizeof(float);
break; break;
default: default:
sample = 0; sample = 0;
break; break;
} }
return sample; return sample;
} }
void void
media_to_gs_format(gs_audio_format* dest, media_raw_audio_format* source) media_to_gs_format(gs_audio_format* dest, media_raw_audio_format* source)
{ {
dest->format = source->format; dest->format = source->format;
dest->frame_rate = source->frame_rate; dest->frame_rate = source->frame_rate;
dest->channel_count = source->channel_count; dest->channel_count = source->channel_count;
dest->byte_order = source->byte_order; dest->byte_order = source->byte_order;
dest->buffer_size = source->buffer_size; dest->buffer_size = source->buffer_size;
} }
+13 -10
View File
@@ -23,32 +23,35 @@
// Author: Christopher ML Zumwalt May ([email protected]) // Author: Christopher ML Zumwalt May ([email protected])
// Description: Utility functions used by sound system // Description: Utility functions used by sound system
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifndef _GAMESOUND_UTILITY_H #ifndef _GAMESOUND_UTILITY_H
#define _GAMESOUND_UTILITY_H #define _GAMESOUND_UTILITY_H
#include <GameSoundDefs.h> #include <GameSoundDefs.h>
#include <MediaDefs.h> #include <MediaDefs.h>
struct _gs_ramp struct _gs_ramp
{ {
float inc; float inc;
float orignal; float orignal;
float* value; float* value;
float frame_total; float frame_total;
float frame_inc; float frame_inc;
float frame_count; float frame_count;
float frame_inc_count; float frame_inc_count;
bigtime_t duration; bigtime_t duration;
}; };
_gs_ramp* InitRamp(float* value, float set, float frames, bigtime_t duration);
bool ChangeRamp(_gs_ramp* ramp); _gs_ramp* InitRamp(float* value, float set, float frames, bigtime_t duration);
size_t get_sample_size(int32 format); bool ChangeRamp(_gs_ramp* ramp);
void media_to_gs_format(gs_audio_format * dest, media_raw_audio_format * source); size_t get_sample_size(int32 format);
void media_to_gs_format(gs_audio_format* dest,
media_raw_audio_format* source);
#endif #endif
+158 -124
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2010 Haiku Inc. All rights reserved. * Copyright 2002-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -12,6 +12,8 @@
*/ */
#include "GameProducer.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@@ -26,20 +28,18 @@
#include "GameSoundDevice.h" #include "GameSoundDevice.h"
#include "GSUtility.h" #include "GSUtility.h"
#include "GameProducer.h"
struct _gs_play { struct _gs_play {
gs_id sound; gs_id sound;
bool* hook; bool* hook;
_gs_play* next; _gs_play* next;
_gs_play* previous; _gs_play* previous;
}; };
GameProducer::GameProducer(GameSoundBuffer* object, GameProducer::GameProducer(GameSoundBuffer* object,
const gs_audio_format* format) const gs_audio_format* format)
: :
BMediaNode("GameProducer.h"), BMediaNode("GameProducer.h"),
BBufferProducer(B_MEDIA_RAW_AUDIO), BBufferProducer(B_MEDIA_RAW_AUDIO),
@@ -53,19 +53,21 @@ GameProducer::GameProducer(GameSoundBuffer* object,
fPreferredFormat.type = B_MEDIA_RAW_AUDIO; fPreferredFormat.type = B_MEDIA_RAW_AUDIO;
fPreferredFormat.u.raw_audio.format = format->format; fPreferredFormat.u.raw_audio.format = format->format;
fPreferredFormat.u.raw_audio.channel_count = format->channel_count; fPreferredFormat.u.raw_audio.channel_count = format->channel_count;
fPreferredFormat.u.raw_audio.frame_rate = format->frame_rate; // measured in Hertz fPreferredFormat.u.raw_audio.frame_rate = format->frame_rate; // Hertz
fPreferredFormat.u.raw_audio.byte_order = format->byte_order; fPreferredFormat.u.raw_audio.byte_order = format->byte_order;
// fPreferredFormat.u.raw_audio.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; // fPreferredFormat.u.raw_audio.channel_mask
// = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
// fPreferredFormat.u.raw_audio.valid_bits = 32; // fPreferredFormat.u.raw_audio.valid_bits = 32;
// fPreferredFormat.u.raw_audio.matrix_mask = B_MATRIX_AMBISONIC_WXYZ; // fPreferredFormat.u.raw_audio.matrix_mask = B_MATRIX_AMBISONIC_WXYZ;
// we'll use the consumer's preferred buffer size, if any // we'll use the consumer's preferred buffer size, if any
fPreferredFormat.u.raw_audio.buffer_size = media_raw_audio_format::wildcard.buffer_size; fPreferredFormat.u.raw_audio.buffer_size
= media_raw_audio_format::wildcard.buffer_size;
// we're not connected yet // we're not connected yet
fOutput.destination = media_destination::null; fOutput.destination = media_destination::null;
fOutput.format = fPreferredFormat; fOutput.format = fPreferredFormat;
fFrameSize = get_sample_size(format->format) * format->channel_count; fFrameSize = get_sample_size(format->format) * format->channel_count;
fObject = object; fObject = object;
} }
@@ -87,19 +89,20 @@ GameProducer::AddOn(int32 *internal_id) const
// BBufferProducer methods // BBufferProducer methods
status_t status_t
GameProducer::GetNextOutput(int32* cookie, media_output* out_output) GameProducer::GetNextOutput(int32* cookie, media_output* out_output)
{ {
// we currently support only one output // we currently support only one output
if (0 != *cookie) return B_BAD_INDEX; if (0 != *cookie)
return B_BAD_INDEX;
*out_output = fOutput; *out_output = fOutput;
*cookie += 1; *cookie += 1;
return B_OK; return B_OK;
} }
status_t status_t
GameProducer::DisposeOutputCookie(int32 cookie) GameProducer::DisposeOutputCookie(int32 cookie)
{ {
// do nothing because our cookie is only an integer // do nothing because our cookie is only an integer
@@ -107,13 +110,14 @@ GameProducer::DisposeOutputCookie(int32 cookie)
} }
void void
GameProducer::EnableOutput(const media_source& what, bool enabled, int32* _deprecated_) GameProducer::EnableOutput(const media_source& what, bool enabled,
int32* _deprecated_)
{ {
// If I had more than one output, I'd have to walk my list of output records to see // If I had more than one output, I'd have to walk my list of output records
// which one matched the given source, and then enable/disable that one. But this // to see which one matched the given source, and then enable/disable that
// node only has one output, so I just make sure the given source matches, then set // one. But this node only has one output, so I just make sure the given
// the enable state accordingly. // source matches, then set the enable state accordingly.
if (what == fOutput.source) if (what == fOutput.source)
{ {
fOutputEnabled = enabled; fOutputEnabled = enabled;
@@ -121,10 +125,11 @@ GameProducer::EnableOutput(const media_source& what, bool enabled, int32* _depre
} }
status_t status_t
GameProducer::FormatSuggestionRequested(media_type type, int32 /*quality*/, media_format* format) GameProducer::FormatSuggestionRequested(media_type type, int32 /*quality*/,
media_format* format)
{ {
// insure that we received a format // insure that we received a format
if (!format) if (!format)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -132,55 +137,66 @@ GameProducer::FormatSuggestionRequested(media_type type, int32 /*quality*/, medi
*format = fPreferredFormat; *format = fPreferredFormat;
// our format is supported // our format is supported
if (type == B_MEDIA_UNKNOWN_TYPE) return B_OK; if (type == B_MEDIA_UNKNOWN_TYPE)
return B_OK;
// we only support raw audo // we only support raw audo
return (type != B_MEDIA_RAW_AUDIO) ? B_MEDIA_BAD_FORMAT : B_OK; return (type != B_MEDIA_RAW_AUDIO) ? B_MEDIA_BAD_FORMAT : B_OK;
} }
status_t status_t
GameProducer::FormatProposal(const media_source& output, media_format* format) GameProducer::FormatProposal(const media_source& output, media_format* format)
{ {
// doest the proposed output match our output? // doest the proposed output match our output?
if (output != fOutput.source) return B_MEDIA_BAD_SOURCE; if (output != fOutput.source)
return B_MEDIA_BAD_SOURCE;
// return our preferred format // return our preferred format
*format = fPreferredFormat; *format = fPreferredFormat;
// we will reject the proposal if the format is not audio // we will reject the proposal if the format is not audio
media_type requestedType = format->type; media_type requestedType = format->type;
if ((requestedType != B_MEDIA_UNKNOWN_TYPE) && (requestedType != B_MEDIA_RAW_AUDIO)) if ((requestedType != B_MEDIA_UNKNOWN_TYPE)
&& (requestedType != B_MEDIA_RAW_AUDIO)) {
return B_MEDIA_BAD_FORMAT; return B_MEDIA_BAD_FORMAT;
}
return B_OK; // raw audio or wildcard type, either is okay by us return B_OK; // raw audio or wildcard type, either is okay by us
} }
status_t status_t
GameProducer::PrepareToConnect(const media_source& what, const media_destination& where, media_format* format, media_source* out_source, char* out_name) GameProducer::PrepareToConnect(const media_source& what,
const media_destination& where, media_format* format,
media_source* out_source, char* out_name)
{ {
// The format has been processed by the consumer at this point. We need // The format has been processed by the consumer at this point. We need
// to insure the format is still acceptable and any wild care are filled in. // to insure the format is still acceptable and any wild care are filled in.
// trying to connect something that isn't our source? // trying to connect something that isn't our source?
if (what != fOutput.source) return B_MEDIA_BAD_SOURCE; if (what != fOutput.source)
return B_MEDIA_BAD_SOURCE;
// are we already connected? // are we already connected?
if (fOutput.destination != media_destination::null) return B_MEDIA_ALREADY_CONNECTED; if (fOutput.destination != media_destination::null)
return B_MEDIA_ALREADY_CONNECTED;
// the format may not yet be fully specialized (the consumer might have // the format may not yet be fully specialized (the consumer might have
// passed back some wildcards). Finish specializing it now, and return an // passed back some wildcards). Finish specializing it now, and return an
// error if we don't support the requested format. // error if we don't support the requested format.
if (format->type != B_MEDIA_RAW_AUDIO) if (format->type != B_MEDIA_RAW_AUDIO)
return B_MEDIA_BAD_FORMAT; return B_MEDIA_BAD_FORMAT;
if (format->u.raw_audio.format != fPreferredFormat.u.raw_audio.format) if (format->u.raw_audio.format != fPreferredFormat.u.raw_audio.format)
return B_MEDIA_BAD_FORMAT; return B_MEDIA_BAD_FORMAT;
// check the buffer size, which may still be wildcarded // check the buffer size, which may still be wildcarded
if (format->u.raw_audio.buffer_size == media_raw_audio_format::wildcard.buffer_size) if (format->u.raw_audio.buffer_size
format->u.raw_audio.buffer_size = 4096; // pick something comfortable to suggest == media_raw_audio_format::wildcard.buffer_size) {
format->u.raw_audio.buffer_size = 4096;
// pick something comfortable to suggest
}
// Now reserve the connection, and return information about it // Now reserve the connection, and return information about it
fOutput.destination = where; fOutput.destination = where;
@@ -191,20 +207,22 @@ GameProducer::PrepareToConnect(const media_source& what, const media_destination
} }
void void
GameProducer::Connect(status_t error, const media_source& source, const media_destination& destination, const media_format& format, char* io_name) GameProducer::Connect(status_t error, const media_source& source,
const media_destination& destination, const media_format& format,
char* io_name)
{ {
// If something earlier failed, Connect() might still be called, but with a non-zero // If something earlier failed, Connect() might still be called, but with a
// error code. When that happens we simply unreserve the connection and do // non-zero error code. When that happens we simply unreserve the
// nothing else. // connection and do nothing else.
if (error) { if (error) {
fOutput.destination = media_destination::null; fOutput.destination = media_destination::null;
fOutput.format = fPreferredFormat; fOutput.format = fPreferredFormat;
return; return;
} }
// Okay, the connection has been confirmed. Record the destination and format // Okay, the connection has been confirmed. Record the destination and
// that we agreed on, and report our connection name again. // format that we agreed on, and report our connection name again.
fOutput.destination = destination; fOutput.destination = destination;
fOutput.format = format; fOutput.format = format;
strlcpy(io_name, fOutput.name, B_MEDIA_NAME_LENGTH); strlcpy(io_name, fOutput.name, B_MEDIA_NAME_LENGTH);
@@ -219,33 +237,34 @@ GameProducer::Connect(status_t error, const media_source& source, const media_de
// Have to set it before latency calculating // Have to set it before latency calculating
// Use a dry run to see how long it takes me to fill a buffer of data // Use a dry run to see how long it takes me to fill a buffer of data
// The first step to setup the buffer // The first step to setup the buffer
bigtime_t start, produceLatency; bigtime_t start, produceLatency;
int32 frames = int32(fBufferSize / fFrameSize); int32 frames = int32(fBufferSize / fFrameSize);
float* data = new float[frames * 2]; float* data = new float[frames * 2];
// Second, fill the buffer // Second, fill the buffer
start = ::system_time(); start = ::system_time();
for (int32 i = 0; i < frames; i++) { for (int32 i = 0; i < frames; i++) {
data[i*2] = 0.8 * float(i/frames); data[i * 2] = 0.8 * float(i / frames);
data[i*2+1] = 0.8 * float(i/frames); data[i * 2 + 1] = 0.8 * float(i / frames);
} }
produceLatency = ::system_time(); produceLatency = ::system_time();
// Third, calculate the latency // Third, calculate the latency
fInternalLatency = produceLatency - start; fInternalLatency = produceLatency - start;
SetEventLatency(fLatency + fInternalLatency); SetEventLatency(fLatency + fInternalLatency);
// Finaily, clean up // Finaily, clean up
delete [] data; delete [] data;
// reset our buffer duration, etc. to avoid later calculations // reset our buffer duration, etc. to avoid later calculations
bigtime_t duration = bigtime_t(1000000) * frames / bigtime_t(fOutput.format.u.raw_audio.frame_rate); bigtime_t duration = bigtime_t(1000000) * frames
/ bigtime_t(fOutput.format.u.raw_audio.frame_rate);
SetBufferDuration(duration); SetBufferDuration(duration);
// Set up the buffer group for our connection, as long as nobody handed us a // Set up the buffer group for our connection, as long as nobody handed us a
// buffer group (via SetBufferGroup()) prior to this. // buffer group (via SetBufferGroup()) prior to this.
if (!fBufferGroup) { if (!fBufferGroup) {
int32 count = int32(fLatency / BufferDuration() + 2); int32 count = int32(fLatency / BufferDuration() + 2);
fBufferGroup = new BBufferGroup(fBufferSize, count); fBufferGroup = new BBufferGroup(fBufferSize, count);
@@ -253,8 +272,9 @@ GameProducer::Connect(status_t error, const media_source& source, const media_de
} }
void void
GameProducer::Disconnect(const media_source& what, const media_destination& where) GameProducer::Disconnect(const media_source& what,
const media_destination& where)
{ {
// Make sure that our connection is the one being disconnected // Make sure that our connection is the one being disconnected
if ((where == fOutput.destination) && (what == fOutput.source)) { if ((where == fOutput.destination) && (what == fOutput.source)) {
@@ -266,16 +286,19 @@ GameProducer::Disconnect(const media_source& what, const media_destination& wher
} }
status_t status_t
GameProducer::FormatChangeRequested(const media_source& source, const media_destination& destination, media_format* io_format, int32* _deprecated_) GameProducer::FormatChangeRequested(const media_source& source,
const media_destination& destination, media_format* io_format,
int32* _deprecated_)
{ {
// we don't support any other formats, so we just reject any format changes. // we don't support any other formats, so we just reject any format changes.
return B_ERROR; return B_ERROR;
} }
status_t status_t
GameProducer::SetBufferGroup(const media_source& for_source, BBufferGroup* newGroup) GameProducer::SetBufferGroup(const media_source& for_source,
BBufferGroup* newGroup)
{ {
// verify that we didn't get bogus arguments before we proceed // verify that we didn't get bogus arguments before we proceed
if (for_source != fOutput.source) if (for_source != fOutput.source)
@@ -285,12 +308,12 @@ GameProducer::SetBufferGroup(const media_source& for_source, BBufferGroup* newGr
if (newGroup == fBufferGroup) if (newGroup == fBufferGroup)
return B_OK; return B_OK;
// Ahh, someone wants us to use a different buffer group. At this point we delete // Ahh, someone wants us to use a different buffer group. At this point we
// the one we are using and use the specified one instead. If the specified group is // delete the one we are using and use the specified one instead. If the
// NULL, we need to recreate one ourselves, and use *that*. Note that if we're // specified group is NULL, we need to recreate one ourselves, and use
// caching a BBuffer that we requested earlier, we have to Recycle() that buffer // *that*. Note that if we're caching a BBuffer that we requested earlier,
// *before* deleting the buffer group, otherwise we'll deadlock waiting for that // we have to Recycle() that buffer *before* deleting the buffer group,
// buffer to be recycled! // otherwise we'll deadlock waiting for that buffer to be recycled!
delete fBufferGroup; // waits for all buffers to recycle delete fBufferGroup; // waits for all buffers to recycle
if (newGroup != NULL) { if (newGroup != NULL) {
// we were given a valid group; just use that one from now on // we were given a valid group; just use that one from now on
@@ -313,7 +336,7 @@ GameProducer::SetBufferGroup(const media_source& for_source, BBufferGroup* newGr
} }
status_t status_t
GameProducer::GetLatency(bigtime_t* out_latency) GameProducer::GetLatency(bigtime_t* out_latency)
{ {
// report our *total* latency: internal plus downstream plus scheduling // report our *total* latency: internal plus downstream plus scheduling
@@ -322,29 +345,31 @@ GameProducer::GetLatency(bigtime_t* out_latency)
} }
void void
GameProducer::LateNoticeReceived(const media_source& what, bigtime_t how_much, bigtime_t performance_time) GameProducer::LateNoticeReceived(const media_source& what, bigtime_t how_much,
bigtime_t performance_time)
{ {
// If we're late, we need to catch up. Respond in a manner appropriate to our // If we're late, we need to catch up. Respond in a manner appropriate to
// current run mode. // our current run mode.
if (what == fOutput.source) { if (what == fOutput.source) {
if (RunMode() == B_RECORDING) { if (RunMode() == B_RECORDING) {
// A hardware capture node can't adjust; it simply emits buffers at // A hardware capture node can't adjust; it simply emits buffers at
// appropriate points. We (partially) simulate this by not adjusting // appropriate points. We (partially) simulate this by not
// our behavior upon receiving late notices -- after all, the hardware // adjusting our behavior upon receiving late notices -- after all,
// can't choose to capture "sooner".... // the hardware can't choose to capture "sooner"...
} else if (RunMode() == B_INCREASE_LATENCY) { } else if (RunMode() == B_INCREASE_LATENCY) {
// We're late, and our run mode dictates that we try to produce buffers // We're late, and our run mode dictates that we try to produce
// earlier in order to catch up. This argues that the downstream nodes are // buffers earlier in order to catch up. This argues that the
// not properly reporting their latency, but there's not much we can do about // downstream nodes are not properly reporting their latency, but
// that at the moment, so we try to start producing buffers earlier to // there's not much we can do about that at the moment, so we try
// compensate. // to start producing buffers earlier to compensate.
fInternalLatency += how_much; fInternalLatency += how_much;
SetEventLatency(fLatency + fInternalLatency); SetEventLatency(fLatency + fInternalLatency);
} else { } else {
// The other run modes dictate various strategies for sacrificing data quality // The other run modes dictate various strategies for sacrificing
// in the interests of timely data delivery. The way *we* do this is to skip // data quality in the interests of timely data delivery. The way we
// a buffer, which catches us up in time by one buffer duration. // do this is to skip a buffer, which catches us up in time by one
// buffer duration.
size_t nSamples = fBufferSize / fFrameSize; size_t nSamples = fBufferSize / fFrameSize;
fFramesSent += nSamples; fFramesSent += nSamples;
} }
@@ -352,8 +377,9 @@ GameProducer::LateNoticeReceived(const media_source& what, bigtime_t how_much, b
} }
void void
GameProducer::LatencyChanged(const media_source& source, const media_destination& destination, bigtime_t new_latency, uint32 flags) GameProducer::LatencyChanged(const media_source& source,
const media_destination& destination, bigtime_t new_latency, uint32 flags)
{ {
// something downstream changed latency, so we need to start producing // something downstream changed latency, so we need to start producing
// buffers earlier (or later) than we were previously. Make sure that the // buffers earlier (or later) than we were previously. Make sure that the
@@ -366,7 +392,7 @@ GameProducer::LatencyChanged(const media_source& source, const media_destination
} }
status_t status_t
GameProducer::SetPlayRate(int32 numer, int32 denom) GameProducer::SetPlayRate(int32 numer, int32 denom)
{ {
// Play rates are weird. We don't support them // Play rates are weird. We don't support them
@@ -374,7 +400,7 @@ GameProducer::SetPlayRate(int32 numer, int32 denom)
} }
status_t status_t
GameProducer::HandleMessage(int32 message, const void* data, size_t size) GameProducer::HandleMessage(int32 message, const void* data, size_t size)
{ {
// We currently do not handle private messages // We currently do not handle private messages
@@ -382,8 +408,10 @@ GameProducer::HandleMessage(int32 message, const void* data, size_t size)
} }
void void
GameProducer::AdditionalBufferRequested(const media_source& source, media_buffer_id prev_buffer, bigtime_t prev_time, const media_seek_tag* prev_tag) GameProducer::AdditionalBufferRequested(const media_source& source,
media_buffer_id prev_buffer, bigtime_t prev_time,
const media_seek_tag* prev_tag)
{ {
// we don't support offline mode (yet...) // we don't support offline mode (yet...)
return; return;
@@ -391,7 +419,7 @@ GameProducer::AdditionalBufferRequested(const media_source& source, media_buffer
// BMediaEventLooper methods // BMediaEventLooper methods
void void
GameProducer::NodeRegistered() GameProducer::NodeRegistered()
{ {
// Start the BMediaEventLooper thread // Start the BMediaEventLooper thread
@@ -406,7 +434,7 @@ GameProducer::NodeRegistered()
} }
void void
GameProducer::SetRunMode(run_mode mode) GameProducer::SetRunMode(run_mode mode)
{ {
// We don't support offline run mode, so broadcast an error if we're set to // We don't support offline run mode, so broadcast an error if we're set to
@@ -417,8 +445,9 @@ GameProducer::SetRunMode(run_mode mode)
} }
void void
GameProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bool realTimeEvent) GameProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
bool realTimeEvent)
{ {
// FPRINTF(stderr, "ToneProducer::HandleEvent\n"); // FPRINTF(stderr, "ToneProducer::HandleEvent\n");
switch (event->type) switch (event->type)
@@ -426,55 +455,58 @@ GameProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
case BTimedEventQueue::B_START: case BTimedEventQueue::B_START:
// don't do anything if we're already running // don't do anything if we're already running
if (RunState() != B_STARTED) { if (RunState() != B_STARTED) {
// We are going to start sending buffers so setup the needed bookkeeping // Going to start sending buffers so setup the needed bookkeeping
fFramesSent = 0; fFramesSent = 0;
fStartTime = event->event_time; fStartTime = event->event_time;
media_timed_event firstBufferEvent(fStartTime, BTimedEventQueue::B_HANDLE_BUFFER); media_timed_event firstBufferEvent(fStartTime,
BTimedEventQueue::B_HANDLE_BUFFER);
// Alternatively, we could call HandleEvent() directly with this event, to avoid a trip through // Alternatively, we could call HandleEvent() directly with this
// the event queue, like this: // event, to avoid a trip through the event queue like this:
//
// this->HandleEvent(&firstBufferEvent, 0, false); // this->HandleEvent(&firstBufferEvent, 0, false);
//
EventQueue()->AddEvent(firstBufferEvent); EventQueue()->AddEvent(firstBufferEvent);
} }
break; break;
case BTimedEventQueue::B_STOP: case BTimedEventQueue::B_STOP:
// When we handle a stop, we must ensure that downstream consumers don't // When we handle a stop, we must ensure that downstream consumers don't
// get any more buffers from us. This means we have to flush any pending // get any more buffers from us. This means we have to flush any
// buffer-producing events from the queue. // pending buffer-producing events from the queue.
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER); EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
BTimedEventQueue::B_HANDLE_BUFFER);
break; break;
case BTimedEventQueue::B_HANDLE_BUFFER: case BTimedEventQueue::B_HANDLE_BUFFER:
{ {
// make sure we're both started *and* connected before delivering a buffer // Ensure we're both started and connected before delivering buffer
if ((RunState() == BMediaEventLooper::B_STARTED) if ((RunState() == BMediaEventLooper::B_STARTED)
&& (fOutput.destination != media_destination::null)) { && (fOutput.destination != media_destination::null)) {
// Get the next buffer of data // Get the next buffer of data
BBuffer* buffer = FillNextBuffer(event->event_time); BBuffer* buffer = FillNextBuffer(event->event_time);
if (buffer) { if (buffer) {
// send the buffer downstream if and only if output is enabled // Send the buffer downstream if output is enabled
status_t err = B_ERROR; status_t err = B_ERROR;
if (fOutputEnabled) { if (fOutputEnabled) {
err = SendBuffer(buffer, fOutput.source, err = SendBuffer(buffer, fOutput.source,
fOutput.destination); fOutput.destination);
} }
if (err) { if (err) {
// we need to recycle the buffer ourselves if output is disabled or // we need to recycle the buffer ourselves if output is
// if the call to SendBuffer() fails // disabled or if the call to SendBuffer() fails
buffer->Recycle(); buffer->Recycle();
} }
} }
// track how much media we've delivered so far // track how much media we've delivered so far
size_t nFrames = fBufferSize / fFrameSize; size_t nFrames = fBufferSize / fFrameSize;
fFramesSent += nFrames; fFramesSent += nFrames;
// The buffer is on its way; now schedule the next one to go // The buffer is on its way; now schedule the next one to go
bigtime_t nextEvent = fStartTime + bigtime_t(double(fFramesSent) / double(fOutput.format.u.raw_audio.frame_rate) * 1000000.0); bigtime_t nextEvent = fStartTime + bigtime_t(double(fFramesSent)
media_timed_event nextBufferEvent(nextEvent, BTimedEventQueue::B_HANDLE_BUFFER); / double(fOutput.format.u.raw_audio.frame_rate)
* 1000000.0);
media_timed_event nextBufferEvent(nextEvent,
BTimedEventQueue::B_HANDLE_BUFFER);
EventQueue()->AddEvent(nextBufferEvent); EventQueue()->AddEvent(nextBufferEvent);
} }
} }
@@ -486,47 +518,49 @@ GameProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
} }
BBuffer* BBuffer*
GameProducer::FillNextBuffer(bigtime_t event_time) GameProducer::FillNextBuffer(bigtime_t event_time)
{ {
// get a buffer from our buffer group // get a buffer from our buffer group
BBuffer* buf = fBufferGroup->RequestBuffer(fBufferSize, BufferDuration()); BBuffer* buf = fBufferGroup->RequestBuffer(fBufferSize, BufferDuration());
// if we fail to get a buffer (for example, if the request times out), we skip this // if we fail to get a buffer (for example, if the request times out), we
// buffer and go on to the next, to avoid locking up the control thread // skip this buffer and go on to the next, to avoid locking up the control
if (!buf) // thread.
if (!buf)
return NULL; return NULL;
// we need to discribe the buffer // we need to discribe the buffer
int64 frames = int64(fBufferSize / fFrameSize); int64 frames = int64(fBufferSize / fFrameSize);
memset(buf->Data(), 0, fBufferSize); memset(buf->Data(), 0, fBufferSize);
// now fill the buffer with data, continuing where the last buffer left off // now fill the buffer with data, continuing where the last buffer left off
fObject->Play(buf->Data(), frames); fObject->Play(buf->Data(), frames);
// fill in the buffer header // fill in the buffer header
media_header* hdr = buf->Header(); media_header* hdr = buf->Header();
hdr->type = B_MEDIA_RAW_AUDIO; hdr->type = B_MEDIA_RAW_AUDIO;
hdr->size_used = fBufferSize; hdr->size_used = fBufferSize;
hdr->time_source = TimeSource()->ID(); hdr->time_source = TimeSource()->ID();
bigtime_t stamp; bigtime_t stamp;
if (RunMode() == B_RECORDING) { if (RunMode() == B_RECORDING) {
// In B_RECORDING mode, we stamp with the capture time. We're not // In B_RECORDING mode, we stamp with the capture time. We're not
// really a hardware capture node, but we simulate it by using the (precalculated) // really a hardware capture node, but we simulate it by using the
// time at which this buffer "should" have been created. // (precalculated) time at which this buffer "should" have been created.
stamp = event_time; stamp = event_time;
} else { } else {
// okay, we're in one of the "live" performance run modes. in these modes, we // okay, we're in one of the "live" performance run modes. in these
// stamp the buffer with the time at which the buffer should be rendered to the // modes, we stamp the buffer with the time at which the buffer should
// output, not with the capture time. fStartTime is the cached value of the // be rendered to the output, not with the capture time. fStartTime is
// first buffer's performance time; we calculate this buffer's performance time as // the cached value of the first buffer's performance time; we calculate
// an offset from that time, based on the amount of media we've created so far. // this buffer's performance time as an offset from that time, based on
// the amount of media we've created so far.
// Recalculating every buffer like this avoids accumulation of error. // Recalculating every buffer like this avoids accumulation of error.
stamp = fStartTime + bigtime_t(double(fFramesSent) / double(fOutput.format.u.raw_audio.frame_rate) * 1000000.0); stamp = fStartTime + bigtime_t(double(fFramesSent)
/ double(fOutput.format.u.raw_audio.frame_rate) * 1000000.0);
} }
hdr->start_time = stamp; hdr->start_time = stamp;
return buf; return buf;
} }
+19 -18
View File
@@ -1,27 +1,31 @@
/* /*
* Copyright 2001-2002, Haiku Inc. * Copyright 2002-2012 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors: * Authors:
* Christopher ML Zumwalt May (zummy@users.sf.net) * Christopher ML Zumwalt May (zummy@users.sf.net)
* *
* Distributed under the terms of the MIT License.
*/ */
#include <GameSound.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <GameSound.h>
#include "GameSoundBuffer.h" #include "GameSoundBuffer.h"
#include "GameSoundDevice.h" #include "GameSoundDevice.h"
using std::nothrow; using std::nothrow;
// Local Defines --------------------------------------------------------------- // Local Defines ---------------------------------------------------------------
// BGameSound class ------------------------------------------------------------ // BGameSound class ------------------------------------------------------------
BGameSound::BGameSound(BGameSoundDevice *device) BGameSound::BGameSound(BGameSoundDevice *device)
: fSound(-1) :
fSound(-1)
{ {
// TODO: device is ignored! // TODO: device is ignored!
// NOTE: BeBook documents that BGameSoundDevice must currently always // NOTE: BeBook documents that BGameSoundDevice must currently always
@@ -32,7 +36,8 @@ BGameSound::BGameSound(BGameSoundDevice *device)
BGameSound::BGameSound(const BGameSound &other) BGameSound::BGameSound(const BGameSound &other)
: fSound(-1) :
fSound(-1)
{ {
memcpy(&fFormat, &other.fFormat, sizeof(gs_audio_format)); memcpy(&fFormat, &other.fFormat, sizeof(gs_audio_format));
// TODO: device from other is ignored! // TODO: device from other is ignored!
@@ -106,8 +111,7 @@ BGameSound::StopPlaying()
status_t status_t
BGameSound::SetGain(float gain, BGameSound::SetGain(float gain, bigtime_t duration)
bigtime_t duration)
{ {
gs_attribute attribute; gs_attribute attribute;
@@ -121,8 +125,7 @@ BGameSound::SetGain(float gain,
status_t status_t
BGameSound::SetPan(float pan, BGameSound::SetPan(float pan, bigtime_t duration)
bigtime_t duration)
{ {
gs_attribute attribute; gs_attribute attribute;
@@ -166,16 +169,14 @@ BGameSound::Pan()
status_t status_t
BGameSound::SetAttributes(gs_attribute *inAttributes, BGameSound::SetAttributes(gs_attribute *inAttributes, size_t inAttributeCount)
size_t inAttributeCount)
{ {
return fDevice->SetAttributes(fSound, inAttributes, inAttributeCount); return fDevice->SetAttributes(fSound, inAttributes, inAttributeCount);
} }
status_t status_t
BGameSound::GetAttributes(gs_attribute *outAttributes, BGameSound::GetAttributes(gs_attribute *outAttributes, size_t inAttributeCount)
size_t inAttributeCount)
{ {
return fDevice->GetAttributes(fSound, outAttributes, inAttributeCount); return fDevice->GetAttributes(fSound, outAttributes, inAttributeCount);
} }
@@ -258,7 +259,8 @@ BGameSound::Init(gs_id handle)
return B_OK; return B_OK;
} }
/*
#if 0
BGameSound & BGameSound &
BGameSound::operator=(const BGameSound &other) BGameSound::operator=(const BGameSound &other)
{ {
@@ -272,7 +274,8 @@ BGameSound::operator=(const BGameSound &other)
return this; return this;
} }
*/ #endif
/* unimplemented for protection of the user: /* unimplemented for protection of the user:
* *
@@ -614,5 +617,3 @@ BGameSound::_Reserved_BGameSound_47(int32 arg, ...)
{ {
return B_ERROR; return B_ERROR;
} }
+123 -116
View File
@@ -24,6 +24,9 @@
// Description: Interface to a single sound, managed by the GameSoundDevice. // Description: Interface to a single sound, managed by the GameSoundDevice.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#include "GameSoundBuffer.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -35,7 +38,6 @@
#include <BufferGroup.h> #include <BufferGroup.h>
#include "GameProducer.h" #include "GameProducer.h"
#include "GameSoundBuffer.h"
#include "GameSoundDevice.h" #include "GameSoundDevice.h"
#include "StreamingGameSound.h" #include "StreamingGameSound.h"
#include "GSUtility.h" #include "GSUtility.h"
@@ -45,62 +47,63 @@
inline void inline void
ApplyMod(uint8 * data, uint8 * buffer, int64 index, float gain, float * pan) ApplyMod(uint8 * data, uint8 * buffer, int64 index, float gain, float * pan)
{ {
data[index*2] += uint8(float(buffer[index*2]) * gain * pan[0]); data[index * 2] += uint8(float(buffer[index * 2]) * gain * pan[0]);
data[index*2+1] += uint8(float(buffer[index*2+1]) * gain * pan[1]); data[index * 2 + 1] += uint8(float(buffer[index * 2 + 1]) * gain * pan[1]);
} }
inline void inline void
ApplyMod(int16 * data, int16 * buffer, int32 index, float gain, float * pan) ApplyMod(int16 * data, int16 * buffer, int32 index, float gain, float * pan)
{ {
data[index*2] = int16(float(buffer[index*2]) * gain * pan[0]); data[index * 2] = int16(float(buffer[index * 2]) * gain * pan[0]);
data[index*2+1] = int16(float(buffer[index*2+1]) * gain * pan[1]); data[index * 2 + 1] = int16(float(buffer[index * 2 + 1]) * gain * pan[1]);
} }
inline void inline void
ApplyMod(int32 * data, int32 * buffer, int32 index, float gain, float * pan) ApplyMod(int32 * data, int32 * buffer, int32 index, float gain, float * pan)
{ {
data[index*2] += int32(float(buffer[index*2]) * gain * pan[0]); data[index * 2] += int32(float(buffer[index * 2]) * gain * pan[0]);
data[index*2+1] += int32(float(buffer[index*2+1]) * gain * pan[1]); data[index * 2 + 1] += int32(float(buffer[index * 2 + 1]) * gain * pan[1]);
} }
inline void inline void
ApplyMod(float * data, float * buffer, int32 index, float gain, float * pan) ApplyMod(float * data, float * buffer, int32 index, float gain, float * pan)
{ {
data[index*2] += buffer[index*2] * gain * pan[0]; data[index * 2] += buffer[index * 2] * gain * pan[0];
data[index*2+1] += buffer[index*2+1] * gain * pan[1]; data[index * 2 + 1] += buffer[index * 2 + 1] * gain * pan[1];
} }
// GameSoundBuffer ------------------------------------------------------- // GameSoundBuffer -------------------------------------------------------
GameSoundBuffer::GameSoundBuffer(const gs_audio_format * format) GameSoundBuffer::GameSoundBuffer(const gs_audio_format * format)
: fLooping(false), :
fIsConnected(false), fLooping(false),
fIsPlaying(false), fIsConnected(false),
fGain(1.0), fIsPlaying(false),
fPan(0.0), fGain(1.0),
fPanLeft(1.0), fPan(0.0),
fPanRight(1.0), fPanLeft(1.0),
fGainRamp(NULL), fPanRight(1.0),
fPanRamp(NULL) fGainRamp(NULL),
fPanRamp(NULL)
{ {
fConnection = new Connection; fConnection = new Connection;
fNode = new GameProducer(this, format); fNode = new GameProducer(this, format);
fFrameSize = get_sample_size(format->format) * format->channel_count; fFrameSize = get_sample_size(format->format) * format->channel_count;
memcpy(&fFormat, format, sizeof(gs_audio_format)); memcpy(&fFormat, format, sizeof(gs_audio_format));
} }
// Play must stop before the distructor is called; otherwise, a fatel // Play must stop before the distructor is called; otherwise, a fatel
// error occures if the playback is in a subclass. // error occures if the playback is in a subclass.
GameSoundBuffer::~GameSoundBuffer() GameSoundBuffer::~GameSoundBuffer()
{ {
BMediaRoster* roster = BMediaRoster::Roster(); BMediaRoster* roster = BMediaRoster::Roster();
if (fIsConnected) { if (fIsConnected) {
// Ordinarily we'd stop *all* of the nodes in the chain at this point. // Ordinarily we'd stop *all* of the nodes in the chain at this point.
// However, one of the nodes is the System Mixer, and stopping the Mixer // However, one of the nodes is the System Mixer, and stopping the Mixer
@@ -109,14 +112,14 @@ GameSoundBuffer::~GameSoundBuffer()
// that even for global nodes like the Mixer. // that even for global nodes like the Mixer.
roster->Disconnect(fConnection->producer.node, fConnection->source, roster->Disconnect(fConnection->producer.node, fConnection->source,
fConnection->consumer.node, fConnection->destination); fConnection->consumer.node, fConnection->destination);
roster->ReleaseNode(fConnection->producer); roster->ReleaseNode(fConnection->producer);
roster->ReleaseNode(fConnection->consumer); roster->ReleaseNode(fConnection->consumer);
} }
delete fGainRamp; delete fGainRamp;
delete fPanRamp; delete fPanRamp;
delete fConnection; delete fConnection;
delete fNode; delete fNode;
} }
@@ -139,7 +142,7 @@ GameSoundBuffer::IsLooping() const
void void
GameSoundBuffer::SetLooping(bool looping) GameSoundBuffer::SetLooping(bool looping)
{ {
fLooping = looping; fLooping = looping;
} }
@@ -152,22 +155,22 @@ GameSoundBuffer::Gain() const
status_t status_t
GameSoundBuffer::SetGain(float gain, bigtime_t duration) GameSoundBuffer::SetGain(float gain, bigtime_t duration)
{ {
if (gain < 0.0 || gain > 1.0) if (gain < 0.0 || gain > 1.0)
return B_BAD_VALUE; return B_BAD_VALUE;
delete fGainRamp; delete fGainRamp;
fGainRamp = NULL; fGainRamp = NULL;
if (duration > 100000) if (duration > 100000)
fGainRamp = InitRamp(&fGain, gain, fFormat.frame_rate, duration); fGainRamp = InitRamp(&fGain, gain, fFormat.frame_rate, duration);
else else
fGain = gain; fGain = gain;
return B_OK; return B_OK;
} }
float float
GameSoundBuffer::Pan() const GameSoundBuffer::Pan() const
{ {
@@ -180,64 +183,64 @@ GameSoundBuffer::SetPan(float pan, bigtime_t duration)
{ {
if (pan < -1.0 || pan > 1.0) if (pan < -1.0 || pan > 1.0)
return B_BAD_VALUE; return B_BAD_VALUE;
delete fPanRamp; delete fPanRamp;
fPanRamp = NULL; fPanRamp = NULL;
if (duration < 100000) { if (duration < 100000) {
fPan = pan; fPan = pan;
if (fPan < 0.0) { if (fPan < 0.0) {
fPanLeft = 1.0; fPanLeft = 1.0;
fPanRight = 1.0 + fPan; fPanRight = 1.0 + fPan;
} else { } else {
fPanRight = 1.0; fPanRight = 1.0;
fPanLeft = 1.0 - fPan; fPanLeft = 1.0 - fPan;
} }
} else } else
fPanRamp = InitRamp(&fPan, pan, fFormat.frame_rate, duration); fPanRamp = InitRamp(&fPan, pan, fFormat.frame_rate, duration);
return B_OK; return B_OK;
} }
status_t status_t
GameSoundBuffer::GetAttributes(gs_attribute * attributes, GameSoundBuffer::GetAttributes(gs_attribute * attributes,
size_t attributeCount) size_t attributeCount)
{ {
for (size_t i = 0; i < attributeCount; i++) { for (size_t i = 0; i < attributeCount; i++) {
switch (attributes[i].attribute) { switch (attributes[i].attribute) {
case B_GS_GAIN: case B_GS_GAIN:
attributes[i].value = fGain; attributes[i].value = fGain;
if (fGainRamp) if (fGainRamp)
attributes[i].duration = fGainRamp->duration; attributes[i].duration = fGainRamp->duration;
break; break;
case B_GS_PAN: case B_GS_PAN:
attributes[i].value = fPan; attributes[i].value = fPan;
if (fPanRamp) if (fPanRamp)
attributes[i].duration = fPanRamp->duration; attributes[i].duration = fPanRamp->duration;
break; break;
case B_GS_LOOPING: case B_GS_LOOPING:
attributes[i].value = (fLooping) ? -1.0 : 0.0; attributes[i].value = (fLooping) ? -1.0 : 0.0;
attributes[i].duration = bigtime_t(0); attributes[i].duration = bigtime_t(0);
break; break;
default: default:
attributes[i].value = 0.0; attributes[i].value = 0.0;
attributes[i].duration = bigtime_t(0); attributes[i].duration = bigtime_t(0);
break; break;
} }
} }
return B_OK; return B_OK;
} }
status_t status_t
GameSoundBuffer::SetAttributes(gs_attribute * attributes, GameSoundBuffer::SetAttributes(gs_attribute * attributes,
size_t attributeCount) size_t attributeCount)
{ {
status_t error = B_OK; status_t error = B_OK;
@@ -246,21 +249,21 @@ GameSoundBuffer::SetAttributes(gs_attribute * attributes,
case B_GS_GAIN: case B_GS_GAIN:
error = SetGain(attributes[i].value, attributes[i].duration); error = SetGain(attributes[i].value, attributes[i].duration);
break; break;
case B_GS_PAN: case B_GS_PAN:
error = SetPan(attributes[i].value, attributes[i].duration); error = SetPan(attributes[i].value, attributes[i].duration);
break; break;
case B_GS_LOOPING: case B_GS_LOOPING:
fLooping = bool(attributes[i].value); fLooping = bool(attributes[i].value);
break; break;
default: default:
break; break;
} }
} }
return error; return error;
} }
@@ -270,11 +273,11 @@ GameSoundBuffer::Play(void * data, int64 frames)
float pan[2]; float pan[2];
pan[0] = fPanRight; pan[0] = fPanRight;
pan[1] = fPanLeft; pan[1] = fPanLeft;
char * buffer = new char[fFrameSize * frames]; char * buffer = new char[fFrameSize * frames];
FillBuffer(buffer, frames); FillBuffer(buffer, frames);
switch (fFormat.format) { switch (fFormat.format) {
case gs_audio_format::B_GS_U8: case gs_audio_format::B_GS_U8:
{ {
@@ -282,56 +285,56 @@ GameSoundBuffer::Play(void * data, int64 frames)
ApplyMod((uint8*)data, (uint8*)buffer, i, fGain, pan); ApplyMod((uint8*)data, (uint8*)buffer, i, fGain, pan);
UpdateMods(); UpdateMods();
} }
break; break;
} }
case gs_audio_format::B_GS_S16: case gs_audio_format::B_GS_S16:
{ {
for (int64 i = 0; i < frames; i++) { for (int64 i = 0; i < frames; i++) {
ApplyMod((int16*)data, (int16*)buffer, i, fGain, pan); ApplyMod((int16*)data, (int16*)buffer, i, fGain, pan);
UpdateMods(); UpdateMods();
} }
break; break;
} }
case gs_audio_format::B_GS_S32: case gs_audio_format::B_GS_S32:
{ {
for (int64 i = 0; i < frames; i++) { for (int64 i = 0; i < frames; i++) {
ApplyMod((int32*)data, (int32*)buffer, i, fGain, pan); ApplyMod((int32*)data, (int32*)buffer, i, fGain, pan);
UpdateMods(); UpdateMods();
} }
break; break;
} }
case gs_audio_format::B_GS_F: case gs_audio_format::B_GS_F:
{ {
for (int64 i = 0; i < frames; i++) { for (int64 i = 0; i < frames; i++) {
ApplyMod((float*)data, (float*)buffer, i, fGain, pan); ApplyMod((float*)data, (float*)buffer, i, fGain, pan);
UpdateMods(); UpdateMods();
} }
break; break;
} }
} }
delete[] buffer; delete[] buffer;
} }
void void
GameSoundBuffer::UpdateMods() GameSoundBuffer::UpdateMods()
{ {
// adjust the gain if needed // adjust the gain if needed
if (fGainRamp) { if (fGainRamp) {
if (ChangeRamp(fGainRamp)) { if (ChangeRamp(fGainRamp)) {
delete fGainRamp; delete fGainRamp;
fGainRamp = NULL; fGainRamp = NULL;
} }
} }
// adjust the ramp if needed // adjust the ramp if needed
if (fPanRamp) { if (fPanRamp) {
if (ChangeRamp(fPanRamp)) { if (ChangeRamp(fPanRamp)) {
@@ -356,14 +359,14 @@ GameSoundBuffer::Reset()
fGain = 1.0; fGain = 1.0;
delete fGainRamp; delete fGainRamp;
fGainRamp = NULL; fGainRamp = NULL;
fPan = 0.0; fPan = 0.0;
fPanLeft = 1.0; fPanLeft = 1.0;
fPanRight = 1.0; fPanRight = 1.0;
delete fPanRamp; delete fPanRamp;
fPanRamp = NULL; fPanRamp = NULL;
fLooping = false; fLooping = false;
} }
@@ -373,16 +376,16 @@ GameSoundBuffer::Connect(media_node * consumer)
{ {
BMediaRoster* roster = BMediaRoster::Roster(); BMediaRoster* roster = BMediaRoster::Roster();
status_t err = roster->RegisterNode(fNode); status_t err = roster->RegisterNode(fNode);
if (err != B_OK) if (err != B_OK)
return err; return err;
// make sure the Media Roster knows that we're using the node // make sure the Media Roster knows that we're using the node
err = roster->GetNodeFor(fNode->Node().node, &fConnection->producer); err = roster->GetNodeFor(fNode->Node().node, &fConnection->producer);
if (err != B_OK) if (err != B_OK)
return err; return err;
// connect to the mixer // connect to the mixer
fConnection->consumer = *consumer; fConnection->consumer = *consumer;
@@ -390,7 +393,7 @@ GameSoundBuffer::Connect(media_node * consumer)
// the Mixer uses too. // the Mixer uses too.
err = roster->GetTimeSource(&fConnection->timeSource); err = roster->GetTimeSource(&fConnection->timeSource);
if (err != B_OK) if (err != B_OK)
return err; return err;
err = roster->SetTimeSourceFor(fConnection->producer.node, err = roster->SetTimeSourceFor(fConnection->producer.node,
fConnection->timeSource.node); fConnection->timeSource.node);
@@ -400,22 +403,26 @@ GameSoundBuffer::Connect(media_node * consumer)
media_input mixerInput; media_input mixerInput;
media_output soundOutput; media_output soundOutput;
int32 count = 1; int32 count = 1;
err = roster->GetFreeOutputsFor(fConnection->producer, &soundOutput, 1, &count); err = roster->GetFreeOutputsFor(fConnection->producer, &soundOutput, 1,
if (err != B_OK) &count);
if (err != B_OK)
return err; return err;
count = 1; count = 1;
err = roster->GetFreeInputsFor(fConnection->consumer, &mixerInput, 1, &count); err = roster->GetFreeInputsFor(fConnection->consumer, &mixerInput, 1,
if (err != B_OK) &count);
if (err != B_OK)
return err; return err;
// got the endpoints; now we connect it! // got the endpoints; now we connect it!
media_format format; media_format format;
format.type = B_MEDIA_RAW_AUDIO; format.type = B_MEDIA_RAW_AUDIO;
format.u.raw_audio = media_raw_audio_format::wildcard; format.u.raw_audio = media_raw_audio_format::wildcard;
err = roster->Connect(soundOutput.source, mixerInput.destination, &format, &soundOutput, &mixerInput); err = roster->Connect(soundOutput.source, mixerInput.destination, &format,
if (err != B_OK) &soundOutput, &mixerInput);
if (err != B_OK)
return err; return err;
// the inputs and outputs might have been reassigned during the // the inputs and outputs might have been reassigned during the
// nodes' negotiation of the Connect(). That's why we wait until // nodes' negotiation of the Connect(). That's why we wait until
// after Connect() finishes to save their contents. // after Connect() finishes to save their contents.
@@ -431,22 +438,24 @@ GameSoundBuffer::Connect(media_node * consumer)
status_t status_t
GameSoundBuffer::StartPlaying() GameSoundBuffer::StartPlaying()
{ {
if (fIsPlaying) if (fIsPlaying)
return EALREADY; return EALREADY;
BMediaRoster* roster = BMediaRoster::Roster(); BMediaRoster* roster = BMediaRoster::Roster();
BTimeSource* source = roster->MakeTimeSourceFor(fConnection->producer); BTimeSource* source = roster->MakeTimeSourceFor(fConnection->producer);
// make sure we give the producer enough time to run buffers through // make sure we give the producer enough time to run buffers through
// the node chain, otherwise it'll start up already late // the node chain, otherwise it'll start up already late
bigtime_t latency = 0; bigtime_t latency = 0;
status_t status = roster->GetLatencyFor(fConnection->producer, &latency); status_t status = roster->GetLatencyFor(fConnection->producer, &latency);
if (status == B_OK) if (status == B_OK) {
status = roster->StartNode(fConnection->producer, source->Now() + latency); status = roster->StartNode(fConnection->producer,
source->Now() + latency);
}
source->Release(); source->Release();
fIsPlaying = true; fIsPlaying = true;
return status; return status;
} }
@@ -454,16 +463,16 @@ GameSoundBuffer::StartPlaying()
status_t status_t
GameSoundBuffer::StopPlaying() GameSoundBuffer::StopPlaying()
{ {
if (!fIsPlaying) if (!fIsPlaying)
return EALREADY; return EALREADY;
BMediaRoster* roster = BMediaRoster::Roster(); BMediaRoster* roster = BMediaRoster::Roster();
roster->StopNode(fConnection->producer, 0, true); roster->StopNode(fConnection->producer, 0, true);
// synchronous stop // synchronous stop
Reset(); Reset();
fIsPlaying = false; fIsPlaying = false;
return B_OK; return B_OK;
} }
@@ -474,19 +483,18 @@ GameSoundBuffer::IsPlaying()
return fIsPlaying; return fIsPlaying;
} }
// SimpleSoundBuffer ------------------------------------------------------ // SimpleSoundBuffer ------------------------------------------------------
SimpleSoundBuffer::SimpleSoundBuffer(const gs_audio_format * format, SimpleSoundBuffer::SimpleSoundBuffer(const gs_audio_format * format,
const void * data, const void * data, int64 frames)
int64 frames) :
: GameSoundBuffer(format), GameSoundBuffer(format),
fPosition(0) fPosition(0)
{ {
fBufferSize = frames * fFrameSize; fBufferSize = frames * fFrameSize;
fBuffer = new char[fBufferSize]; fBuffer = new char[fBufferSize];
memcpy(fBuffer, data, fBufferSize); memcpy(fBuffer, data, fBufferSize);
} }
@@ -506,16 +514,16 @@ SimpleSoundBuffer::Reset()
void void
SimpleSoundBuffer::FillBuffer(void * data, int64 frames) SimpleSoundBuffer::FillBuffer(void * data, int64 frames)
{ {
char * buffer = (char*)data; char * buffer = (char*)data;
size_t bytes = fFrameSize * frames; size_t bytes = fFrameSize * frames;
if (fPosition + bytes >= fBufferSize) { if (fPosition + bytes >= fBufferSize) {
if (fPosition < fBufferSize) { if (fPosition < fBufferSize) {
// copy the remaining frames // copy the remaining frames
size_t remainder = fBufferSize - fPosition; size_t remainder = fBufferSize - fPosition;
memcpy(buffer, &fBuffer[fPosition], remainder); memcpy(buffer, &fBuffer[fPosition], remainder);
if (fLooping) { if (fLooping) {
// restart the sound from the begging // restart the sound from the begging
memcpy(&buffer[remainder], fBuffer, bytes - remainder); memcpy(&buffer[remainder], fBuffer, bytes - remainder);
@@ -534,15 +542,14 @@ SimpleSoundBuffer::FillBuffer(void * data, int64 frames)
// StreamingSoundBuffer ------------------------------------------------------ // StreamingSoundBuffer ------------------------------------------------------
StreamingSoundBuffer::StreamingSoundBuffer(const gs_audio_format * format, StreamingSoundBuffer::StreamingSoundBuffer(const gs_audio_format * format,
const void * streamHook, size_t inBufferFrameCount, const void * streamHook, size_t inBufferFrameCount, size_t inBufferCount)
size_t inBufferCount)
: :
GameSoundBuffer(format), GameSoundBuffer(format),
fStreamHook(const_cast<void *>(streamHook)) fStreamHook(const_cast<void *>(streamHook))
{ {
if (inBufferFrameCount != 0 && inBufferCount != 0) { if (inBufferFrameCount != 0 && inBufferCount != 0) {
BBufferGroup *bufferGroup = new BBufferGroup(inBufferFrameCount BBufferGroup *bufferGroup
* fFrameSize, inBufferCount); = new BBufferGroup(inBufferFrameCount * fFrameSize, inBufferCount);
fNode->SetBufferGroup(fConnection->source, bufferGroup); fNode->SetBufferGroup(fConnection->source, bufferGroup);
} }
} }
@@ -557,7 +564,7 @@ void
StreamingSoundBuffer::FillBuffer(void * buffer, int64 frames) StreamingSoundBuffer::FillBuffer(void * buffer, int64 frames)
{ {
BStreamingGameSound* object = (BStreamingGameSound*)fStreamHook; BStreamingGameSound* object = (BStreamingGameSound*)fStreamHook;
size_t bytes = fFrameSize * frames; size_t bytes = fFrameSize * frames;
object->FillBuffer(buffer, bytes); object->FillBuffer(buffer, bytes);
} }
+7 -4
View File
@@ -26,6 +26,9 @@
// this time. Use at your own risk. // this time. Use at your own risk.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#include "GameSoundDevice.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -33,15 +36,15 @@
#include <Autolock.h> #include <Autolock.h>
#include <List.h> #include <List.h>
#include <Locker.h> #include <Locker.h>
#include <MediaRoster.h>
#include <MediaAddOn.h> #include <MediaAddOn.h>
#include <TimeSource.h> #include <MediaRoster.h>
#include <MediaTheme.h> #include <MediaTheme.h>
#include <TimeSource.h>
#include "GSUtility.h"
#include "GameSoundDevice.h"
#include "GameSoundBuffer.h" #include "GameSoundBuffer.h"
#include "GameProducer.h" #include "GameProducer.h"
#include "GSUtility.h"
// BGameSoundDevice definitions ------------------------------------ // BGameSoundDevice definitions ------------------------------------
const int32 kInitSoundCount = 32; const int32 kInitSoundCount = 32;
+35 -36
View File
@@ -1,16 +1,17 @@
/* /*
* Copyright 2001-2007, Haiku Inc. * Copyright 2001-2012 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors: * Authors:
* Christopher ML Zumwalt May (zummy@users.sf.net) * Christopher ML Zumwalt May (zummy@users.sf.net)
* Jérôme Duval * Jérôme Duval
*
* Distributed under the terms of the MIT License.
*/ */
#include <string.h>
#include <PushGameSound.h>
#include <List.h> #include <List.h>
#include <PushGameSound.h> #include <string.h>
#include "GSUtility.h" #include "GSUtility.h"
@@ -18,7 +19,7 @@
BPushGameSound::BPushGameSound(size_t inBufferFrameCount, BPushGameSound::BPushGameSound(size_t inBufferFrameCount,
const gs_audio_format *format, size_t inBufferCount, const gs_audio_format *format, size_t inBufferCount,
BGameSoundDevice *device) BGameSoundDevice *device)
: :
BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device), BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device),
fLockPos(0), fLockPos(0),
fPlayPos(0) fPlayPos(0)
@@ -26,11 +27,11 @@ BPushGameSound::BPushGameSound(size_t inBufferFrameCount,
fPageLocked = new BList; fPageLocked = new BList;
size_t frameSize = get_sample_size(format->format) * format->channel_count; size_t frameSize = get_sample_size(format->format) * format->channel_count;
fPageCount = inBufferCount; fPageCount = inBufferCount;
fPageSize = frameSize * inBufferFrameCount; fPageSize = frameSize * inBufferFrameCount;
fBufferSize = fPageSize * fPageCount; fBufferSize = fPageSize * fPageCount;
fBuffer = new char[fBufferSize]; fBuffer = new char[fBufferSize];
} }
@@ -57,28 +58,28 @@ BPushGameSound::~BPushGameSound()
BPushGameSound::lock_status BPushGameSound::lock_status
BPushGameSound::LockNextPage(void **out_pagePtr, size_t *out_pageSize) BPushGameSound::LockNextPage(void **out_pagePtr, size_t *out_pageSize)
{ {
// the user can not lock every page // the user can not lock every page
if (fPageLocked->CountItems() > fPageCount - 3) if (fPageLocked->CountItems() > fPageCount - 3)
return lock_failed; return lock_failed;
// the user cann't lock a page being played // the user cann't lock a page being played
if (fLockPos < fPlayPos if (fLockPos < fPlayPos
&& fLockPos + fPageSize > fPlayPos) && fLockPos + fPageSize > fPlayPos)
return lock_failed; return lock_failed;
// lock the page // lock the page
char * lockPage = &fBuffer[fLockPos]; char * lockPage = &fBuffer[fLockPos];
fPageLocked->AddItem(lockPage); fPageLocked->AddItem(lockPage);
// move the locker to the next page // move the locker to the next page
fLockPos += fPageSize; fLockPos += fPageSize;
if (fLockPos > fBufferSize) if (fLockPos > fBufferSize)
fLockPos = 0; fLockPos = 0;
*out_pagePtr = lockPage; *out_pagePtr = lockPage;
*out_pageSize = fPageSize; *out_pageSize = fPageSize;
return lock_ok; return lock_ok;
} }
@@ -119,7 +120,7 @@ BPushGameSound::Clone() const
gs_audio_format format = Format(); gs_audio_format format = Format();
size_t frameSize = get_sample_size(format.format) * format.channel_count; size_t frameSize = get_sample_size(format.format) * format.channel_count;
size_t bufferFrameCount = fPageSize / frameSize; size_t bufferFrameCount = fPageSize / frameSize;
return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device()); return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device());
} }
@@ -133,8 +134,7 @@ BPushGameSound::Perform(int32 selector, void *data)
status_t status_t
BPushGameSound::SetParameters(size_t inBufferFrameCount, BPushGameSound::SetParameters(size_t inBufferFrameCount,
const gs_audio_format *format, const gs_audio_format *format, size_t inBufferCount)
size_t inBufferCount)
{ {
return B_UNSUPPORTED; return B_UNSUPPORTED;
} }
@@ -150,66 +150,67 @@ BPushGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer,
void void
BPushGameSound::FillBuffer(void *inBuffer, size_t inByteCount) BPushGameSound::FillBuffer(void *inBuffer, size_t inByteCount)
{ {
size_t bytes = inByteCount; size_t bytes = inByteCount;
if (!BytesReady(&bytes)) if (!BytesReady(&bytes))
return; return;
if (fPlayPos + bytes > fBufferSize) { if (fPlayPos + bytes > fBufferSize) {
size_t remainder = fBufferSize - fPlayPos; size_t remainder = fBufferSize - fPlayPos;
// Space left in buffer // Space left in buffer
char * buffer = (char*)inBuffer; char * buffer = (char*)inBuffer;
// fill the buffer with the samples left at the end of our buffer // fill the buffer with the samples left at the end of our buffer
memcpy(buffer, &fBuffer[fPlayPos], remainder); memcpy(buffer, &fBuffer[fPlayPos], remainder);
fPlayPos = 0; fPlayPos = 0;
// fill the remainder of the buffer by looping to the start // fill the remainder of the buffer by looping to the start
// of the buffer if it isn't locked // of the buffer if it isn't locked
bytes -= remainder; bytes -= remainder;
if (BytesReady(&bytes)) { if (BytesReady(&bytes)) {
memcpy(&buffer[remainder], fBuffer, bytes); memcpy(&buffer[remainder], fBuffer, bytes);
fPlayPos += bytes; fPlayPos += bytes;
} }
} else { } else {
memcpy(inBuffer, &fBuffer[fPlayPos], bytes); memcpy(inBuffer, &fBuffer[fPlayPos], bytes);
fPlayPos += bytes; fPlayPos += bytes;
} }
BStreamingGameSound::FillBuffer(inBuffer, inByteCount); BStreamingGameSound::FillBuffer(inBuffer, inByteCount);
} }
bool bool
BPushGameSound::BytesReady(size_t * bytes) BPushGameSound::BytesReady(size_t * bytes)
{ {
if (fPageLocked->CountItems() <= 0) if (fPageLocked->CountItems() <= 0)
return true; return true;
size_t start = fPlayPos; size_t start = fPlayPos;
size_t ready = fPlayPos; size_t ready = fPlayPos;
int32 page = int32(start / fPageSize); int32 page = int32(start / fPageSize);
// return if there is nothing to do // return if there is nothing to do
if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) if (fPageLocked->HasItem(&fBuffer[page * fPageSize]))
return false; return false;
while (ready < *bytes) { while (ready < *bytes) {
ready += fPageSize; ready += fPageSize;
page = int32(ready / fPageSize); page = int32(ready / fPageSize);
if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) { if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) {
// we have found a locked page // we have found a locked page
*bytes = ready - start - (ready - page * fPageSize); *bytes = ready - start - (ready - page * fPageSize);
return true; return true;
} }
} }
// all of the bytes are ready // all of the bytes are ready
return true; return true;
} }
/* unimplemented for protection of the user: /* unimplemented for protection of the user:
* *
* BPushGameSound::BPushGameSound() * BPushGameSound::BPushGameSound()
@@ -384,5 +385,3 @@ BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...)
{ {
return B_ERROR; return B_ERROR;
} }
+74 -69
View File
@@ -1,39 +1,43 @@
/* /*
* Copyright 2001-2005, Haiku Inc. * Copyright 2001-2012 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors: * Authors:
* Christopher ML Zumwalt May (zummy@users.sf.net) * Christopher ML Zumwalt May (zummy@users.sf.net)
*
* Distributed under the terms of the MIT License.
*/ */
#include <stdlib.h>
#include <string.h> #include <SimpleGameSound.h>
#include <Entry.h> #include <Entry.h>
#include <MediaFile.h> #include <MediaFile.h>
#include <MediaTrack.h> #include <MediaTrack.h>
#include <stdlib.h>
#include <string.h>
#include "GameSoundDefs.h"
#include "GameSoundBuffer.h" #include "GameSoundBuffer.h"
#include "GameSoundDefs.h"
#include "GameSoundDevice.h" #include "GameSoundDevice.h"
#include "GSUtility.h" #include "GSUtility.h"
#include <SimpleGameSound.h>
BSimpleGameSound::BSimpleGameSound(const entry_ref *inFile, BGameSoundDevice *device) BSimpleGameSound::BSimpleGameSound(const entry_ref *inFile,
: BGameSound(device) BGameSoundDevice *device)
:
BGameSound(device)
{ {
if (InitCheck() == B_OK) if (InitCheck() == B_OK)
SetInitError(Init(inFile)); SetInitError(Init(inFile));
} }
BSimpleGameSound::BSimpleGameSound(const char *inFile, BGameSoundDevice *device) BSimpleGameSound::BSimpleGameSound(const char *inFile, BGameSoundDevice *device)
: BGameSound(device) :
BGameSound(device)
{ {
if (InitCheck() == B_OK) { if (InitCheck() == B_OK) {
entry_ref file; entry_ref file;
if (get_ref_for_path(inFile, &file) != B_OK) if (get_ref_for_path(inFile, &file) != B_OK)
SetInitError(B_ENTRY_NOT_FOUND); SetInitError(B_ENTRY_NOT_FOUND);
else else
@@ -42,20 +46,20 @@ BSimpleGameSound::BSimpleGameSound(const char *inFile, BGameSoundDevice *device)
} }
BSimpleGameSound::BSimpleGameSound(const void *inData, BSimpleGameSound::BSimpleGameSound(const void *inData, size_t inFrameCount,
size_t inFrameCount, const gs_audio_format *format, BGameSoundDevice *device)
const gs_audio_format *format, :
BGameSoundDevice *device) BGameSound(device)
: BGameSound(device)
{ {
if (InitCheck() == B_OK) if (InitCheck() == B_OK)
SetInitError(Init(inData, inFrameCount, format)); SetInitError(Init(inData, inFrameCount, format));
} }
BSimpleGameSound::BSimpleGameSound(const BSimpleGameSound &other) BSimpleGameSound::BSimpleGameSound(const BSimpleGameSound &other)
: BGameSound(other) :
{ BGameSound(other)
{
gs_audio_format format; gs_audio_format format;
void *data = NULL; void *data = NULL;
@@ -90,7 +94,7 @@ BSimpleGameSound::Clone() const
} }
/* virtual */ status_t /* virtual */ status_t
BSimpleGameSound::Perform(int32 selector, void * data) BSimpleGameSound::Perform(int32 selector, void * data)
{ {
return B_ERROR; return B_ERROR;
@@ -101,12 +105,12 @@ status_t
BSimpleGameSound::SetIsLooping(bool looping) BSimpleGameSound::SetIsLooping(bool looping)
{ {
gs_attribute attribute; gs_attribute attribute;
attribute.attribute = B_GS_LOOPING; attribute.attribute = B_GS_LOOPING;
attribute.value = (looping) ? -1.0 : 0.0; attribute.value = (looping) ? -1.0 : 0.0;
attribute.duration = bigtime_t(0); attribute.duration = bigtime_t(0);
attribute.flags = 0; attribute.flags = 0;
return Device()->SetAttributes(ID(), &attribute, 1); return Device()->SetAttributes(ID(), &attribute, 1);
} }
@@ -115,13 +119,13 @@ bool
BSimpleGameSound::IsLooping() const BSimpleGameSound::IsLooping() const
{ {
gs_attribute attribute; gs_attribute attribute;
attribute.attribute = B_GS_LOOPING; attribute.attribute = B_GS_LOOPING;
attribute.flags = 0; attribute.flags = 0;
if (Device()->GetAttributes(ID(), &attribute, 1) != B_OK) if (Device()->GetAttributes(ID(), &attribute, 1) != B_OK)
return false; return false;
return bool(attribute.value); return bool(attribute.value);
} }
@@ -133,90 +137,93 @@ BSimpleGameSound::Init(const entry_ref* inFile)
gs_audio_format gsformat; gs_audio_format gsformat;
media_format mformat; media_format mformat;
int64 framesRead, framesTotal = 0; int64 framesRead, framesTotal = 0;
if (file.InitCheck() != B_OK) if (file.InitCheck() != B_OK)
return file.InitCheck(); return file.InitCheck();
BMediaTrack* audioStream = file.TrackAt(0); BMediaTrack* audioStream = file.TrackAt(0);
audioStream->EncodedFormat(&mformat); audioStream->EncodedFormat(&mformat);
if (!mformat.IsAudio()) if (!mformat.IsAudio())
return B_ERROR; return B_ERROR;
int64 frames = audioStream->CountFrames(); int64 frames = audioStream->CountFrames();
memset(&mformat, 0, sizeof(media_format)); memset(&mformat, 0, sizeof(media_format));
mformat.type = B_MEDIA_RAW_AUDIO; mformat.type = B_MEDIA_RAW_AUDIO;
// mformat.u.raw_audio.byte_order = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN; // mformat.u.raw_audio.byte_order
// = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
status_t error = audioStream->DecodedFormat(&mformat); status_t error = audioStream->DecodedFormat(&mformat);
if (error != B_OK) if (error != B_OK)
return error; return error;
memset(&gsformat, 0, sizeof(gs_audio_format)); memset(&gsformat, 0, sizeof(gs_audio_format));
media_to_gs_format(&gsformat, &mformat.u.raw_audio); media_to_gs_format(&gsformat, &mformat.u.raw_audio);
if (mformat.u.raw_audio.format == media_raw_audio_format::B_AUDIO_CHAR) { 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 GameKit doesnt support this format so we will have to reformat
// the data into something the GameKit does support. // the data into something the GameKit does support.
char * buffer = new char[gsformat.buffer_size]; char * buffer = new char[gsformat.buffer_size];
uchar * data = new uchar[frames * gsformat.channel_count]; uchar * data = new uchar[frames * gsformat.channel_count];
while (framesTotal < frames) { while (framesTotal < frames) {
// read the next chunck from the stream // read the next chunck from the stream
memset(buffer, 0, gsformat.buffer_size); memset(buffer, 0, gsformat.buffer_size);
audioStream->ReadFrames(buffer, &framesRead); audioStream->ReadFrames(buffer, &framesRead);
// refomat the buffer from // refomat the buffer from
int64 position = framesTotal * gsformat.channel_count; int64 position = framesTotal * gsformat.channel_count;
for(int32 i = 0; i < (int32)gsformat.buffer_size; i++) for (int32 i = 0; i < (int32)gsformat.buffer_size; i++)
data[i + position] = buffer[i] + 128; data[i + position] = buffer[i] + 128;
framesTotal += framesRead; framesTotal += framesRead;
} }
gsformat.format = gs_audio_format::B_GS_U8; gsformat.format = gs_audio_format::B_GS_U8;
error = Init(data, frames, &gsformat); error = Init(data, frames, &gsformat);
// free the buffers we no longer need // free the buffers we no longer need
delete [] buffer; delete [] buffer;
delete [] data; delete [] data;
} else { } else {
// We need to determine the size, in bytes, of a single sample. // We need to determine the size, in bytes, of a single sample.
// At the same time, we will store the format of the audio buffer // At the same time, we will store the format of the audio buffer
size_t frameSize = get_sample_size(gsformat.format) * gsformat.channel_count; size_t frameSize
char * data = new char[frames * frameSize]; = get_sample_size(gsformat.format) * gsformat.channel_count;
char * data = new char[frames * frameSize];
gsformat.buffer_size = frames * frameSize; gsformat.buffer_size = frames * frameSize;
while(framesTotal < frames) { while (framesTotal < frames) {
char * position = &data[framesTotal * frameSize]; char * position = &data[framesTotal * frameSize];
audioStream->ReadFrames(position, &framesRead); audioStream->ReadFrames(position, &framesRead);
framesTotal += framesRead; framesTotal += framesRead;
} }
error = Init(data, frames, &gsformat); error = Init(data, frames, &gsformat);
delete [] data; delete [] data;
} }
file.ReleaseTrack(audioStream); file.ReleaseTrack(audioStream);
return error; return error;
} }
status_t
status_t
BSimpleGameSound::Init(const void* inData, int64 inFrameCount, BSimpleGameSound::Init(const void* inData, int64 inFrameCount,
const gs_audio_format* format) const gs_audio_format* format)
{ {
gs_id sound; gs_id sound;
status_t error = Device()->CreateBuffer(&sound, format, inData, inFrameCount); status_t error
= Device()->CreateBuffer(&sound, format, inData, inFrameCount);
if (error != B_OK) if (error != B_OK)
return error; return error;
BGameSound::Init(sound); BGameSound::Init(sound);
return B_OK; return B_OK;
} }
@@ -393,5 +400,3 @@ BSimpleGameSound::_Reserved_BSimpleGameSound_23(int32 arg, ...)
{ {
return B_ERROR; return B_ERROR;
} }
+24 -24
View File
@@ -25,29 +25,33 @@
// (data not known beforehand) game sounds. // (data not known beforehand) game sounds.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#include "GameSoundDevice.h"
#include "StreamingGameSound.h" #include "StreamingGameSound.h"
#include "GameSoundDevice.h"
BStreamingGameSound::BStreamingGameSound(size_t inBufferFrameCount, BStreamingGameSound::BStreamingGameSound(size_t inBufferFrameCount,
const gs_audio_format *format, const gs_audio_format *format, size_t inBufferCount,
size_t inBufferCount, BGameSoundDevice *device)
BGameSoundDevice *device) :
: BGameSound(device), BGameSound(device),
fStreamHook(NULL), fStreamHook(NULL),
fStreamCookie(NULL) fStreamCookie(NULL)
{ {
if (InitCheck() == B_OK) { if (InitCheck() == B_OK) {
status_t error = SetParameters(inBufferFrameCount, format, inBufferCount); status_t error = SetParameters(inBufferFrameCount, format,
inBufferCount);
SetInitError(error); SetInitError(error);
} }
} }
BStreamingGameSound::BStreamingGameSound(BGameSoundDevice *device) BStreamingGameSound::BStreamingGameSound(BGameSoundDevice *device)
: BGameSound(device), :
fStreamHook(NULL), BGameSound(device),
fStreamCookie(NULL) fStreamHook(NULL),
fStreamCookie(NULL)
{ {
} }
@@ -65,12 +69,12 @@ BStreamingGameSound::Clone() const
status_t status_t
BStreamingGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer, size_t inByteCount, BStreamingGameSound * me), BStreamingGameSound::SetStreamHook(void (*hook)(void* inCookie, void* inBuffer,
void * cookie) size_t inByteCount, BStreamingGameSound * me), void * cookie)
{ {
fStreamHook = hook; fStreamHook = hook;
fStreamCookie = cookie; fStreamCookie = cookie;
return B_OK; return B_OK;
} }
@@ -79,20 +83,19 @@ void
BStreamingGameSound::FillBuffer(void *inBuffer, BStreamingGameSound::FillBuffer(void *inBuffer,
size_t inByteCount) size_t inByteCount)
{ {
if (fStreamHook) if (fStreamHook)
(fStreamHook)(fStreamCookie, inBuffer, inByteCount, this); (fStreamHook)(fStreamCookie, inBuffer, inByteCount, this);
} }
status_t status_t
BStreamingGameSound::Perform(int32 selector, BStreamingGameSound::Perform(int32 selector, void *data)
void *data)
{ {
return B_ERROR; return B_ERROR;
} }
status_t status_t
BStreamingGameSound::SetAttributes(gs_attribute * inAttributes, BStreamingGameSound::SetAttributes(gs_attribute * inAttributes,
size_t inAttributeCount) size_t inAttributeCount)
{ {
@@ -102,14 +105,13 @@ BStreamingGameSound::SetAttributes(gs_attribute * inAttributes,
status_t status_t
BStreamingGameSound::SetParameters(size_t inBufferFrameCount, BStreamingGameSound::SetParameters(size_t inBufferFrameCount,
const gs_audio_format *format, const gs_audio_format *format, size_t inBufferCount)
size_t inBufferCount)
{ {
gs_id sound; gs_id sound;
status_t error = Device()->CreateBuffer(&sound, this, format, status_t error = Device()->CreateBuffer(&sound, this, format,
inBufferFrameCount, inBufferCount); inBufferFrameCount, inBufferCount);
if (error != B_OK) return error; if (error != B_OK) return error;
return BGameSound::Init(sound); return BGameSound::Init(sound);
} }
@@ -302,5 +304,3 @@ BStreamingGameSound::_Reserved_BStreamingGameSound_23(int32 arg, ...)
{ {
return B_ERROR; return B_ERROR;
} }