Reformat all the things. Have fun with merge conflicts.

This commit is contained in:
Pierre Bourdon
2016-06-24 10:43:46 +02:00
parent 2115e8a4a6
commit 3570c7f03a
1116 changed files with 187350 additions and 180289 deletions
File diff suppressed because it is too large Load Diff
+238 -238
View File
@@ -9,249 +9,249 @@
namespace ButtonManager namespace ButtonManager
{ {
enum ButtonType enum ButtonType
{ {
// GC // GC
BUTTON_A = 0, BUTTON_A = 0,
BUTTON_B = 1, BUTTON_B = 1,
BUTTON_START = 2, BUTTON_START = 2,
BUTTON_X = 3, BUTTON_X = 3,
BUTTON_Y = 4, BUTTON_Y = 4,
BUTTON_Z = 5, BUTTON_Z = 5,
BUTTON_UP = 6, BUTTON_UP = 6,
BUTTON_DOWN = 7, BUTTON_DOWN = 7,
BUTTON_LEFT = 8, BUTTON_LEFT = 8,
BUTTON_RIGHT = 9, BUTTON_RIGHT = 9,
STICK_MAIN = 10, // Used on Java Side STICK_MAIN = 10, // Used on Java Side
STICK_MAIN_UP = 11, STICK_MAIN_UP = 11,
STICK_MAIN_DOWN = 12, STICK_MAIN_DOWN = 12,
STICK_MAIN_LEFT = 13, STICK_MAIN_LEFT = 13,
STICK_MAIN_RIGHT = 14, STICK_MAIN_RIGHT = 14,
STICK_C = 15, // Used on Java Side STICK_C = 15, // Used on Java Side
STICK_C_UP = 16, STICK_C_UP = 16,
STICK_C_DOWN = 17, STICK_C_DOWN = 17,
STICK_C_LEFT = 18, STICK_C_LEFT = 18,
STICK_C_RIGHT = 19, STICK_C_RIGHT = 19,
TRIGGER_L = 20, TRIGGER_L = 20,
TRIGGER_R = 21, TRIGGER_R = 21,
// Wiimote // Wiimote
WIIMOTE_BUTTON_A = 100, WIIMOTE_BUTTON_A = 100,
WIIMOTE_BUTTON_B = 101, WIIMOTE_BUTTON_B = 101,
WIIMOTE_BUTTON_MINUS = 102, WIIMOTE_BUTTON_MINUS = 102,
WIIMOTE_BUTTON_PLUS = 103, WIIMOTE_BUTTON_PLUS = 103,
WIIMOTE_BUTTON_HOME = 104, WIIMOTE_BUTTON_HOME = 104,
WIIMOTE_BUTTON_1 = 105, WIIMOTE_BUTTON_1 = 105,
WIIMOTE_BUTTON_2 = 106, WIIMOTE_BUTTON_2 = 106,
WIIMOTE_UP = 107, WIIMOTE_UP = 107,
WIIMOTE_DOWN = 108, WIIMOTE_DOWN = 108,
WIIMOTE_LEFT = 109, WIIMOTE_LEFT = 109,
WIIMOTE_RIGHT = 110, WIIMOTE_RIGHT = 110,
WIIMOTE_IR = 111, // To Be Used on Java Side WIIMOTE_IR = 111, // To Be Used on Java Side
WIIMOTE_IR_UP = 112, WIIMOTE_IR_UP = 112,
WIIMOTE_IR_DOWN = 113, WIIMOTE_IR_DOWN = 113,
WIIMOTE_IR_LEFT = 114, WIIMOTE_IR_LEFT = 114,
WIIMOTE_IR_RIGHT = 115, WIIMOTE_IR_RIGHT = 115,
WIIMOTE_IR_FORWARD = 116, WIIMOTE_IR_FORWARD = 116,
WIIMOTE_IR_BACKWARD = 117, WIIMOTE_IR_BACKWARD = 117,
WIIMOTE_IR_HIDE = 118, WIIMOTE_IR_HIDE = 118,
WIIMOTE_SWING = 119, // To Be Used on Java Side WIIMOTE_SWING = 119, // To Be Used on Java Side
WIIMOTE_SWING_UP = 120, WIIMOTE_SWING_UP = 120,
WIIMOTE_SWING_DOWN = 121, WIIMOTE_SWING_DOWN = 121,
WIIMOTE_SWING_LEFT = 122, WIIMOTE_SWING_LEFT = 122,
WIIMOTE_SWING_RIGHT = 123, WIIMOTE_SWING_RIGHT = 123,
WIIMOTE_SWING_FORWARD = 124, WIIMOTE_SWING_FORWARD = 124,
WIIMOTE_SWING_BACKWARD = 125, WIIMOTE_SWING_BACKWARD = 125,
WIIMOTE_TILT = 126, // To Be Used on Java Side WIIMOTE_TILT = 126, // To Be Used on Java Side
WIIMOTE_TILT_FORWARD = 127, WIIMOTE_TILT_FORWARD = 127,
WIIMOTE_TILT_BACKWARD = 128, WIIMOTE_TILT_BACKWARD = 128,
WIIMOTE_TILT_LEFT = 129, WIIMOTE_TILT_LEFT = 129,
WIIMOTE_TILT_RIGHT = 130, WIIMOTE_TILT_RIGHT = 130,
WIIMOTE_TILT_MODIFIER = 131, WIIMOTE_TILT_MODIFIER = 131,
WIIMOTE_SHAKE_X = 132, WIIMOTE_SHAKE_X = 132,
WIIMOTE_SHAKE_Y = 133, WIIMOTE_SHAKE_Y = 133,
WIIMOTE_SHAKE_Z = 134, WIIMOTE_SHAKE_Z = 134,
//Nunchuk // Nunchuk
NUNCHUK_BUTTON_C = 200, NUNCHUK_BUTTON_C = 200,
NUNCHUK_BUTTON_Z = 201, NUNCHUK_BUTTON_Z = 201,
NUNCHUK_STICK = 202, // To Be Used on Java Side NUNCHUK_STICK = 202, // To Be Used on Java Side
NUNCHUK_STICK_UP = 203, NUNCHUK_STICK_UP = 203,
NUNCHUK_STICK_DOWN = 204, NUNCHUK_STICK_DOWN = 204,
NUNCHUK_STICK_LEFT = 205, NUNCHUK_STICK_LEFT = 205,
NUNCHUK_STICK_RIGHT = 206, NUNCHUK_STICK_RIGHT = 206,
NUNCHUK_SWING = 207, // To Be Used on Java Side NUNCHUK_SWING = 207, // To Be Used on Java Side
NUNCHUK_SWING_UP = 208, NUNCHUK_SWING_UP = 208,
NUNCHUK_SWING_DOWN = 209, NUNCHUK_SWING_DOWN = 209,
NUNCHUK_SWING_LEFT = 210, NUNCHUK_SWING_LEFT = 210,
NUNCHUK_SWING_RIGHT = 211, NUNCHUK_SWING_RIGHT = 211,
NUNCHUK_SWING_FORWARD = 212, NUNCHUK_SWING_FORWARD = 212,
NUNCHUK_SWING_BACKWARD = 213, NUNCHUK_SWING_BACKWARD = 213,
NUNCHUK_TILT = 214, // To Be Used on Java Side NUNCHUK_TILT = 214, // To Be Used on Java Side
NUNCHUK_TILT_FORWARD = 215, NUNCHUK_TILT_FORWARD = 215,
NUNCHUK_TILT_BACKWARD = 216, NUNCHUK_TILT_BACKWARD = 216,
NUNCHUK_TILT_LEFT = 217, NUNCHUK_TILT_LEFT = 217,
NUNCHUK_TILT_RIGHT = 218, NUNCHUK_TILT_RIGHT = 218,
NUNCHUK_TILT_MODIFIER = 219, NUNCHUK_TILT_MODIFIER = 219,
NUNCHUK_SHAKE_X = 220, NUNCHUK_SHAKE_X = 220,
NUNCHUK_SHAKE_Y = 221, NUNCHUK_SHAKE_Y = 221,
NUNCHUK_SHAKE_Z = 222, NUNCHUK_SHAKE_Z = 222,
//Classic // Classic
CLASSIC_BUTTON_A = 300, CLASSIC_BUTTON_A = 300,
CLASSIC_BUTTON_B = 301, CLASSIC_BUTTON_B = 301,
CLASSIC_BUTTON_X = 302, CLASSIC_BUTTON_X = 302,
CLASSIC_BUTTON_Y = 303, CLASSIC_BUTTON_Y = 303,
CLASSIC_BUTTON_MINUS = 304, CLASSIC_BUTTON_MINUS = 304,
CLASSIC_BUTTON_PLUS = 305, CLASSIC_BUTTON_PLUS = 305,
CLASSIC_BUTTON_HOME = 306, CLASSIC_BUTTON_HOME = 306,
CLASSIC_BUTTON_ZL = 307, CLASSIC_BUTTON_ZL = 307,
CLASSIC_BUTTON_ZR = 308, CLASSIC_BUTTON_ZR = 308,
CLASSIC_DPAD_UP = 309, CLASSIC_DPAD_UP = 309,
CLASSIC_DPAD_DOWN = 310, CLASSIC_DPAD_DOWN = 310,
CLASSIC_DPAD_LEFT = 311, CLASSIC_DPAD_LEFT = 311,
CLASSIC_DPAD_RIGHT = 312, CLASSIC_DPAD_RIGHT = 312,
CLASSIC_STICK_LEFT = 313, // To Be Used on Java Side CLASSIC_STICK_LEFT = 313, // To Be Used on Java Side
CLASSIC_STICK_LEFT_UP = 314, CLASSIC_STICK_LEFT_UP = 314,
CLASSIC_STICK_LEFT_DOWN = 315, CLASSIC_STICK_LEFT_DOWN = 315,
CLASSIC_STICK_LEFT_LEFT = 316, CLASSIC_STICK_LEFT_LEFT = 316,
CLASSIC_STICK_LEFT_RIGHT = 317, CLASSIC_STICK_LEFT_RIGHT = 317,
CLASSIC_STICK_RIGHT = 318, // To Be Used on Java Side CLASSIC_STICK_RIGHT = 318, // To Be Used on Java Side
CLASSIC_STICK_RIGHT_UP = 319, CLASSIC_STICK_RIGHT_UP = 319,
CLASSIC_STICK_RIGHT_DOWN = 320, CLASSIC_STICK_RIGHT_DOWN = 320,
CLASSIC_STICK_RIGHT_LEFT = 321, CLASSIC_STICK_RIGHT_LEFT = 321,
CLASSIC_STICK_RIGHT_RIGHT = 322, CLASSIC_STICK_RIGHT_RIGHT = 322,
CLASSIC_TRIGGER_L = 323, CLASSIC_TRIGGER_L = 323,
CLASSIC_TRIGGER_R = 324, CLASSIC_TRIGGER_R = 324,
//Guitar // Guitar
GUITAR_BUTTON_MINUS = 400, GUITAR_BUTTON_MINUS = 400,
GUITAR_BUTTON_PLUS = 401, GUITAR_BUTTON_PLUS = 401,
GUITAR_FRET_GREEN = 402, GUITAR_FRET_GREEN = 402,
GUITAR_FRET_RED = 403, GUITAR_FRET_RED = 403,
GUITAR_FRET_YELLOW = 404, GUITAR_FRET_YELLOW = 404,
GUITAR_FRET_BLUE = 405, GUITAR_FRET_BLUE = 405,
GUITAR_FRET_ORANGE = 406, GUITAR_FRET_ORANGE = 406,
GUITAR_STRUM_UP = 407, GUITAR_STRUM_UP = 407,
GUITAR_STRUM_DOWN = 408, GUITAR_STRUM_DOWN = 408,
GUITAR_STICK = 409, // To Be Used on Java Side GUITAR_STICK = 409, // To Be Used on Java Side
GUITAR_STICK_UP = 410, GUITAR_STICK_UP = 410,
GUITAR_STICK_DOWN = 411, GUITAR_STICK_DOWN = 411,
GUITAR_STICK_LEFT = 412, GUITAR_STICK_LEFT = 412,
GUITAR_STICK_RIGHT = 413, GUITAR_STICK_RIGHT = 413,
GUITAR_WHAMMY_BAR = 414, GUITAR_WHAMMY_BAR = 414,
//Drums // Drums
DRUMS_BUTTON_MINUS = 500, DRUMS_BUTTON_MINUS = 500,
DRUMS_BUTTON_PLUS = 501, DRUMS_BUTTON_PLUS = 501,
DRUMS_PAD_RED = 502, DRUMS_PAD_RED = 502,
DRUMS_PAD_YELLOW = 503, DRUMS_PAD_YELLOW = 503,
DRUMS_PAD_BLUE = 504, DRUMS_PAD_BLUE = 504,
DRUMS_PAD_GREEN = 505, DRUMS_PAD_GREEN = 505,
DRUMS_PAD_ORANGE = 506, DRUMS_PAD_ORANGE = 506,
DRUMS_PAD_BASS = 507, DRUMS_PAD_BASS = 507,
DRUMS_STICK = 508, // To Be Used on Java Side DRUMS_STICK = 508, // To Be Used on Java Side
DRUMS_STICK_UP = 509, DRUMS_STICK_UP = 509,
DRUMS_STICK_DOWN = 510, DRUMS_STICK_DOWN = 510,
DRUMS_STICK_LEFT = 511, DRUMS_STICK_LEFT = 511,
DRUMS_STICK_RIGHT = 512, DRUMS_STICK_RIGHT = 512,
//Turntable // Turntable
TURNTABLE_BUTTON_GREEN_LEFT = 600, TURNTABLE_BUTTON_GREEN_LEFT = 600,
TURNTABLE_BUTTON_RED_LEFT = 601, TURNTABLE_BUTTON_RED_LEFT = 601,
TURNTABLE_BUTTON_BLUE_LEFT = 602, TURNTABLE_BUTTON_BLUE_LEFT = 602,
TURNTABLE_BUTTON_GREEN_RIGHT = 603, TURNTABLE_BUTTON_GREEN_RIGHT = 603,
TURNTABLE_BUTTON_RED_RIGHT = 604, TURNTABLE_BUTTON_RED_RIGHT = 604,
TURNTABLE_BUTTON_BLUE_RIGHT = 605, TURNTABLE_BUTTON_BLUE_RIGHT = 605,
TURNTABLE_BUTTON_MINUS = 606, TURNTABLE_BUTTON_MINUS = 606,
TURNTABLE_BUTTON_PLUS = 607, TURNTABLE_BUTTON_PLUS = 607,
TURNTABLE_BUTTON_HOME = 608, TURNTABLE_BUTTON_HOME = 608,
TURNTABLE_BUTTON_EUPHORIA = 609, TURNTABLE_BUTTON_EUPHORIA = 609,
TURNTABLE_TABLE_LEFT = 610, // To Be Used on Java Side TURNTABLE_TABLE_LEFT = 610, // To Be Used on Java Side
TURNTABLE_TABLE_LEFT_LEFT = 611, TURNTABLE_TABLE_LEFT_LEFT = 611,
TURNTABLE_TABLE_LEFT_RIGHT = 612, TURNTABLE_TABLE_LEFT_RIGHT = 612,
TURNTABLE_TABLE_RIGHT = 613, // To Be Used on Java Side TURNTABLE_TABLE_RIGHT = 613, // To Be Used on Java Side
TURNTABLE_TABLE_RIGHT_LEFT = 614, TURNTABLE_TABLE_RIGHT_LEFT = 614,
TURNTABLE_TABLE_RIGHT_RIGHT = 615, TURNTABLE_TABLE_RIGHT_RIGHT = 615,
TURNTABLE_STICK = 616, // To Be Used on Java Side TURNTABLE_STICK = 616, // To Be Used on Java Side
TURNTABLE_STICK_UP = 617, TURNTABLE_STICK_UP = 617,
TURNTABLE_STICK_DOWN = 618, TURNTABLE_STICK_DOWN = 618,
TURNTABLE_STICK_LEFT = 619, TURNTABLE_STICK_LEFT = 619,
TURNTABLE_STICK_RIGHT = 620, TURNTABLE_STICK_RIGHT = 620,
TURNTABLE_EFFECT_DIAL = 621, TURNTABLE_EFFECT_DIAL = 621,
TURNTABLE_CROSSFADE = 622, // To Be Used on Java Side TURNTABLE_CROSSFADE = 622, // To Be Used on Java Side
TURNTABLE_CROSSFADE_LEFT = 623, TURNTABLE_CROSSFADE_LEFT = 623,
TURNTABLE_CROSSFADE_RIGHT = 624, TURNTABLE_CROSSFADE_RIGHT = 624,
}; };
enum ButtonState enum ButtonState
{ {
BUTTON_RELEASED = 0, BUTTON_RELEASED = 0,
BUTTON_PRESSED = 1 BUTTON_PRESSED = 1
}; };
enum BindType enum BindType
{ {
BIND_BUTTON = 0, BIND_BUTTON = 0,
BIND_AXIS BIND_AXIS
}; };
class Button class Button
{ {
private: private:
ButtonState m_state; ButtonState m_state;
public:
Button() : m_state(BUTTON_RELEASED) {}
void SetState(ButtonState state) { m_state = state; }
bool Pressed() { return m_state == BUTTON_PRESSED; }
~Button() {} public:
}; Button() : m_state(BUTTON_RELEASED) {}
class Axis void SetState(ButtonState state) { m_state = state; }
{ bool Pressed() { return m_state == BUTTON_PRESSED; }
private: ~Button() {}
float m_value; };
public: class Axis
Axis() : m_value(0.0f) {} {
void SetValue(float value) { m_value = value; } private:
float AxisValue() { return m_value; } float m_value;
~Axis() {} public:
}; Axis() : m_value(0.0f) {}
void SetValue(float value) { m_value = value; }
float AxisValue() { return m_value; }
~Axis() {}
};
struct sBind struct sBind
{ {
const int _padID; const int _padID;
const ButtonType _buttontype; const ButtonType _buttontype;
const BindType _bindtype; const BindType _bindtype;
const int _bind; const int _bind;
const float _neg; const float _neg;
sBind(int padID, ButtonType buttontype, BindType bindtype, int bind, float neg) sBind(int padID, ButtonType buttontype, BindType bindtype, int bind, float neg)
: _padID(padID), _buttontype(buttontype), _bindtype(bindtype), _bind(bind), _neg(neg) : _padID(padID), _buttontype(buttontype), _bindtype(bindtype), _bind(bind), _neg(neg)
{} {
}; }
};
class InputDevice
{
private:
const std::string _dev;
std::map<ButtonType, bool> _buttons;
std::map<ButtonType, float> _axises;
class InputDevice // Key is padID and ButtonType
{ std::map<std::pair<int, ButtonType>, sBind*> _inputbinds;
private:
const std::string _dev;
std::map<ButtonType, bool> _buttons;
std::map<ButtonType, float> _axises;
// Key is padID and ButtonType public:
std::map<std::pair<int, ButtonType>, sBind*> _inputbinds; InputDevice(std::string dev) : _dev(dev) {}
public: ~InputDevice()
InputDevice(std::string dev) {
: _dev(dev) {} for (const auto& bind : _inputbinds)
~InputDevice() delete bind.second;
{ _inputbinds.clear();
for (const auto& bind : _inputbinds) }
delete bind.second; void AddBind(sBind* bind) { _inputbinds[std::make_pair(bind->_padID, bind->_buttontype)] = bind; }
_inputbinds.clear(); bool PressEvent(int button, int action);
} void AxisEvent(int axis, float value);
void AddBind(sBind* bind) { _inputbinds[std::make_pair(bind->_padID, bind->_buttontype)] = bind; } bool ButtonValue(int padID, ButtonType button);
bool PressEvent(int button, int action); float AxisValue(int padID, ButtonType axis);
void AxisEvent(int axis, float value); };
bool ButtonValue(int padID, ButtonType button);
float AxisValue(int padID, ButtonType axis);
};
void Init(); void Init();
bool GetButtonPressed(int padID, ButtonType button); bool GetButtonPressed(int padID, ButtonType button);
float GetAxisValue(int padID, ButtonType axis); float GetAxisValue(int padID, ButtonType axis);
bool GamepadEvent(const std::string& dev, int button, int action); bool GamepadEvent(const std::string& dev, int button, int action);
void GamepadAxisEvent(const std::string& dev, int axis, float value); void GamepadAxisEvent(const std::string& dev, int axis, float value);
void Shutdown(); void Shutdown();
} }
File diff suppressed because it is too large Load Diff
+42 -42
View File
@@ -6,77 +6,77 @@
#include "AudioCommon/AOSoundStream.h" #include "AudioCommon/AOSoundStream.h"
#include "AudioCommon/Mixer.h" #include "AudioCommon/Mixer.h"
#include "Common/MsgHandler.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#if defined(HAVE_AO) && HAVE_AO #if defined(HAVE_AO) && HAVE_AO
void AOSound::SoundLoop() void AOSound::SoundLoop()
{ {
Common::SetCurrentThreadName("Audio thread - ao"); Common::SetCurrentThreadName("Audio thread - ao");
uint_32 numBytesToRender = 256; uint_32 numBytesToRender = 256;
ao_initialize(); ao_initialize();
default_driver = ao_default_driver_id(); default_driver = ao_default_driver_id();
format.bits = 16; format.bits = 16;
format.channels = 2; format.channels = 2;
format.rate = m_mixer->GetSampleRate(); format.rate = m_mixer->GetSampleRate();
format.byte_format = AO_FMT_LITTLE; format.byte_format = AO_FMT_LITTLE;
device = ao_open_live(default_driver, &format, nullptr /* no options */); device = ao_open_live(default_driver, &format, nullptr /* no options */);
if (!device) if (!device)
{ {
PanicAlertT("AudioCommon: Error opening AO device.\n"); PanicAlertT("AudioCommon: Error opening AO device.\n");
ao_shutdown(); ao_shutdown();
Stop(); Stop();
return; return;
} }
buf_size = format.bits/8 * format.channels * format.rate; buf_size = format.bits / 8 * format.channels * format.rate;
while (m_run_thread.load()) while (m_run_thread.load())
{ {
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2); m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
{ {
std::lock_guard<std::mutex> lk(soundCriticalSection); std::lock_guard<std::mutex> lk(soundCriticalSection);
ao_play(device, (char*)realtimeBuffer, numBytesToRender); ao_play(device, (char*)realtimeBuffer, numBytesToRender);
} }
soundSyncEvent.Wait(); soundSyncEvent.Wait();
} }
} }
bool AOSound::Start() bool AOSound::Start()
{ {
m_run_thread.store(true); m_run_thread.store(true);
memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); memset(realtimeBuffer, 0, sizeof(realtimeBuffer));
thread = std::thread(&AOSound::SoundLoop, this); thread = std::thread(&AOSound::SoundLoop, this);
return true; return true;
} }
void AOSound::Update() void AOSound::Update()
{ {
soundSyncEvent.Set(); soundSyncEvent.Set();
} }
void AOSound::Stop() void AOSound::Stop()
{ {
m_run_thread.store(false); m_run_thread.store(false);
soundSyncEvent.Set(); soundSyncEvent.Set();
{ {
std::lock_guard<std::mutex> lk(soundCriticalSection); std::lock_guard<std::mutex> lk(soundCriticalSection);
thread.join(); thread.join();
if (device) if (device)
ao_close(device); ao_close(device);
ao_shutdown(); ao_shutdown();
device = nullptr; device = nullptr;
} }
} }
#endif #endif
+14 -18
View File
@@ -19,29 +19,25 @@
class AOSound final : public SoundStream class AOSound final : public SoundStream
{ {
#if defined(HAVE_AO) && HAVE_AO #if defined(HAVE_AO) && HAVE_AO
std::thread thread; std::thread thread;
std::atomic<bool> m_run_thread; std::atomic<bool> m_run_thread;
std::mutex soundCriticalSection; std::mutex soundCriticalSection;
Common::Event soundSyncEvent; Common::Event soundSyncEvent;
int buf_size; int buf_size;
ao_device *device; ao_device* device;
ao_sample_format format; ao_sample_format format;
int default_driver; int default_driver;
short realtimeBuffer[1024 * 1024]; short realtimeBuffer[1024 * 1024];
public: public:
bool Start() override; bool Start() override;
void SoundLoop() override; void SoundLoop() override;
void Stop() override; void Stop() override;
void Update() override; void Update() override;
static bool isValid()
{
return true;
}
static bool isValid() { return true; }
#endif #endif
}; };
+170 -171
View File
@@ -6,230 +6,229 @@
#include "AudioCommon/AlsaSoundStream.h" #include "AudioCommon/AlsaSoundStream.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Thread.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/Thread.h"
AlsaSound::AlsaSound() AlsaSound::AlsaSound()
: m_thread_status(ALSAThreadStatus::STOPPED) : m_thread_status(ALSAThreadStatus::STOPPED), handle(nullptr),
, handle(nullptr) frames_to_deliver(FRAME_COUNT_MIN)
, frames_to_deliver(FRAME_COUNT_MIN)
{ {
} }
bool AlsaSound::Start() bool AlsaSound::Start()
{ {
m_thread_status.store(ALSAThreadStatus::RUNNING); m_thread_status.store(ALSAThreadStatus::RUNNING);
if (!AlsaInit()) if (!AlsaInit())
{ {
m_thread_status.store(ALSAThreadStatus::STOPPED); m_thread_status.store(ALSAThreadStatus::STOPPED);
return false; return false;
} }
thread = std::thread(&AlsaSound::SoundLoop, this); thread = std::thread(&AlsaSound::SoundLoop, this);
return true; return true;
} }
void AlsaSound::Stop() void AlsaSound::Stop()
{ {
m_thread_status.store(ALSAThreadStatus::STOPPING); m_thread_status.store(ALSAThreadStatus::STOPPING);
//Give the opportunity to the audio thread // Give the opportunity to the audio thread
//to realize we are stopping the emulation // to realize we are stopping the emulation
cv.notify_one(); cv.notify_one();
thread.join(); thread.join();
} }
void AlsaSound::Update() void AlsaSound::Update()
{ {
// don't need to do anything here. // don't need to do anything here.
} }
// Called on audio thread. // Called on audio thread.
void AlsaSound::SoundLoop() void AlsaSound::SoundLoop()
{ {
Common::SetCurrentThreadName("Audio thread - alsa"); Common::SetCurrentThreadName("Audio thread - alsa");
while (m_thread_status.load() != ALSAThreadStatus::STOPPING) while (m_thread_status.load() != ALSAThreadStatus::STOPPING)
{ {
while (m_thread_status.load() == ALSAThreadStatus::RUNNING) while (m_thread_status.load() == ALSAThreadStatus::RUNNING)
{ {
m_mixer->Mix(mix_buffer, frames_to_deliver); m_mixer->Mix(mix_buffer, frames_to_deliver);
int rc = snd_pcm_writei(handle, mix_buffer, frames_to_deliver); int rc = snd_pcm_writei(handle, mix_buffer, frames_to_deliver);
if (rc == -EPIPE) if (rc == -EPIPE)
{ {
// Underrun // Underrun
snd_pcm_prepare(handle); snd_pcm_prepare(handle);
} }
else if (rc < 0) else if (rc < 0)
{ {
ERROR_LOG(AUDIO, "writei fail: %s", snd_strerror(rc)); ERROR_LOG(AUDIO, "writei fail: %s", snd_strerror(rc));
} }
} }
if (m_thread_status.load() == ALSAThreadStatus::PAUSED) if (m_thread_status.load() == ALSAThreadStatus::PAUSED)
{ {
snd_pcm_drop(handle); // Stop sound output snd_pcm_drop(handle); // Stop sound output
// Block until thread status changes. // Block until thread status changes.
std::unique_lock<std::mutex> lock(cv_m); std::unique_lock<std::mutex> lock(cv_m);
cv.wait(lock, [this]{ return m_thread_status.load() != ALSAThreadStatus::PAUSED; }); cv.wait(lock, [this] { return m_thread_status.load() != ALSAThreadStatus::PAUSED; });
snd_pcm_prepare(handle); // resume sound output snd_pcm_prepare(handle); // resume sound output
} }
} }
AlsaShutdown(); AlsaShutdown();
m_thread_status.store(ALSAThreadStatus::STOPPED); m_thread_status.store(ALSAThreadStatus::STOPPED);
} }
void AlsaSound::Clear(bool muted) void AlsaSound::Clear(bool muted)
{ {
m_muted = muted; m_muted = muted;
m_thread_status.store(muted ? ALSAThreadStatus::PAUSED : ALSAThreadStatus::RUNNING); m_thread_status.store(muted ? ALSAThreadStatus::PAUSED : ALSAThreadStatus::RUNNING);
cv.notify_one(); // Notify thread that status has changed cv.notify_one(); // Notify thread that status has changed
} }
bool AlsaSound::AlsaInit() bool AlsaSound::AlsaInit()
{ {
unsigned int sample_rate = m_mixer->GetSampleRate(); unsigned int sample_rate = m_mixer->GetSampleRate();
int err; int err;
int dir; int dir;
snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_t* swparams;
snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_t* hwparams;
snd_pcm_uframes_t buffer_size,buffer_size_max; snd_pcm_uframes_t buffer_size, buffer_size_max;
unsigned int periods; unsigned int periods;
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Audio open error: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Audio open error: %s\n", snd_strerror(err));
return false; return false;
} }
snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_alloca(&hwparams);
err = snd_pcm_hw_params_any(handle, hwparams); err = snd_pcm_hw_params_any(handle, hwparams);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Broken configuration for this PCM: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Broken configuration for this PCM: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Access type not available: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Access type not available: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE); err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Sample format not available: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Sample format not available: %s\n", snd_strerror(err));
return false; return false;
} }
dir = 0; dir = 0;
err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &sample_rate, &dir); err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &sample_rate, &dir);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Rate not available: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Rate not available: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_hw_params_set_channels(handle, hwparams, CHANNEL_COUNT); err = snd_pcm_hw_params_set_channels(handle, hwparams, CHANNEL_COUNT);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Channels count not available: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Channels count not available: %s\n", snd_strerror(err));
return false; return false;
} }
periods = BUFFER_SIZE_MAX / FRAME_COUNT_MIN; periods = BUFFER_SIZE_MAX / FRAME_COUNT_MIN;
err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &periods, &dir); err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &periods, &dir);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Cannot set maximum periods per buffer: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Cannot set maximum periods per buffer: %s\n", snd_strerror(err));
return false; return false;
} }
buffer_size_max = BUFFER_SIZE_MAX; buffer_size_max = BUFFER_SIZE_MAX;
err = snd_pcm_hw_params_set_buffer_size_max(handle, hwparams, &buffer_size_max); err = snd_pcm_hw_params_set_buffer_size_max(handle, hwparams, &buffer_size_max);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Cannot set maximum buffer size: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Cannot set maximum buffer size: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_hw_params(handle, hwparams); err = snd_pcm_hw_params(handle, hwparams);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Unable to install hw params: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Unable to install hw params: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size); err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Cannot get buffer size: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Cannot get buffer size: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_hw_params_get_periods_max(hwparams, &periods, &dir); err = snd_pcm_hw_params_get_periods_max(hwparams, &periods, &dir);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Cannot get periods: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Cannot get periods: %s\n", snd_strerror(err));
return false; return false;
} }
//periods is the number of fragments alsa can wait for during one // periods is the number of fragments alsa can wait for during one
//buffer_size // buffer_size
frames_to_deliver = buffer_size / periods; frames_to_deliver = buffer_size / periods;
//limit the minimum size. pulseaudio advertises a minimum of 32 samples. // limit the minimum size. pulseaudio advertises a minimum of 32 samples.
if (frames_to_deliver < FRAME_COUNT_MIN) if (frames_to_deliver < FRAME_COUNT_MIN)
frames_to_deliver = FRAME_COUNT_MIN; frames_to_deliver = FRAME_COUNT_MIN;
//it is probably a bad idea to try to send more than one buffer of data // it is probably a bad idea to try to send more than one buffer of data
if ((unsigned int)frames_to_deliver > buffer_size) if ((unsigned int)frames_to_deliver > buffer_size)
frames_to_deliver = buffer_size; frames_to_deliver = buffer_size;
NOTICE_LOG(AUDIO, "ALSA gave us a %ld sample \"hardware\" buffer with %d periods. Will send %d samples per fragments.\n", buffer_size, periods, frames_to_deliver); NOTICE_LOG(AUDIO, "ALSA gave us a %ld sample \"hardware\" buffer with %d periods. Will send %d "
"samples per fragments.\n",
buffer_size, periods, frames_to_deliver);
snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_alloca(&swparams);
err = snd_pcm_sw_params_current(handle, swparams); err = snd_pcm_sw_params_current(handle, swparams);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "cannot init sw params: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "cannot init sw params: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0U); err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0U);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "cannot set start thresh: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "cannot set start thresh: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_sw_params(handle, swparams); err = snd_pcm_sw_params(handle, swparams);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "cannot set sw params: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "cannot set sw params: %s\n", snd_strerror(err));
return false; return false;
} }
err = snd_pcm_prepare(handle); err = snd_pcm_prepare(handle);
if (err < 0) if (err < 0)
{ {
ERROR_LOG(AUDIO, "Unable to prepare: %s\n", snd_strerror(err)); ERROR_LOG(AUDIO, "Unable to prepare: %s\n", snd_strerror(err));
return false; return false;
} }
NOTICE_LOG(AUDIO, "ALSA successfully initialized.\n"); NOTICE_LOG(AUDIO, "ALSA successfully initialized.\n");
return true; return true;
} }
void AlsaSound::AlsaShutdown() void AlsaSound::AlsaShutdown()
{ {
if (handle != nullptr) if (handle != nullptr)
{ {
snd_pcm_drop(handle); snd_pcm_drop(handle);
snd_pcm_close(handle); snd_pcm_close(handle);
handle = nullptr; handle = nullptr;
} }
} }
+29 -33
View File
@@ -20,47 +20,43 @@ class AlsaSound final : public SoundStream
{ {
#if defined(HAVE_ALSA) && HAVE_ALSA #if defined(HAVE_ALSA) && HAVE_ALSA
public: public:
AlsaSound(); AlsaSound();
bool Start() override; bool Start() override;
void SoundLoop() override; void SoundLoop() override;
void Stop() override; void Stop() override;
void Update() override; void Update() override;
void Clear(bool) override; void Clear(bool) override;
static bool isValid()
{
return true;
}
static bool isValid() { return true; }
private: private:
// maximum number of frames the buffer can hold // maximum number of frames the buffer can hold
static constexpr size_t BUFFER_SIZE_MAX = 8192; static constexpr size_t BUFFER_SIZE_MAX = 8192;
// minimum number of frames to deliver in one transfer // minimum number of frames to deliver in one transfer
static constexpr u32 FRAME_COUNT_MIN = 256; static constexpr u32 FRAME_COUNT_MIN = 256;
// number of channels per frame // number of channels per frame
static constexpr u32 CHANNEL_COUNT = 2; static constexpr u32 CHANNEL_COUNT = 2;
enum class ALSAThreadStatus enum class ALSAThreadStatus
{ {
RUNNING, RUNNING,
PAUSED, PAUSED,
STOPPING, STOPPING,
STOPPED, STOPPED,
}; };
bool AlsaInit(); bool AlsaInit();
void AlsaShutdown(); void AlsaShutdown();
s16 mix_buffer[BUFFER_SIZE_MAX * CHANNEL_COUNT]; s16 mix_buffer[BUFFER_SIZE_MAX * CHANNEL_COUNT];
std::thread thread; std::thread thread;
std::atomic<ALSAThreadStatus> m_thread_status; std::atomic<ALSAThreadStatus> m_thread_status;
std::condition_variable cv; std::condition_variable cv;
std::mutex cv_m; std::mutex cv_m;
snd_pcm_t *handle; snd_pcm_t* handle;
unsigned int frames_to_deliver; unsigned int frames_to_deliver;
#endif #endif
}; };
+175 -176
View File
@@ -2,22 +2,21 @@
// Licensed under GPLv2+ // Licensed under GPLv2+
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "AudioCommon/AlsaSoundStream.h"
#include "AudioCommon/AOSoundStream.h"
#include "AudioCommon/AudioCommon.h" #include "AudioCommon/AudioCommon.h"
#include "AudioCommon/AOSoundStream.h"
#include "AudioCommon/AlsaSoundStream.h"
#include "AudioCommon/CoreAudioSoundStream.h" #include "AudioCommon/CoreAudioSoundStream.h"
#include "AudioCommon/Mixer.h" #include "AudioCommon/Mixer.h"
#include "AudioCommon/NullSoundStream.h" #include "AudioCommon/NullSoundStream.h"
#include "AudioCommon/OpenALStream.h" #include "AudioCommon/OpenALStream.h"
#include "AudioCommon/OpenSLESStream.h" #include "AudioCommon/OpenSLESStream.h"
#include "AudioCommon/PulseAudioStream.h" #include "AudioCommon/PulseAudioStream.h"
#include "AudioCommon/XAudio2_7Stream.h"
#include "AudioCommon/XAudio2Stream.h" #include "AudioCommon/XAudio2Stream.h"
#include "AudioCommon/XAudio2_7Stream.h"
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/Movie.h" #include "Core/Movie.h"
@@ -28,182 +27,182 @@ static bool s_audio_dump_start = false;
namespace AudioCommon namespace AudioCommon
{ {
static const int AUDIO_VOLUME_MIN = 0; static const int AUDIO_VOLUME_MIN = 0;
static const int AUDIO_VOLUME_MAX = 100; static const int AUDIO_VOLUME_MAX = 100;
SoundStream* InitSoundStream() SoundStream* InitSoundStream()
{ {
std::string backend = SConfig::GetInstance().sBackend; std::string backend = SConfig::GetInstance().sBackend;
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) if (backend == BACKEND_OPENAL && OpenALStream::isValid())
g_sound_stream = new OpenALStream(); g_sound_stream = new OpenALStream();
else if (backend == BACKEND_NULLSOUND && NullSound::isValid()) else if (backend == BACKEND_NULLSOUND && NullSound::isValid())
g_sound_stream = new NullSound(); g_sound_stream = new NullSound();
else if (backend == BACKEND_XAUDIO2) else if (backend == BACKEND_XAUDIO2)
{ {
if (XAudio2::isValid()) if (XAudio2::isValid())
g_sound_stream = new XAudio2(); g_sound_stream = new XAudio2();
else if (XAudio2_7::isValid()) else if (XAudio2_7::isValid())
g_sound_stream = new XAudio2_7(); g_sound_stream = new XAudio2_7();
} }
else if (backend == BACKEND_AOSOUND && AOSound::isValid()) else if (backend == BACKEND_AOSOUND && AOSound::isValid())
g_sound_stream = new AOSound(); g_sound_stream = new AOSound();
else if (backend == BACKEND_ALSA && AlsaSound::isValid()) else if (backend == BACKEND_ALSA && AlsaSound::isValid())
g_sound_stream = new AlsaSound(); g_sound_stream = new AlsaSound();
else if (backend == BACKEND_COREAUDIO && CoreAudioSound::isValid()) else if (backend == BACKEND_COREAUDIO && CoreAudioSound::isValid())
g_sound_stream = new CoreAudioSound(); g_sound_stream = new CoreAudioSound();
else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid()) else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid())
g_sound_stream = new PulseAudio(); g_sound_stream = new PulseAudio();
else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid()) else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid())
g_sound_stream = new OpenSLESStream(); g_sound_stream = new OpenSLESStream();
if (!g_sound_stream && NullSound::isValid()) if (!g_sound_stream && NullSound::isValid())
{ {
WARN_LOG(AUDIO, "Could not initialize backend %s, using %s instead.", WARN_LOG(AUDIO, "Could not initialize backend %s, using %s instead.", backend.c_str(),
backend.c_str(), BACKEND_NULLSOUND); BACKEND_NULLSOUND);
g_sound_stream = new NullSound(); g_sound_stream = new NullSound();
} }
if (g_sound_stream) if (g_sound_stream)
{ {
UpdateSoundStream(); UpdateSoundStream();
if (!g_sound_stream->Start()) if (!g_sound_stream->Start())
{ {
ERROR_LOG(AUDIO, "Could not start backend %s, using %s instead", ERROR_LOG(AUDIO, "Could not start backend %s, using %s instead", backend.c_str(),
backend.c_str(), BACKEND_NULLSOUND); BACKEND_NULLSOUND);
delete g_sound_stream; delete g_sound_stream;
g_sound_stream = new NullSound(); g_sound_stream = new NullSound();
g_sound_stream->Start(); g_sound_stream->Start();
} }
if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start) if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start)
StartAudioDump(); StartAudioDump();
return g_sound_stream; return g_sound_stream;
} }
PanicAlertT("Sound backend %s is not valid.", backend.c_str()); PanicAlertT("Sound backend %s is not valid.", backend.c_str());
delete g_sound_stream; delete g_sound_stream;
g_sound_stream = nullptr; g_sound_stream = nullptr;
return nullptr; return nullptr;
} }
void ShutdownSoundStream() void ShutdownSoundStream()
{ {
INFO_LOG(AUDIO, "Shutting down sound stream"); INFO_LOG(AUDIO, "Shutting down sound stream");
if (g_sound_stream) if (g_sound_stream)
{ {
g_sound_stream->Stop(); g_sound_stream->Stop();
if (SConfig::GetInstance().m_DumpAudio && s_audio_dump_start) if (SConfig::GetInstance().m_DumpAudio && s_audio_dump_start)
StopAudioDump(); StopAudioDump();
delete g_sound_stream; delete g_sound_stream;
g_sound_stream = nullptr; g_sound_stream = nullptr;
} }
INFO_LOG(AUDIO, "Done shutting down sound stream"); INFO_LOG(AUDIO, "Done shutting down sound stream");
} }
std::vector<std::string> GetSoundBackends() std::vector<std::string> GetSoundBackends()
{ {
std::vector<std::string> backends; std::vector<std::string> backends;
if (NullSound::isValid()) if (NullSound::isValid())
backends.push_back(BACKEND_NULLSOUND); backends.push_back(BACKEND_NULLSOUND);
if (XAudio2_7::isValid() || XAudio2::isValid()) if (XAudio2_7::isValid() || XAudio2::isValid())
backends.push_back(BACKEND_XAUDIO2); backends.push_back(BACKEND_XAUDIO2);
if (AOSound::isValid()) if (AOSound::isValid())
backends.push_back(BACKEND_AOSOUND); backends.push_back(BACKEND_AOSOUND);
if (AlsaSound::isValid()) if (AlsaSound::isValid())
backends.push_back(BACKEND_ALSA); backends.push_back(BACKEND_ALSA);
if (CoreAudioSound::isValid()) if (CoreAudioSound::isValid())
backends.push_back(BACKEND_COREAUDIO); backends.push_back(BACKEND_COREAUDIO);
if (PulseAudio::isValid()) if (PulseAudio::isValid())
backends.push_back(BACKEND_PULSEAUDIO); backends.push_back(BACKEND_PULSEAUDIO);
if (OpenALStream::isValid()) if (OpenALStream::isValid())
backends.push_back(BACKEND_OPENAL); backends.push_back(BACKEND_OPENAL);
if (OpenSLESStream::isValid()) if (OpenSLESStream::isValid())
backends.push_back(BACKEND_OPENSLES); backends.push_back(BACKEND_OPENSLES);
return backends; return backends;
} }
void UpdateSoundStream() void UpdateSoundStream()
{ {
if (g_sound_stream) if (g_sound_stream)
{ {
int volume = SConfig::GetInstance().m_IsMuted ? 0 : SConfig::GetInstance().m_Volume; int volume = SConfig::GetInstance().m_IsMuted ? 0 : SConfig::GetInstance().m_Volume;
g_sound_stream->SetVolume(volume); g_sound_stream->SetVolume(volume);
} }
} }
void ClearAudioBuffer(bool mute) void ClearAudioBuffer(bool mute)
{ {
if (g_sound_stream) if (g_sound_stream)
g_sound_stream->Clear(mute); g_sound_stream->Clear(mute);
} }
void SendAIBuffer(short *samples, unsigned int num_samples) void SendAIBuffer(short* samples, unsigned int num_samples)
{ {
if (!g_sound_stream) if (!g_sound_stream)
return; return;
if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start) if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start)
StartAudioDump(); StartAudioDump();
else if (!SConfig::GetInstance().m_DumpAudio && s_audio_dump_start) else if (!SConfig::GetInstance().m_DumpAudio && s_audio_dump_start)
StopAudioDump(); StopAudioDump();
CMixer* pMixer = g_sound_stream->GetMixer(); CMixer* pMixer = g_sound_stream->GetMixer();
if (pMixer && samples) if (pMixer && samples)
{ {
pMixer->PushSamples(samples, num_samples); pMixer->PushSamples(samples, num_samples);
} }
g_sound_stream->Update(); g_sound_stream->Update();
} }
void StartAudioDump() void StartAudioDump()
{ {
std::string audio_file_name_dtk = File::GetUserPath(D_DUMPAUDIO_IDX) + "dtkdump.wav"; std::string audio_file_name_dtk = File::GetUserPath(D_DUMPAUDIO_IDX) + "dtkdump.wav";
std::string audio_file_name_dsp = File::GetUserPath(D_DUMPAUDIO_IDX) + "dspdump.wav"; std::string audio_file_name_dsp = File::GetUserPath(D_DUMPAUDIO_IDX) + "dspdump.wav";
File::CreateFullPath(audio_file_name_dtk); File::CreateFullPath(audio_file_name_dtk);
File::CreateFullPath(audio_file_name_dsp); File::CreateFullPath(audio_file_name_dsp);
g_sound_stream->GetMixer()->StartLogDTKAudio(audio_file_name_dtk); g_sound_stream->GetMixer()->StartLogDTKAudio(audio_file_name_dtk);
g_sound_stream->GetMixer()->StartLogDSPAudio(audio_file_name_dsp); g_sound_stream->GetMixer()->StartLogDSPAudio(audio_file_name_dsp);
s_audio_dump_start = true; s_audio_dump_start = true;
} }
void StopAudioDump() void StopAudioDump()
{ {
g_sound_stream->GetMixer()->StopLogDTKAudio(); g_sound_stream->GetMixer()->StopLogDTKAudio();
g_sound_stream->GetMixer()->StopLogDSPAudio(); g_sound_stream->GetMixer()->StopLogDSPAudio();
s_audio_dump_start = false; s_audio_dump_start = false;
} }
void IncreaseVolume(unsigned short offset) void IncreaseVolume(unsigned short offset)
{ {
SConfig::GetInstance().m_IsMuted = false; SConfig::GetInstance().m_IsMuted = false;
int& currentVolume = SConfig::GetInstance().m_Volume; int& currentVolume = SConfig::GetInstance().m_Volume;
currentVolume += offset; currentVolume += offset;
if (currentVolume > AUDIO_VOLUME_MAX) if (currentVolume > AUDIO_VOLUME_MAX)
currentVolume = AUDIO_VOLUME_MAX; currentVolume = AUDIO_VOLUME_MAX;
UpdateSoundStream(); UpdateSoundStream();
} }
void DecreaseVolume(unsigned short offset) void DecreaseVolume(unsigned short offset)
{ {
SConfig::GetInstance().m_IsMuted = false; SConfig::GetInstance().m_IsMuted = false;
int& currentVolume = SConfig::GetInstance().m_Volume; int& currentVolume = SConfig::GetInstance().m_Volume;
currentVolume -= offset; currentVolume -= offset;
if (currentVolume < AUDIO_VOLUME_MIN) if (currentVolume < AUDIO_VOLUME_MIN)
currentVolume = AUDIO_VOLUME_MIN; currentVolume = AUDIO_VOLUME_MIN;
UpdateSoundStream(); UpdateSoundStream();
} }
void ToggleMuteVolume() void ToggleMuteVolume()
{ {
bool& isMuted = SConfig::GetInstance().m_IsMuted; bool& isMuted = SConfig::GetInstance().m_IsMuted;
isMuted = !isMuted; isMuted = !isMuted;
UpdateSoundStream(); UpdateSoundStream();
} }
} }
+12 -13
View File
@@ -7,22 +7,21 @@
#include "AudioCommon/SoundStream.h" #include "AudioCommon/SoundStream.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
class CMixer; class CMixer;
extern SoundStream *g_sound_stream; extern SoundStream* g_sound_stream;
namespace AudioCommon namespace AudioCommon
{ {
SoundStream* InitSoundStream(); SoundStream* InitSoundStream();
void ShutdownSoundStream(); void ShutdownSoundStream();
std::vector<std::string> GetSoundBackends(); std::vector<std::string> GetSoundBackends();
void UpdateSoundStream(); void UpdateSoundStream();
void ClearAudioBuffer(bool mute); void ClearAudioBuffer(bool mute);
void SendAIBuffer(short* samples, unsigned int num_samples); void SendAIBuffer(short* samples, unsigned int num_samples);
void StartAudioDump(); void StartAudioDump();
void StopAudioDump(); void StopAudioDump();
void IncreaseVolume(unsigned short offset); void IncreaseVolume(unsigned short offset);
void DecreaseVolume(unsigned short offset); void DecreaseVolume(unsigned short offset);
void ToggleMuteVolume(); void ToggleMuteVolume();
} }
@@ -7,105 +7,94 @@
#include "AudioCommon/CoreAudioSoundStream.h" #include "AudioCommon/CoreAudioSoundStream.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
OSStatus CoreAudioSound::callback(void *inRefCon, OSStatus CoreAudioSound::callback(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
UInt32 inNumberFrames, AudioBufferList *ioData)
{ {
for (UInt32 i = 0; i < ioData->mNumberBuffers; i++) for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
((CoreAudioSound *)inRefCon)->m_mixer-> ((CoreAudioSound*)inRefCon)
Mix((short *)ioData->mBuffers[i].mData, ->m_mixer->Mix((short*)ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize / 4);
ioData->mBuffers[i].mDataByteSize / 4);
return noErr; return noErr;
} }
bool CoreAudioSound::Start() bool CoreAudioSound::Start()
{ {
OSStatus err; OSStatus err;
AURenderCallbackStruct callback_struct; AURenderCallbackStruct callback_struct;
AudioStreamBasicDescription format; AudioStreamBasicDescription format;
AudioComponentDescription desc; AudioComponentDescription desc;
AudioComponent component; AudioComponent component;
desc.componentType = kAudioUnitType_Output; desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentFlags = 0; desc.componentFlags = 0;
desc.componentFlagsMask = 0; desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentManufacturer = kAudioUnitManufacturer_Apple;
component = AudioComponentFindNext(nullptr, &desc); component = AudioComponentFindNext(nullptr, &desc);
if (component == nullptr) if (component == nullptr)
{ {
ERROR_LOG(AUDIO, "error finding audio component"); ERROR_LOG(AUDIO, "error finding audio component");
return false; return false;
} }
err = AudioComponentInstanceNew(component, &audioUnit); err = AudioComponentInstanceNew(component, &audioUnit);
if (err != noErr) if (err != noErr)
{ {
ERROR_LOG(AUDIO, "error opening audio component"); ERROR_LOG(AUDIO, "error opening audio component");
return false; return false;
} }
FillOutASBDForLPCM(format, m_mixer->GetSampleRate(), FillOutASBDForLPCM(format, m_mixer->GetSampleRate(), 2, 16, 16, false, false, false);
2, 16, 16, false, false, false); err = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0,
err = AudioUnitSetProperty(audioUnit, &format, sizeof(AudioStreamBasicDescription));
kAudioUnitProperty_StreamFormat, if (err != noErr)
kAudioUnitScope_Input, 0, &format, {
sizeof(AudioStreamBasicDescription)); ERROR_LOG(AUDIO, "error setting audio format");
if (err != noErr) return false;
{ }
ERROR_LOG(AUDIO, "error setting audio format");
return false;
}
callback_struct.inputProc = callback; callback_struct.inputProc = callback;
callback_struct.inputProcRefCon = this; callback_struct.inputProcRefCon = this;
err = AudioUnitSetProperty(audioUnit, err = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
kAudioUnitProperty_SetRenderCallback, 0, &callback_struct, sizeof callback_struct);
kAudioUnitScope_Input, 0, &callback_struct, if (err != noErr)
sizeof callback_struct); {
if (err != noErr) ERROR_LOG(AUDIO, "error setting audio callback");
{ return false;
ERROR_LOG(AUDIO, "error setting audio callback"); }
return false;
}
err = AudioUnitSetParameter(audioUnit, err = AudioUnitSetParameter(audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Output, 0,
kHALOutputParam_Volume, m_volume / 100., 0);
kAudioUnitScope_Output, 0, if (err != noErr)
m_volume / 100., 0); ERROR_LOG(AUDIO, "error setting volume");
if (err != noErr)
ERROR_LOG(AUDIO, "error setting volume");
err = AudioUnitInitialize(audioUnit); err = AudioUnitInitialize(audioUnit);
if (err != noErr) if (err != noErr)
{ {
ERROR_LOG(AUDIO, "error initializing audiounit"); ERROR_LOG(AUDIO, "error initializing audiounit");
return false; return false;
} }
err = AudioOutputUnitStart(audioUnit); err = AudioOutputUnitStart(audioUnit);
if (err != noErr) if (err != noErr)
{ {
ERROR_LOG(AUDIO, "error starting audiounit"); ERROR_LOG(AUDIO, "error starting audiounit");
return false; return false;
} }
return true; return true;
} }
void CoreAudioSound::SetVolume(int volume) void CoreAudioSound::SetVolume(int volume)
{ {
OSStatus err; OSStatus err;
m_volume = volume; m_volume = volume;
err = AudioUnitSetParameter(audioUnit, err = AudioUnitSetParameter(audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Output, 0,
kHALOutputParam_Volume, volume / 100., 0);
kAudioUnitScope_Output, 0, if (err != noErr)
volume / 100., 0); ERROR_LOG(AUDIO, "error setting volume");
if (err != noErr)
ERROR_LOG(AUDIO, "error setting volume");
} }
void CoreAudioSound::SoundLoop() void CoreAudioSound::SoundLoop()
@@ -114,19 +103,19 @@ void CoreAudioSound::SoundLoop()
void CoreAudioSound::Stop() void CoreAudioSound::Stop()
{ {
OSStatus err; OSStatus err;
err = AudioOutputUnitStop(audioUnit); err = AudioOutputUnitStop(audioUnit);
if (err != noErr) if (err != noErr)
ERROR_LOG(AUDIO, "error stopping audiounit"); ERROR_LOG(AUDIO, "error stopping audiounit");
err = AudioUnitUninitialize(audioUnit); err = AudioUnitUninitialize(audioUnit);
if (err != noErr) if (err != noErr)
ERROR_LOG(AUDIO, "error uninitializing audiounit"); ERROR_LOG(AUDIO, "error uninitializing audiounit");
err = AudioComponentInstanceDispose(audioUnit); err = AudioComponentInstanceDispose(audioUnit);
if (err != noErr) if (err != noErr)
ERROR_LOG(AUDIO, "error closing audio component"); ERROR_LOG(AUDIO, "error closing audio component");
} }
void CoreAudioSound::Update() void CoreAudioSound::Update()
+11 -17
View File
@@ -14,25 +14,19 @@ class CoreAudioSound final : public SoundStream
{ {
#ifdef __APPLE__ #ifdef __APPLE__
public: public:
bool Start() override; bool Start() override;
void SetVolume(int volume) override; void SetVolume(int volume) override;
void SoundLoop() override; void SoundLoop() override;
void Stop() override; void Stop() override;
void Update() override; void Update() override;
static bool isValid()
{
return true;
}
static bool isValid() { return true; }
private: private:
AudioUnit audioUnit; AudioUnit audioUnit;
int m_volume; int m_volume;
static OSStatus callback(void *inRefCon, static OSStatus callback(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber,
const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList* ioData);
UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *ioData);
#endif #endif
}; };
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -4,5 +4,5 @@
#pragma once #pragma once
void DPL2Decode(float *samples, int numsamples, float *out); void DPL2Decode(float* samples, int numsamples, float* out);
void DPL2Reset(); void DPL2Reset();
+172 -169
View File
@@ -8,18 +8,17 @@
#include "AudioCommon/Mixer.h" #include "AudioCommon/Mixer.h"
#include "Common/CommonFuncs.h" #include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/MathUtil.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__) #if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__)
#include <tmmintrin.h> #include <tmmintrin.h>
#endif #endif
CMixer::CMixer(unsigned int BackendSampleRate) CMixer::CMixer(unsigned int BackendSampleRate) : m_sampleRate(BackendSampleRate)
: m_sampleRate(BackendSampleRate)
{ {
INFO_LOG(AUDIO_INTERFACE, "Mixer is initialized"); INFO_LOG(AUDIO_INTERFACE, "Mixer is initialized");
} }
CMixer::~CMixer() CMixer::~CMixer()
@@ -27,249 +26,253 @@ CMixer::~CMixer()
} }
// Executed from sound stream thread // Executed from sound stream thread
unsigned int CMixer::MixerFifo::Mix(short* samples, unsigned int numSamples, bool consider_framelimit) unsigned int CMixer::MixerFifo::Mix(short* samples, unsigned int numSamples,
bool consider_framelimit)
{ {
unsigned int currentSample = 0; unsigned int currentSample = 0;
// Cache access in non-volatile variable // Cache access in non-volatile variable
// This is the only function changing the read value, so it's safe to // This is the only function changing the read value, so it's safe to
// cache it locally although it's written here. // cache it locally although it's written here.
// The writing pointer will be modified outside, but it will only increase, // The writing pointer will be modified outside, but it will only increase,
// so we will just ignore new written data while interpolating. // so we will just ignore new written data while interpolating.
// Without this cache, the compiler wouldn't be allowed to optimize the // Without this cache, the compiler wouldn't be allowed to optimize the
// interpolation loop. // interpolation loop.
u32 indexR = m_indexR.load(); u32 indexR = m_indexR.load();
u32 indexW = m_indexW.load(); u32 indexW = m_indexW.load();
u32 low_waterwark = m_input_sample_rate * SConfig::GetInstance().iTimingVariance / 1000; u32 low_waterwark = m_input_sample_rate * SConfig::GetInstance().iTimingVariance / 1000;
low_waterwark = std::min(low_waterwark, MAX_SAMPLES / 2); low_waterwark = std::min(low_waterwark, MAX_SAMPLES / 2);
float numLeft = (float)(((indexW - indexR) & INDEX_MASK) / 2); float numLeft = (float)(((indexW - indexR) & INDEX_MASK) / 2);
m_numLeftI = (numLeft + m_numLeftI*(CONTROL_AVG-1)) / CONTROL_AVG; m_numLeftI = (numLeft + m_numLeftI * (CONTROL_AVG - 1)) / CONTROL_AVG;
float offset = (m_numLeftI - low_waterwark) * CONTROL_FACTOR; float offset = (m_numLeftI - low_waterwark) * CONTROL_FACTOR;
if (offset > MAX_FREQ_SHIFT) offset = MAX_FREQ_SHIFT; if (offset > MAX_FREQ_SHIFT)
if (offset < -MAX_FREQ_SHIFT) offset = -MAX_FREQ_SHIFT; offset = MAX_FREQ_SHIFT;
if (offset < -MAX_FREQ_SHIFT)
offset = -MAX_FREQ_SHIFT;
//render numleft sample pairs to samples[] // render numleft sample pairs to samples[]
//advance indexR with sample position // advance indexR with sample position
//remember fractional offset // remember fractional offset
float emulationspeed = SConfig::GetInstance().m_EmulationSpeed; float emulationspeed = SConfig::GetInstance().m_EmulationSpeed;
float aid_sample_rate = m_input_sample_rate + offset; float aid_sample_rate = m_input_sample_rate + offset;
if (consider_framelimit && emulationspeed > 0.0f) if (consider_framelimit && emulationspeed > 0.0f)
{ {
aid_sample_rate = aid_sample_rate * emulationspeed; aid_sample_rate = aid_sample_rate * emulationspeed;
} }
const u32 ratio = (u32)(65536.0f * aid_sample_rate / (float)m_mixer->m_sampleRate); const u32 ratio = (u32)(65536.0f * aid_sample_rate / (float)m_mixer->m_sampleRate);
s32 lvolume = m_LVolume.load(); s32 lvolume = m_LVolume.load();
s32 rvolume = m_RVolume.load(); s32 rvolume = m_RVolume.load();
// TODO: consider a higher-quality resampling algorithm. // TODO: consider a higher-quality resampling algorithm.
for (; currentSample < numSamples * 2 && ((indexW-indexR) & INDEX_MASK) > 2; currentSample += 2) for (; currentSample < numSamples * 2 && ((indexW - indexR) & INDEX_MASK) > 2; currentSample += 2)
{ {
u32 indexR2 = indexR + 2; //next sample u32 indexR2 = indexR + 2; // next sample
s16 l1 = Common::swap16(m_buffer[indexR & INDEX_MASK]); //current s16 l1 = Common::swap16(m_buffer[indexR & INDEX_MASK]); // current
s16 l2 = Common::swap16(m_buffer[indexR2 & INDEX_MASK]); //next s16 l2 = Common::swap16(m_buffer[indexR2 & INDEX_MASK]); // next
int sampleL = ((l1 << 16) + (l2 - l1) * (u16)m_frac) >> 16; int sampleL = ((l1 << 16) + (l2 - l1) * (u16)m_frac) >> 16;
sampleL = (sampleL * lvolume) >> 8; sampleL = (sampleL * lvolume) >> 8;
sampleL += samples[currentSample + 1]; sampleL += samples[currentSample + 1];
samples[currentSample + 1] = MathUtil::Clamp(sampleL, -32767, 32767); samples[currentSample + 1] = MathUtil::Clamp(sampleL, -32767, 32767);
s16 r1 = Common::swap16(m_buffer[(indexR + 1) & INDEX_MASK]); //current s16 r1 = Common::swap16(m_buffer[(indexR + 1) & INDEX_MASK]); // current
s16 r2 = Common::swap16(m_buffer[(indexR2 + 1) & INDEX_MASK]); //next s16 r2 = Common::swap16(m_buffer[(indexR2 + 1) & INDEX_MASK]); // next
int sampleR = ((r1 << 16) + (r2 - r1) * (u16)m_frac) >> 16; int sampleR = ((r1 << 16) + (r2 - r1) * (u16)m_frac) >> 16;
sampleR = (sampleR * rvolume) >> 8; sampleR = (sampleR * rvolume) >> 8;
sampleR += samples[currentSample]; sampleR += samples[currentSample];
samples[currentSample] = MathUtil::Clamp(sampleR, -32767, 32767); samples[currentSample] = MathUtil::Clamp(sampleR, -32767, 32767);
m_frac += ratio; m_frac += ratio;
indexR += 2 * (u16)(m_frac >> 16); indexR += 2 * (u16)(m_frac >> 16);
m_frac &= 0xffff; m_frac &= 0xffff;
} }
// Padding // Padding
short s[2]; short s[2];
s[0] = Common::swap16(m_buffer[(indexR - 1) & INDEX_MASK]); s[0] = Common::swap16(m_buffer[(indexR - 1) & INDEX_MASK]);
s[1] = Common::swap16(m_buffer[(indexR - 2) & INDEX_MASK]); s[1] = Common::swap16(m_buffer[(indexR - 2) & INDEX_MASK]);
s[0] = (s[0] * rvolume) >> 8; s[0] = (s[0] * rvolume) >> 8;
s[1] = (s[1] * lvolume) >> 8; s[1] = (s[1] * lvolume) >> 8;
for (; currentSample < numSamples * 2; currentSample += 2) for (; currentSample < numSamples * 2; currentSample += 2)
{ {
int sampleR = MathUtil::Clamp(s[0] + samples[currentSample + 0], -32767, 32767); int sampleR = MathUtil::Clamp(s[0] + samples[currentSample + 0], -32767, 32767);
int sampleL = MathUtil::Clamp(s[1] + samples[currentSample + 1], -32767, 32767); int sampleL = MathUtil::Clamp(s[1] + samples[currentSample + 1], -32767, 32767);
samples[currentSample + 0] = sampleR; samples[currentSample + 0] = sampleR;
samples[currentSample + 1] = sampleL; samples[currentSample + 1] = sampleL;
} }
// Flush cached variable // Flush cached variable
m_indexR.store(indexR); m_indexR.store(indexR);
return numSamples; return numSamples;
} }
unsigned int CMixer::Mix(short* samples, unsigned int num_samples, bool consider_framelimit) unsigned int CMixer::Mix(short* samples, unsigned int num_samples, bool consider_framelimit)
{ {
if (!samples) if (!samples)
return 0; return 0;
memset(samples, 0, num_samples * 2 * sizeof(short)); memset(samples, 0, num_samples * 2 * sizeof(short));
m_dma_mixer.Mix(samples, num_samples, consider_framelimit); m_dma_mixer.Mix(samples, num_samples, consider_framelimit);
m_streaming_mixer.Mix(samples, num_samples, consider_framelimit); m_streaming_mixer.Mix(samples, num_samples, consider_framelimit);
m_wiimote_speaker_mixer.Mix(samples, num_samples, consider_framelimit); m_wiimote_speaker_mixer.Mix(samples, num_samples, consider_framelimit);
return num_samples; return num_samples;
} }
void CMixer::MixerFifo::PushSamples(const short *samples, unsigned int num_samples) void CMixer::MixerFifo::PushSamples(const short* samples, unsigned int num_samples)
{ {
// Cache access in non-volatile variable // Cache access in non-volatile variable
// indexR isn't allowed to cache in the audio throttling loop as it // indexR isn't allowed to cache in the audio throttling loop as it
// needs to get updates to not deadlock. // needs to get updates to not deadlock.
u32 indexW = m_indexW.load(); u32 indexW = m_indexW.load();
// Check if we have enough free space // Check if we have enough free space
// indexW == m_indexR results in empty buffer, so indexR must always be smaller than indexW // indexW == m_indexR results in empty buffer, so indexR must always be smaller than indexW
if (num_samples * 2 + ((indexW - m_indexR.load()) & INDEX_MASK) >= MAX_SAMPLES * 2) if (num_samples * 2 + ((indexW - m_indexR.load()) & INDEX_MASK) >= MAX_SAMPLES * 2)
return; return;
// AyuanX: Actual re-sampling work has been moved to sound thread // AyuanX: Actual re-sampling work has been moved to sound thread
// to alleviate the workload on main thread // to alleviate the workload on main thread
// and we simply store raw data here to make fast mem copy // and we simply store raw data here to make fast mem copy
int over_bytes = num_samples * 4 - (MAX_SAMPLES * 2 - (indexW & INDEX_MASK)) * sizeof(short); int over_bytes = num_samples * 4 - (MAX_SAMPLES * 2 - (indexW & INDEX_MASK)) * sizeof(short);
if (over_bytes > 0) if (over_bytes > 0)
{ {
memcpy(&m_buffer[indexW & INDEX_MASK], samples, num_samples * 4 - over_bytes); memcpy(&m_buffer[indexW & INDEX_MASK], samples, num_samples * 4 - over_bytes);
memcpy(&m_buffer[0], samples + (num_samples * 4 - over_bytes) / sizeof(short), over_bytes); memcpy(&m_buffer[0], samples + (num_samples * 4 - over_bytes) / sizeof(short), over_bytes);
} }
else else
{ {
memcpy(&m_buffer[indexW & INDEX_MASK], samples, num_samples * 4); memcpy(&m_buffer[indexW & INDEX_MASK], samples, num_samples * 4);
} }
m_indexW.fetch_add(num_samples * 2); m_indexW.fetch_add(num_samples * 2);
} }
void CMixer::PushSamples(const short *samples, unsigned int num_samples) void CMixer::PushSamples(const short* samples, unsigned int num_samples)
{ {
m_dma_mixer.PushSamples(samples, num_samples); m_dma_mixer.PushSamples(samples, num_samples);
if (m_log_dsp_audio) if (m_log_dsp_audio)
m_wave_writer_dsp.AddStereoSamplesBE(samples, num_samples); m_wave_writer_dsp.AddStereoSamplesBE(samples, num_samples);
} }
void CMixer::PushStreamingSamples(const short *samples, unsigned int num_samples) void CMixer::PushStreamingSamples(const short* samples, unsigned int num_samples)
{ {
m_streaming_mixer.PushSamples(samples, num_samples); m_streaming_mixer.PushSamples(samples, num_samples);
if (m_log_dtk_audio) if (m_log_dtk_audio)
m_wave_writer_dtk.AddStereoSamplesBE(samples, num_samples); m_wave_writer_dtk.AddStereoSamplesBE(samples, num_samples);
} }
void CMixer::PushWiimoteSpeakerSamples(const short *samples, unsigned int num_samples, unsigned int sample_rate) void CMixer::PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples,
unsigned int sample_rate)
{ {
short samples_stereo[MAX_SAMPLES * 2]; short samples_stereo[MAX_SAMPLES * 2];
if (num_samples < MAX_SAMPLES) if (num_samples < MAX_SAMPLES)
{ {
m_wiimote_speaker_mixer.SetInputSampleRate(sample_rate); m_wiimote_speaker_mixer.SetInputSampleRate(sample_rate);
for (unsigned int i = 0; i < num_samples; ++i) for (unsigned int i = 0; i < num_samples; ++i)
{ {
samples_stereo[i * 2] = Common::swap16(samples[i]); samples_stereo[i * 2] = Common::swap16(samples[i]);
samples_stereo[i * 2 + 1] = Common::swap16(samples[i]); samples_stereo[i * 2 + 1] = Common::swap16(samples[i]);
} }
m_wiimote_speaker_mixer.PushSamples(samples_stereo, num_samples); m_wiimote_speaker_mixer.PushSamples(samples_stereo, num_samples);
} }
} }
void CMixer::SetDMAInputSampleRate(unsigned int rate) void CMixer::SetDMAInputSampleRate(unsigned int rate)
{ {
m_dma_mixer.SetInputSampleRate(rate); m_dma_mixer.SetInputSampleRate(rate);
} }
void CMixer::SetStreamInputSampleRate(unsigned int rate) void CMixer::SetStreamInputSampleRate(unsigned int rate)
{ {
m_streaming_mixer.SetInputSampleRate(rate); m_streaming_mixer.SetInputSampleRate(rate);
} }
void CMixer::SetStreamingVolume(unsigned int lvolume, unsigned int rvolume) void CMixer::SetStreamingVolume(unsigned int lvolume, unsigned int rvolume)
{ {
m_streaming_mixer.SetVolume(lvolume, rvolume); m_streaming_mixer.SetVolume(lvolume, rvolume);
} }
void CMixer::SetWiimoteSpeakerVolume(unsigned int lvolume, unsigned int rvolume) void CMixer::SetWiimoteSpeakerVolume(unsigned int lvolume, unsigned int rvolume)
{ {
m_wiimote_speaker_mixer.SetVolume(lvolume, rvolume); m_wiimote_speaker_mixer.SetVolume(lvolume, rvolume);
} }
void CMixer::StartLogDTKAudio(const std::string& filename) void CMixer::StartLogDTKAudio(const std::string& filename)
{ {
if (!m_log_dtk_audio) if (!m_log_dtk_audio)
{ {
m_log_dtk_audio = true; m_log_dtk_audio = true;
m_wave_writer_dtk.Start(filename, 48000); m_wave_writer_dtk.Start(filename, 48000);
m_wave_writer_dtk.SetSkipSilence(false); m_wave_writer_dtk.SetSkipSilence(false);
NOTICE_LOG(AUDIO, "Starting DTK Audio logging"); NOTICE_LOG(AUDIO, "Starting DTK Audio logging");
} }
else else
{ {
WARN_LOG(AUDIO, "DTK Audio logging has already been started"); WARN_LOG(AUDIO, "DTK Audio logging has already been started");
} }
} }
void CMixer::StopLogDTKAudio() void CMixer::StopLogDTKAudio()
{ {
if (m_log_dtk_audio) if (m_log_dtk_audio)
{ {
m_log_dtk_audio = false; m_log_dtk_audio = false;
m_wave_writer_dtk.Stop(); m_wave_writer_dtk.Stop();
NOTICE_LOG(AUDIO, "Stopping DTK Audio logging"); NOTICE_LOG(AUDIO, "Stopping DTK Audio logging");
} }
else else
{ {
WARN_LOG(AUDIO, "DTK Audio logging has already been stopped"); WARN_LOG(AUDIO, "DTK Audio logging has already been stopped");
} }
} }
void CMixer::StartLogDSPAudio(const std::string& filename) void CMixer::StartLogDSPAudio(const std::string& filename)
{ {
if (!m_log_dsp_audio) if (!m_log_dsp_audio)
{ {
m_log_dsp_audio = true; m_log_dsp_audio = true;
m_wave_writer_dsp.Start(filename, 32000); m_wave_writer_dsp.Start(filename, 32000);
m_wave_writer_dsp.SetSkipSilence(false); m_wave_writer_dsp.SetSkipSilence(false);
NOTICE_LOG(AUDIO, "Starting DSP Audio logging"); NOTICE_LOG(AUDIO, "Starting DSP Audio logging");
} }
else else
{ {
WARN_LOG(AUDIO, "DSP Audio logging has already been started"); WARN_LOG(AUDIO, "DSP Audio logging has already been started");
} }
} }
void CMixer::StopLogDSPAudio() void CMixer::StopLogDSPAudio()
{ {
if (m_log_dsp_audio) if (m_log_dsp_audio)
{ {
m_log_dsp_audio = false; m_log_dsp_audio = false;
m_wave_writer_dsp.Stop(); m_wave_writer_dsp.Stop();
NOTICE_LOG(AUDIO, "Stopping DSP Audio logging"); NOTICE_LOG(AUDIO, "Stopping DSP Audio logging");
} }
else else
{ {
WARN_LOG(AUDIO, "DSP Audio logging has already been stopped"); WARN_LOG(AUDIO, "DSP Audio logging has already been stopped");
} }
} }
void CMixer::MixerFifo::SetInputSampleRate(unsigned int rate) void CMixer::MixerFifo::SetInputSampleRate(unsigned int rate)
{ {
m_input_sample_rate = rate; m_input_sample_rate = rate;
} }
void CMixer::MixerFifo::SetVolume(unsigned int lvolume, unsigned int rvolume) void CMixer::MixerFifo::SetVolume(unsigned int lvolume, unsigned int rvolume)
{ {
m_LVolume.store(lvolume + (lvolume >> 7)); m_LVolume.store(lvolume + (lvolume >> 7));
m_RVolume.store(rvolume + (rvolume >> 7)); m_RVolume.store(rvolume + (rvolume >> 7));
} }
+59 -60
View File
@@ -13,74 +13,73 @@
class CMixer final class CMixer final
{ {
public: public:
explicit CMixer(unsigned int BackendSampleRate); explicit CMixer(unsigned int BackendSampleRate);
~CMixer(); ~CMixer();
// Called from audio threads // Called from audio threads
unsigned int Mix(short* samples, unsigned int numSamples, bool consider_framelimit = true); unsigned int Mix(short* samples, unsigned int numSamples, bool consider_framelimit = true);
// Called from main thread // Called from main thread
void PushSamples(const short* samples, unsigned int num_samples); void PushSamples(const short* samples, unsigned int num_samples);
void PushStreamingSamples(const short* samples, unsigned int num_samples); void PushStreamingSamples(const short* samples, unsigned int num_samples);
void PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples, unsigned int sample_rate); void PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples,
unsigned int GetSampleRate() const { return m_sampleRate; } unsigned int sample_rate);
unsigned int GetSampleRate() const { return m_sampleRate; }
void SetDMAInputSampleRate(unsigned int rate);
void SetStreamInputSampleRate(unsigned int rate);
void SetStreamingVolume(unsigned int lvolume, unsigned int rvolume);
void SetWiimoteSpeakerVolume(unsigned int lvolume, unsigned int rvolume);
void SetDMAInputSampleRate(unsigned int rate); void StartLogDTKAudio(const std::string& filename);
void SetStreamInputSampleRate(unsigned int rate); void StopLogDTKAudio();
void SetStreamingVolume(unsigned int lvolume, unsigned int rvolume);
void SetWiimoteSpeakerVolume(unsigned int lvolume, unsigned int rvolume);
void StartLogDTKAudio(const std::string& filename); void StartLogDSPAudio(const std::string& filename);
void StopLogDTKAudio(); void StopLogDSPAudio();
void StartLogDSPAudio(const std::string& filename);
void StopLogDSPAudio();
float GetCurrentSpeed() const { return m_speed.load(); }
void UpdateSpeed(float val) { m_speed.store(val); }
float GetCurrentSpeed() const { return m_speed.load(); }
void UpdateSpeed(float val) { m_speed.store(val); }
private: private:
static constexpr u32 MAX_SAMPLES = 1024 * 4; // 128 ms static constexpr u32 MAX_SAMPLES = 1024 * 4; // 128 ms
static constexpr u32 INDEX_MASK = MAX_SAMPLES * 2 - 1; static constexpr u32 INDEX_MASK = MAX_SAMPLES * 2 - 1;
static constexpr int MAX_FREQ_SHIFT = 200; // Per 32000 Hz static constexpr int MAX_FREQ_SHIFT = 200; // Per 32000 Hz
static constexpr float CONTROL_FACTOR = 0.2f; static constexpr float CONTROL_FACTOR = 0.2f;
static constexpr u32 CONTROL_AVG = 32; // In freq_shift per FIFO size offset static constexpr u32 CONTROL_AVG = 32; // In freq_shift per FIFO size offset
class MixerFifo final class MixerFifo final
{ {
public: public:
MixerFifo(CMixer* mixer, unsigned sample_rate) MixerFifo(CMixer* mixer, unsigned sample_rate)
: m_mixer(mixer) : m_mixer(mixer), m_input_sample_rate(sample_rate)
, m_input_sample_rate(sample_rate) {
{ }
} void PushSamples(const short* samples, unsigned int num_samples);
void PushSamples(const short* samples, unsigned int num_samples); unsigned int Mix(short* samples, unsigned int numSamples, bool consider_framelimit = true);
unsigned int Mix(short* samples, unsigned int numSamples, bool consider_framelimit = true); void SetInputSampleRate(unsigned int rate);
void SetInputSampleRate(unsigned int rate); void SetVolume(unsigned int lvolume, unsigned int rvolume);
void SetVolume(unsigned int lvolume, unsigned int rvolume);
private:
CMixer* m_mixer;
unsigned m_input_sample_rate;
std::array<short, MAX_SAMPLES * 2> m_buffer{};
std::atomic<u32> m_indexW{0};
std::atomic<u32> m_indexR{0};
// Volume ranges from 0-256
std::atomic<s32> m_LVolume{256};
std::atomic<s32> m_RVolume{256};
float m_numLeftI = 0.0f;
u32 m_frac = 0;
};
MixerFifo m_dma_mixer{this, 32000};
MixerFifo m_streaming_mixer{this, 48000};
MixerFifo m_wiimote_speaker_mixer{this, 3000};
unsigned int m_sampleRate;
WaveFileWriter m_wave_writer_dtk; private:
WaveFileWriter m_wave_writer_dsp; CMixer* m_mixer;
unsigned m_input_sample_rate;
std::array<short, MAX_SAMPLES * 2> m_buffer{};
std::atomic<u32> m_indexW{0};
std::atomic<u32> m_indexR{0};
// Volume ranges from 0-256
std::atomic<s32> m_LVolume{256};
std::atomic<s32> m_RVolume{256};
float m_numLeftI = 0.0f;
u32 m_frac = 0;
};
MixerFifo m_dma_mixer{this, 32000};
MixerFifo m_streaming_mixer{this, 48000};
MixerFifo m_wiimote_speaker_mixer{this, 3000};
unsigned int m_sampleRate;
bool m_log_dtk_audio = false; WaveFileWriter m_wave_writer_dtk;
bool m_log_dsp_audio = false; WaveFileWriter m_wave_writer_dsp;
// Current rate of emulation (1.0 = 100% speed) bool m_log_dtk_audio = false;
std::atomic<float> m_speed{0.0f}; bool m_log_dsp_audio = false;
// Current rate of emulation (1.0 = 100% speed)
std::atomic<float> m_speed{0.0f};
}; };
+12 -9
View File
@@ -13,7 +13,7 @@ void NullSound::SoundLoop()
bool NullSound::Start() bool NullSound::Start()
{ {
return true; return true;
} }
void NullSound::SetVolume(int volume) void NullSound::SetVolume(int volume)
@@ -22,19 +22,22 @@ void NullSound::SetVolume(int volume)
void NullSound::Update() void NullSound::Update()
{ {
// num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD. // num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD.
constexpr u32 stereo_16_bit_size = 4; constexpr u32 stereo_16_bit_size = 4;
constexpr u32 dma_length = 32; constexpr u32 dma_length = 32;
const u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length); const u64 audio_dma_period =
const u64 ais_samples_per_second = 48000 * stereo_16_bit_size; SystemTimers::GetTicksPerSecond() /
const u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond(); (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length);
const u64 ais_samples_per_second = 48000 * stereo_16_bit_size;
const u64 num_samples_to_render =
(audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond();
m_mixer->Mix(m_realtime_buffer.data(), (unsigned int)num_samples_to_render); m_mixer->Mix(m_realtime_buffer.data(), (unsigned int)num_samples_to_render);
} }
void NullSound::Clear(bool mute) void NullSound::Clear(bool mute)
{ {
m_muted = mute; m_muted = mute;
} }
void NullSound::Stop() void NullSound::Stop()
+10 -11
View File
@@ -10,18 +10,17 @@
class NullSound final : public SoundStream class NullSound final : public SoundStream
{ {
public: public:
bool Start() override; bool Start() override;
void SoundLoop() override; void SoundLoop() override;
void SetVolume(int volume) override; void SetVolume(int volume) override;
void Stop() override; void Stop() override;
void Clear(bool mute) override; void Clear(bool mute) override;
void Update() override; void Update() override;
static bool isValid() { return true; }
static bool isValid() { return true; }
private: private:
static constexpr size_t BUFFER_SIZE = 48000 * 4 / 32; static constexpr size_t BUFFER_SIZE = 48000 * 4 / 32;
// Playback position // Playback position
std::array<short, BUFFER_SIZE / sizeof(short)> m_realtime_buffer; std::array<short, BUFFER_SIZE / sizeof(short)> m_realtime_buffer;
}; };
File diff suppressed because it is too large Load Diff
+30 -34
View File
@@ -32,56 +32,52 @@
#define BOOL SoundTouch_BOOL #define BOOL SoundTouch_BOOL
#endif #endif
#include <soundtouch/SoundTouch.h>
#include <soundtouch/STTypes.h> #include <soundtouch/STTypes.h>
#include <soundtouch/SoundTouch.h>
#ifdef __APPLE__ #ifdef __APPLE__
#undef BOOL #undef BOOL
#endif #endif
// 16 bit Stereo // 16 bit Stereo
#define SFX_MAX_SOURCE 1 #define SFX_MAX_SOURCE 1
#define OAL_MAX_BUFFERS 32 #define OAL_MAX_BUFFERS 32
#define OAL_MAX_SAMPLES 256 #define OAL_MAX_SAMPLES 256
#define STEREO_CHANNELS 2 #define STEREO_CHANNELS 2
#define SURROUND_CHANNELS 6 // number of channels in surround mode #define SURROUND_CHANNELS 6 // number of channels in surround mode
#define SIZE_SHORT 2 #define SIZE_SHORT 2
#define SIZE_FLOAT 4 // size of a float in bytes #define SIZE_FLOAT 4 // size of a float in bytes
#define FRAME_STEREO_SHORT STEREO_CHANNELS * SIZE_SHORT #define FRAME_STEREO_SHORT STEREO_CHANNELS* SIZE_SHORT
#define FRAME_STEREO_FLOAT STEREO_CHANNELS * SIZE_FLOAT #define FRAME_STEREO_FLOAT STEREO_CHANNELS* SIZE_FLOAT
#define FRAME_SURROUND_FLOAT SURROUND_CHANNELS * SIZE_FLOAT #define FRAME_SURROUND_FLOAT SURROUND_CHANNELS* SIZE_FLOAT
#define FRAME_SURROUND_SHORT SURROUND_CHANNELS * SIZE_SHORT #define FRAME_SURROUND_SHORT SURROUND_CHANNELS* SIZE_SHORT
#endif #endif
class OpenALStream final : public SoundStream class OpenALStream final : public SoundStream
{ {
#if defined HAVE_OPENAL && HAVE_OPENAL #if defined HAVE_OPENAL && HAVE_OPENAL
public: public:
OpenALStream() : uiSource(0) OpenALStream() : uiSource(0) {}
{ bool Start() override;
} void SoundLoop() override;
void SetVolume(int volume) override;
bool Start() override; void Stop() override;
void SoundLoop() override; void Clear(bool mute) override;
void SetVolume(int volume) override; void Update() override;
void Stop() override;
void Clear(bool mute) override;
void Update() override;
static bool isValid() { return true; }
static bool isValid() { return true; }
private: private:
std::thread thread; std::thread thread;
std::atomic<bool> m_run_thread; std::atomic<bool> m_run_thread;
Common::Event soundSyncEvent; Common::Event soundSyncEvent;
short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS]; short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS];
soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
ALuint uiBuffers[OAL_MAX_BUFFERS]; ALuint uiBuffers[OAL_MAX_BUFFERS];
ALuint uiSource; ALuint uiSource;
ALfloat fVolume; ALfloat fVolume;
u8 numBuffers; u8 numBuffers;
#endif // HAVE_OPENAL #endif // HAVE_OPENAL
}; };
+82 -81
View File
@@ -24,7 +24,7 @@ static SLPlayItf bqPlayerPlay;
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
static SLMuteSoloItf bqPlayerMuteSolo; static SLMuteSoloItf bqPlayerMuteSolo;
static SLVolumeItf bqPlayerVolume; static SLVolumeItf bqPlayerVolume;
static CMixer *g_mixer; static CMixer* g_mixer;
#define BUFFER_SIZE 512 #define BUFFER_SIZE 512
#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2) #define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2)
@@ -32,106 +32,107 @@ static CMixer *g_mixer;
static short buffer[2][BUFFER_SIZE]; static short buffer[2][BUFFER_SIZE];
static int curBuffer = 0; static int curBuffer = 0;
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
{ {
assert(bq == bqPlayerBufferQueue); assert(bq == bqPlayerBufferQueue);
assert(nullptr == context); assert(nullptr == context);
// Render to the fresh buffer // Render to the fresh buffer
g_mixer->Mix(reinterpret_cast<short *>(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES); g_mixer->Mix(reinterpret_cast<short*>(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES);
SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[0])); SLresult result =
curBuffer ^= 1; // Switch buffer (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[0]));
curBuffer ^= 1; // Switch buffer
// Comment from sample code: // Comment from sample code:
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
// which for this code example would indicate a programming error // which for this code example would indicate a programming error
_assert_msg_(AUDIO, SL_RESULT_SUCCESS == result, "Couldn't enqueue audio stream."); _assert_msg_(AUDIO, SL_RESULT_SUCCESS == result, "Couldn't enqueue audio stream.");
} }
bool OpenSLESStream::Start() bool OpenSLESStream::Start()
{ {
SLresult result; SLresult result;
// create engine // create engine
result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr); result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm = { SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,
SL_DATAFORMAT_PCM, 2,
2, m_mixer->GetSampleRate() * 1000,
m_mixer->GetSampleRate() * 1000, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN};
SL_BYTEORDER_LITTLEENDIAN
};
SLDataSource audioSrc = {&loc_bufq, &format_pcm}; SLDataSource audioSrc = {&loc_bufq, &format_pcm};
// configure audio sink // configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&loc_outmix, nullptr}; SLDataSink audioSnk = {&loc_outmix, nullptr};
// create audio player // create audio player
const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); result =
assert(SL_RESULT_SUCCESS == result); (*engineEngine)
->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
assert(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, result =
&bqPlayerBufferQueue); (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr); result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
assert(SL_RESULT_SUCCESS == result); assert(SL_RESULT_SUCCESS == result);
// Render and enqueue a first buffer. // Render and enqueue a first buffer.
curBuffer ^= 1; curBuffer ^= 1;
g_mixer = m_mixer.get(); g_mixer = m_mixer.get();
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[0], sizeof(buffer[0])); result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[0], sizeof(buffer[0]));
if (SL_RESULT_SUCCESS != result) if (SL_RESULT_SUCCESS != result)
return false; return false;
return true; return true;
} }
void OpenSLESStream::Stop() void OpenSLESStream::Stop()
{ {
if (bqPlayerObject != nullptr) if (bqPlayerObject != nullptr)
{ {
(*bqPlayerObject)->Destroy(bqPlayerObject); (*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = nullptr; bqPlayerObject = nullptr;
bqPlayerPlay = nullptr; bqPlayerPlay = nullptr;
bqPlayerBufferQueue = nullptr; bqPlayerBufferQueue = nullptr;
bqPlayerMuteSolo = nullptr; bqPlayerMuteSolo = nullptr;
bqPlayerVolume = nullptr; bqPlayerVolume = nullptr;
} }
if (outputMixObject != nullptr) if (outputMixObject != nullptr)
{ {
(*outputMixObject)->Destroy(outputMixObject); (*outputMixObject)->Destroy(outputMixObject);
outputMixObject = nullptr; outputMixObject = nullptr;
} }
if (engineObject != nullptr) if (engineObject != nullptr)
{ {
(*engineObject)->Destroy(engineObject); (*engineObject)->Destroy(engineObject);
engineObject = nullptr; engineObject = nullptr;
engineEngine = nullptr; engineEngine = nullptr;
} }
} }
#endif #endif

Some files were not shown because too many files have changed in this diff Show More