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