Author: pulkomandy Date: 2011-11-02 21:05:31 +0100 (Wed, 02 Nov 2011) New Revision: 43128 Changeset: https://dev.haiku-os.org/changeset/43128 Ticket: https://dev.haiku-os.org/ticket/5093 Modified: haiku/trunk/src/kits/game/GameProducer.cpp haiku/trunk/src/kits/game/GameProducer.h haiku/trunk/src/kits/game/GameSoundBuffer.cpp haiku/trunk/src/kits/game/GameSoundBuffer.h haiku/trunk/src/kits/game/GameSoundDevice.cpp haiku/trunk/src/kits/game/GameSoundDevice.h haiku/trunk/src/kits/game/StreamingGameSound.cpp Log: Patch from bkmx. Fixes crashes in the game sound code when using small buffers. Closes #5093, but there are other issues left. Modified: haiku/trunk/src/kits/game/GameProducer.cpp =================================================================== --- haiku/trunk/src/kits/game/GameProducer.cpp 2011-11-02 19:44:46 UTC (rev 43127) +++ haiku/trunk/src/kits/game/GameProducer.cpp 2011-11-02 20:05:31 UTC (rev 43128) @@ -214,11 +214,15 @@ media_node_id id; FindLatencyFor(fOutput.destination, &fLatency, &id); + if (!fBufferGroup) + fBufferSize = fOutput.format.u.raw_audio.buffer_size; + // Have to set it before latency calculating + // Use a dry run to see how long it takes me to fill a buffer of data // The first step to setup the buffer bigtime_t start, produceLatency; - int32 frames = int32(fOutput.format.u.raw_audio.buffer_size / fFrameSize); + int32 frames = int32(fBufferSize / fFrameSize); float* data = new float[frames * 2]; // Second, fill the buffer @@ -243,9 +247,8 @@ // Set up the buffer group for our connection, as long as nobody handed us a // buffer group (via SetBufferGroup()) prior to this. if (!fBufferGroup) { - size_t size = fOutput.format.u.raw_audio.buffer_size; int32 count = int32(fLatency / BufferDuration() + 2); - fBufferGroup = new BBufferGroup(size, count); + fBufferGroup = new BBufferGroup(fBufferSize, count); } } @@ -292,12 +295,18 @@ if (newGroup != NULL) { // we were given a valid group; just use that one from now on fBufferGroup = newGroup; + + // get buffer length from the first buffer + BBuffer *buffers[1]; + if (newGroup->GetBufferList(1, buffers) != B_OK) + return B_BAD_VALUE; + fBufferSize = buffers[0]->SizeAvailable(); } else { // we were passed a NULL group pointer; that means we construct // our own buffer group to use from now on - size_t size = fOutput.format.u.raw_audio.buffer_size; + fBufferSize = fOutput.format.u.raw_audio.buffer_size; int32 count = int32(fLatency / BufferDuration() + 2); - fBufferGroup = new BBufferGroup(size, count); + fBufferGroup = new BBufferGroup(fBufferSize, count); } return B_OK; @@ -336,7 +345,7 @@ // The other run modes dictate various strategies for sacrificing data quality // in the interests of timely data delivery. The way *we* do this is to skip // a buffer, which catches us up in time by one buffer duration. - size_t nSamples = fOutput.format.u.raw_audio.buffer_size / fFrameSize; + size_t nSamples = fBufferSize / fFrameSize; fFramesSent += nSamples; } } @@ -460,7 +469,7 @@ } // track how much media we've delivered so far - size_t nFrames = fOutput.format.u.raw_audio.buffer_size / fFrameSize; + size_t nFrames = fBufferSize / fFrameSize; fFramesSent += nFrames; // The buffer is on its way; now schedule the next one to go @@ -479,9 +488,9 @@ BBuffer* GameProducer::FillNextBuffer(bigtime_t event_time) -{ +{ // get a buffer from our buffer group - BBuffer* buf = fBufferGroup->RequestBuffer(fOutput.format.u.raw_audio.buffer_size, BufferDuration()); + BBuffer* buf = fBufferGroup->RequestBuffer(fBufferSize, BufferDuration()); // if we fail to get a buffer (for example, if the request times out), we skip this // buffer and go on to the next, to avoid locking up the control thread @@ -489,8 +498,8 @@ return NULL; // we need to discribe the buffer - int64 frames = int64(fOutput.format.u.raw_audio.buffer_size / fFrameSize); - memset(buf->Data(), 0, fOutput.format.u.raw_audio.buffer_size); + int64 frames = int64(fBufferSize / fFrameSize); + memset(buf->Data(), 0, fBufferSize); // now fill the buffer with data, continuing where the last buffer left off fObject->Play(buf->Data(), frames); @@ -498,7 +507,7 @@ // fill in the buffer header media_header* hdr = buf->Header(); hdr->type = B_MEDIA_RAW_AUDIO; - hdr->size_used = fOutput.format.u.raw_audio.buffer_size; + hdr->size_used = fBufferSize; hdr->time_source = TimeSource()->ID(); bigtime_t stamp; Modified: haiku/trunk/src/kits/game/GameProducer.h =================================================================== --- haiku/trunk/src/kits/game/GameProducer.h 2011-11-02 19:44:46 UTC (rev 43127) +++ haiku/trunk/src/kits/game/GameProducer.h 2011-11-02 20:05:31 UTC (rev 43128) @@ -146,6 +146,7 @@ size_t fFrameSize; int64 fFramesSent; GameSoundBuffer * fObject; + size_t fBufferSize; }; #endif Modified: haiku/trunk/src/kits/game/GameSoundBuffer.cpp =================================================================== --- haiku/trunk/src/kits/game/GameSoundBuffer.cpp 2011-11-02 19:44:46 UTC (rev 43127) +++ haiku/trunk/src/kits/game/GameSoundBuffer.cpp 2011-11-02 20:05:31 UTC (rev 43128) @@ -32,6 +32,7 @@ #include <MediaAddOn.h> #include <MediaTheme.h> #include <TimeSource.h> +#include <BufferGroup.h> #include "GameProducer.h" #include "GameSoundBuffer.h" @@ -271,7 +272,7 @@ pan[1] = fPanLeft; char * buffer = new char[fFrameSize * frames]; - + FillBuffer(buffer, frames); switch (fFormat.format) { @@ -533,11 +534,17 @@ // StreamingSoundBuffer ------------------------------------------------------ StreamingSoundBuffer::StreamingSoundBuffer(const gs_audio_format * format, - const void * streamHook) + const void * streamHook, size_t inBufferFrameCount, + size_t inBufferCount) : GameSoundBuffer(format), fStreamHook(const_cast<void *>(streamHook)) { + if (inBufferFrameCount != 0 && inBufferCount != 0) { + BBufferGroup *bufferGroup = new BBufferGroup(inBufferFrameCount + * fFrameSize, inBufferCount); + fNode->SetBufferGroup(fConnection->source, bufferGroup); + } } @@ -554,4 +561,3 @@ size_t bytes = fFrameSize * frames; object->FillBuffer(buffer, bytes); } - Modified: haiku/trunk/src/kits/game/GameSoundBuffer.h =================================================================== --- haiku/trunk/src/kits/game/GameSoundBuffer.h 2011-11-02 19:44:46 UTC (rev 43127) +++ haiku/trunk/src/kits/game/GameSoundBuffer.h 2011-11-02 20:05:31 UTC (rev 43128) @@ -65,10 +65,11 @@ size_t fFrameSize; + Connection * fConnection; + GameProducer * fNode; + private: - Connection * fConnection; - GameProducer * fNode; bool fIsConnected; bool fIsPlaying; @@ -103,7 +104,9 @@ class StreamingSoundBuffer : public GameSoundBuffer { public: StreamingSoundBuffer(const gs_audio_format * format, - const void * streamHook); + const void * streamHook, + size_t inBufferFrameCount, + size_t inBufferCount); virtual ~StreamingSoundBuffer(); protected: Modified: haiku/trunk/src/kits/game/GameSoundDevice.cpp =================================================================== --- haiku/trunk/src/kits/game/GameSoundDevice.cpp 2011-11-02 19:44:46 UTC (rev 43127) +++ haiku/trunk/src/kits/game/GameSoundDevice.cpp 2011-11-02 20:05:31 UTC (rev 43128) @@ -161,7 +161,8 @@ status_t BGameSoundDevice::CreateBuffer(gs_id* sound, const void* object, - const gs_audio_format* format) + const gs_audio_format* format, size_t inBufferFrameCount, + size_t inBufferCount) { if (!object || !sound) return B_BAD_VALUE; @@ -172,7 +173,8 @@ if (position >= 0) { media_node systemMixer; BMediaRoster::Roster()->GetAudioMixer(&systemMixer); - fSounds[position] = new StreamingSoundBuffer(format, object); + fSounds[position] = new StreamingSoundBuffer(format, object, + inBufferFrameCount, inBufferCount); err = fSounds[position]->Connect(&systemMixer); } Modified: haiku/trunk/src/kits/game/GameSoundDevice.h =================================================================== --- haiku/trunk/src/kits/game/GameSoundDevice.h 2011-11-02 19:44:46 UTC (rev 43127) +++ haiku/trunk/src/kits/game/GameSoundDevice.h 2011-11-02 20:05:31 UTC (rev 43128) @@ -51,7 +51,9 @@ int64 frames); virtual status_t CreateBuffer(gs_id * sound, const void * object, - const gs_audio_format * format); + const gs_audio_format * format, + size_t inBufferFrameCount = 0, + size_t inBufferCount = 0); virtual void ReleaseBuffer(gs_id sound); virtual status_t Buffer(gs_id sound, @@ -73,6 +75,7 @@ void SetInitError(status_t error); gs_audio_format fFormat; + private: int32 AllocateSound(); Modified: haiku/trunk/src/kits/game/StreamingGameSound.cpp =================================================================== --- haiku/trunk/src/kits/game/StreamingGameSound.cpp 2011-11-02 19:44:46 UTC (rev 43127) +++ haiku/trunk/src/kits/game/StreamingGameSound.cpp 2011-11-02 20:05:31 UTC (rev 43128) @@ -106,7 +106,8 @@ size_t inBufferCount) { gs_id sound; - status_t error = Device()->CreateBuffer(&sound, this, format); + status_t error = Device()->CreateBuffer(&sound, this, format, + inBufferFrameCount, inBufferCount); if (error != B_OK) return error; return BGameSound::Init(sound);