diff --git a/Source/Core/Common/Src/FixedSizeQueue.h b/Source/Core/Common/Src/FixedSizeQueue.h new file mode 100644 index 0000000000..e0d4fea84b --- /dev/null +++ b/Source/Core/Common/Src/FixedSizeQueue.h @@ -0,0 +1,81 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _FIXED_SIZE_QUEUE_H +#define _FIXED_SIZE_QUEUE_H + +// STL-look-a-like interface, but name is mixed case to distinguish it clearly from the +// real STL classes. + +// Not fully featured, no safety checking yet. Add features as needed. + +// TODO: "inline" storage? + +template +class FixedSizeQueue +{ + T *storage; + int head; + int tail; + int count; // sacrifice 4 bytes for a simpler implementation. may optimize away in the future. + + // Make copy constructor private for now. + FixedSizeQueue(FixedSizeQueue &other) { } + +public: + FixedSizeQueue() + { + head = 0; + tail = 0; + storage = new T[N]; + } + + ~FixedSizeQueue() + { + delete storage; + } + + void push(T t) { + storage[tail] = t; + tail++; + if (tail == N) + tail = 0; + count++; + } + + void pop() { + head++; + if (head == N) + head = 0; + count--; + } + + T pop_front() { + const T &temp = storage[head]; + pop(); + return temp; + } + + T &front() { return storage[head]; } + const T &front() const { return storage[head]; } + + size_t size() const { + return count; + } +}; + +#endif // _FIXED_SIZE_QUEUE_H \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp index bf86a6e2eb..2226d3f034 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp @@ -23,6 +23,8 @@ #include "../DSPHandler.h" #include "Thread.h" #include "Mixer.h" +#include "FixedSizeQueue.h" + #ifdef _WIN32 #include "../PCHW/DSoundStream.h" #endif @@ -31,8 +33,11 @@ namespace { Common::CriticalSection push_sync; // On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so... -int queue_maxlength = 1024 * 8; -std::queue sample_queue; +const int queue_minlength = 1024 * 4; +const int queue_maxlength = 1024 * 28; + +FixedSizeQueue sample_queue; + } // namespace volatile bool mixer_HLEready = false; @@ -59,15 +64,20 @@ void Mixer(short *buffer, int numSamples, int bits, int rate, int channels) push_sync.Enter(); int count = 0; - while (sample_queue.size() && count < numSamples * 2) { + while (queue_size > queue_minlength && count < numSamples * 2) { int x = buffer[count]; x += sample_queue.front(); if (x > 32767) x = 32767; if (x < -32767) x = -32767; - buffer[count] = x; - count++; + buffer[count++] = x; sample_queue.pop(); - queue_size--; + x = buffer[count]; + x += sample_queue.front(); + if (x > 32767) x = 32767; + if (x < -32767) x = -32767; + buffer[count++] = x; + sample_queue.pop(); + queue_size-=2; } push_sync.Leave(); } @@ -77,6 +87,12 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) { // if (!f) // f = fopen("d:\\hello.raw", "wb"); // fwrite(buffer, num_stereo_samples * 4, 1, f); + if (queue_size == 0) + { + queue_size = queue_minlength; + for (int i = 0; i < queue_minlength; i++) + sample_queue.push((s16)0); + } static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; @@ -84,15 +100,15 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) { #ifdef _WIN32 if (!GetAsyncKeyState(VK_TAB)) { - while (queue_size > queue_maxlength / 2) { - DSound::DSound_UpdateSound(); - Sleep(0); - } + while (queue_size > queue_maxlength / 2) { + DSound::DSound_UpdateSound(); + Sleep(0); + } } else { return; } #else - while (queue_size > queue_maxlength / 2) { + while (queue_size > queue_maxlength) { sleep(0); } #endif @@ -103,7 +119,7 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) { while (num_stereo_samples) { acc += sample_rate; - while (num_stereo_samples && (acc>=48000)) + while (num_stereo_samples && (acc >= 48000)) { PV4l=PV3l; PV3l=PV2l;