mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
Implement AudioIn HQ open and close with paced silent input
This commit is contained in:
+120
-49
@@ -89,9 +89,10 @@ public:
|
|||||||
uint32_t AudioOutOutputs(OutputParam* params, uint32_t num, bool blocking = true);
|
uint32_t AudioOutOutputs(OutputParam* params, uint32_t num, bool blocking = true);
|
||||||
bool AudioOutGetStatus(Id handle, int* type, int* channels_num);
|
bool AudioOutGetStatus(Id handle, int* type, int* channels_num);
|
||||||
|
|
||||||
Id AudioInOpen(uint32_t type, uint32_t samples_num, uint32_t freq, Format format);
|
Id AudioInOpen(uint32_t samples_num, uint32_t freq, Format format, bool asynchronous);
|
||||||
|
int AudioInClose(Id handle);
|
||||||
bool AudioInValid(Id handle);
|
bool AudioInValid(Id handle);
|
||||||
uint32_t AudioInInput(Id handle, void* dest);
|
int AudioInInput(Id handle, void* dest);
|
||||||
|
|
||||||
static constexpr int OUT_PORTS_MAX = 32;
|
static constexpr int OUT_PORTS_MAX = 32;
|
||||||
static constexpr int IN_PORTS_MAX = 8;
|
static constexpr int IN_PORTS_MAX = 8;
|
||||||
@@ -113,13 +114,16 @@ private:
|
|||||||
|
|
||||||
struct PortIn {
|
struct PortIn {
|
||||||
bool used = false;
|
bool used = false;
|
||||||
uint32_t type = 0;
|
bool busy = false;
|
||||||
|
bool asynchronous = false;
|
||||||
uint32_t samples_num = 0;
|
uint32_t samples_num = 0;
|
||||||
uint32_t freq = 0;
|
uint32_t freq = 0;
|
||||||
Format format = Format::Unknown;
|
uint32_t bytes_per_frame = 0;
|
||||||
uint64_t last_input_time = 0;
|
uint64_t last_input_time = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PortIn* GetAudioInPort(Id handle); // Caller holds m_mutex.
|
||||||
|
|
||||||
Common::Mutex m_mutex;
|
Common::Mutex m_mutex;
|
||||||
PortOut m_out_ports[OUT_PORTS_MAX];
|
PortOut m_out_ports[OUT_PORTS_MAX];
|
||||||
PortIn m_in_ports[IN_PORTS_MAX];
|
PortIn m_in_ports[IN_PORTS_MAX];
|
||||||
@@ -566,23 +570,21 @@ uint32_t Audio::AudioOutOutputs(OutputParam* params, uint32_t num, bool blocking
|
|||||||
return first_port.samples_num;
|
return first_port.samples_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
Audio::Id Audio::AudioInOpen(uint32_t type, uint32_t samples_num, uint32_t freq, Format format) {
|
Audio::Id Audio::AudioInOpen(uint32_t samples_num, uint32_t freq, Format format, bool asynchronous) {
|
||||||
Common::LockGuard lock(m_mutex);
|
Common::LockGuard lock(m_mutex);
|
||||||
|
|
||||||
for (int id = 0; id < IN_PORTS_MAX; id++) {
|
for (int id = 0; id < IN_PORTS_MAX; id++) {
|
||||||
if (!m_in_ports[id].used) {
|
if (!m_in_ports[id].used) {
|
||||||
auto& port = m_in_ports[id];
|
auto& port = m_in_ports[id];
|
||||||
|
|
||||||
port.used = true;
|
port = {};
|
||||||
port.type = type;
|
port.used = true;
|
||||||
port.samples_num = samples_num;
|
port.asynchronous = asynchronous;
|
||||||
port.freq = freq;
|
port.samples_num = samples_num;
|
||||||
port.format = format;
|
port.freq = freq;
|
||||||
|
port.bytes_per_frame = BytesPerSample(format);
|
||||||
switch (format) {
|
if (format == Format::Signed16bitStereo || format == Format::FloatStereo) {
|
||||||
case Format::Signed16bitMono:
|
port.bytes_per_frame *= 2;
|
||||||
case Format::Signed16bitStereo: break;
|
|
||||||
default: EXIT("unknown format");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Id::Create(id);
|
return Id::Create(id);
|
||||||
@@ -592,31 +594,72 @@ Audio::Id Audio::AudioInOpen(uint32_t type, uint32_t samples_num, uint32_t freq,
|
|||||||
return Id::Invalid();
|
return Id::Invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Audio::AudioInValid(Id handle) {
|
Audio::PortIn* Audio::GetAudioInPort(Id handle) {
|
||||||
Common::LockGuard lock(m_mutex);
|
if (handle.GetId() < 0 || handle.GetId() >= IN_PORTS_MAX ||
|
||||||
|
!m_in_ports[handle.GetId()].used) {
|
||||||
return (handle.GetId() >= 0 && handle.GetId() < IN_PORTS_MAX &&
|
return nullptr;
|
||||||
m_in_ports[handle.GetId()].used);
|
}
|
||||||
|
return &m_in_ports[handle.GetId()];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Audio::AudioInInput(Id handle, void* dest) {
|
int Audio::AudioInClose(Id handle) {
|
||||||
EXIT_NOT_IMPLEMENTED(!AudioInValid(handle));
|
Common::LockGuard lock(m_mutex);
|
||||||
EXIT_NOT_IMPLEMENTED(dest == nullptr);
|
auto* port = GetAudioInPort(handle);
|
||||||
|
if (port == nullptr) {
|
||||||
|
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if (port->busy) {
|
||||||
|
return AUDIO_IN_ERROR_BUSY;
|
||||||
|
}
|
||||||
|
*port = {};
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& port = m_in_ports[handle.GetId()];
|
bool Audio::AudioInValid(Id handle) {
|
||||||
|
Common::LockGuard lock(m_mutex);
|
||||||
|
return GetAudioInPort(handle) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t block_time = (1000000 * port.samples_num) / port.freq;
|
int Audio::AudioInInput(Id handle, void* dest) {
|
||||||
uint64_t current_time = LibKernel::KernelGetProcessTime();
|
PortIn snapshot;
|
||||||
|
{
|
||||||
|
Common::LockGuard lock(m_mutex);
|
||||||
|
auto* port = GetAudioInPort(handle);
|
||||||
|
if (port == nullptr) {
|
||||||
|
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if (port->busy) {
|
||||||
|
return AUDIO_IN_ERROR_BUSY;
|
||||||
|
}
|
||||||
|
port->busy = true;
|
||||||
|
snapshot = *port;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t next_time = m_in_ports[handle.GetId()].last_input_time + block_time;
|
const uint64_t block_time = (1000000ULL * snapshot.samples_num) / snapshot.freq;
|
||||||
uint64_t wait_time = (next_time > current_time ? next_time - current_time : 0);
|
uint64_t wait_time = 0;
|
||||||
|
if (snapshot.asynchronous) {
|
||||||
// TODO(): Audio input is not yet implemented, so simulate audio delay
|
if (dest != nullptr) {
|
||||||
|
wait_time = block_time;
|
||||||
|
}
|
||||||
|
} else if (snapshot.last_input_time != 0) {
|
||||||
|
const auto now = LibKernel::KernelGetProcessTime();
|
||||||
|
const auto next = snapshot.last_input_time + block_time;
|
||||||
|
if (next > now) {
|
||||||
|
wait_time = next - now;
|
||||||
|
}
|
||||||
|
}
|
||||||
Common::Thread::SleepMicro(wait_time);
|
Common::Thread::SleepMicro(wait_time);
|
||||||
|
if (dest != nullptr) {
|
||||||
m_in_ports[handle.GetId()].last_input_time = LibKernel::KernelGetProcessTime();
|
// No input device backend: return silence matching AUDIO_IN_SILENT_STATE_DEVICE_NONE.
|
||||||
|
std::memset(dest, 0, snapshot.samples_num * snapshot.bytes_per_frame);
|
||||||
return port.samples_num;
|
}
|
||||||
|
{
|
||||||
|
Common::LockGuard lock(m_mutex);
|
||||||
|
auto& port = m_in_ports[handle.GetId()];
|
||||||
|
port.last_input_time = dest != nullptr ? LibKernel::KernelGetProcessTime() : 0;
|
||||||
|
port.busy = false;
|
||||||
|
}
|
||||||
|
return dest != nullptr ? static_cast<int>(snapshot.samples_num) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace AudioOut {
|
namespace AudioOut {
|
||||||
@@ -810,25 +853,36 @@ LIB_NAME("AudioIn", "AudioIn");
|
|||||||
|
|
||||||
constexpr int AUDIO_IN_SILENT_STATE_DEVICE_NONE = 0x1;
|
constexpr int AUDIO_IN_SILENT_STATE_DEVICE_NONE = 0x1;
|
||||||
|
|
||||||
int KYTY_SYSV_ABI AudioInOpen(int user_id, uint32_t type, uint32_t index, uint32_t len,
|
static int OpenPort(int user_id, int type, int index, uint32_t len, uint32_t freq,
|
||||||
uint32_t freq, uint32_t param) {
|
uint32_t param, bool asynchronous) {
|
||||||
PRINT_NAME();
|
|
||||||
|
|
||||||
LOGF("\t user_id = %d\n"
|
LOGF("\t user_id = %d\n"
|
||||||
"\t type = %u\n"
|
"\t type = %d\n"
|
||||||
"\t index = %d\n"
|
"\t index = %d\n"
|
||||||
"\t len = %u\n"
|
"\t len = %u\n"
|
||||||
"\t freq = %u\n",
|
"\t freq = %u\n",
|
||||||
user_id, type, index, len, freq);
|
user_id, type, index, len, freq);
|
||||||
|
|
||||||
EXIT_NOT_IMPLEMENTED(type != 1);
|
if (type != 0 && type != 1) {
|
||||||
EXIT_NOT_IMPLEMENTED(index != 0);
|
return AUDIO_IN_ERROR_INVALID_TYPE;
|
||||||
|
}
|
||||||
|
if (index != 0) {
|
||||||
|
return AUDIO_IN_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
if (len != 128 && (asynchronous || len != 256)) {
|
||||||
|
return AUDIO_IN_ERROR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
if (freq != 48000 && (asynchronous || freq != 16000)) {
|
||||||
|
return AUDIO_IN_ERROR_INVALID_FREQ;
|
||||||
|
}
|
||||||
|
|
||||||
Audio::Format format = Audio::Format::Unknown;
|
Audio::Format format = Audio::Format::Unknown;
|
||||||
|
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 1: format = Audio::Format::Signed16bitMono; break;
|
case 1: format = Audio::Format::Signed16bitMono; break;
|
||||||
case 2: format = Audio::Format::Signed16bitStereo; break;
|
case 2: format = Audio::Format::Signed16bitStereo; break;
|
||||||
|
case 0x10:
|
||||||
|
case 0x11: format = Audio::Format::FloatMono; break;
|
||||||
|
case 0x12: format = Audio::Format::FloatStereo; break;
|
||||||
default: return AUDIO_IN_ERROR_INVALID_PARAM;
|
default: return AUDIO_IN_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,7 +890,7 @@ int KYTY_SYSV_ABI AudioInOpen(int user_id, uint32_t type, uint32_t index, uint32
|
|||||||
|
|
||||||
EXIT_IF(g_audio == nullptr);
|
EXIT_IF(g_audio == nullptr);
|
||||||
|
|
||||||
auto id = g_audio->AudioInOpen(type, len, freq, format);
|
auto id = g_audio->AudioInOpen(len, freq, format, asynchronous);
|
||||||
|
|
||||||
if (!id.IsValid()) {
|
if (!id.IsValid()) {
|
||||||
return AUDIO_IN_ERROR_PORT_FULL;
|
return AUDIO_IN_ERROR_PORT_FULL;
|
||||||
@@ -845,18 +899,35 @@ int KYTY_SYSV_ABI AudioInOpen(int user_id, uint32_t type, uint32_t index, uint32
|
|||||||
return id.ToInt();
|
return id.ToInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int KYTY_SYSV_ABI AudioInOpen(int user_id, int type, int index, uint32_t len,
|
||||||
|
uint32_t freq, uint32_t param) {
|
||||||
|
PRINT_NAME();
|
||||||
|
return OpenPort(user_id, type, index, len, freq, param, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int KYTY_SYSV_ABI AudioInHqOpen(int user_id, int type, int index, uint32_t len,
|
||||||
|
uint32_t freq, uint32_t param) {
|
||||||
|
PRINT_NAME();
|
||||||
|
return OpenPort(user_id, type, index, len, freq, param, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int KYTY_SYSV_ABI AudioInClose(int handle) {
|
||||||
|
PRINT_NAME();
|
||||||
|
EXIT_IF(g_audio == nullptr);
|
||||||
|
if (handle <= 0) {
|
||||||
|
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
return g_audio->AudioInClose(Audio::Id(handle));
|
||||||
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI AudioInInput(int handle, void* dest) {
|
int KYTY_SYSV_ABI AudioInInput(int handle, void* dest) {
|
||||||
PRINT_NAME();
|
PRINT_NAME();
|
||||||
|
|
||||||
EXIT_NOT_IMPLEMENTED(dest == nullptr);
|
|
||||||
|
|
||||||
EXIT_IF(g_audio == nullptr);
|
EXIT_IF(g_audio == nullptr);
|
||||||
|
if (handle <= 0) {
|
||||||
if (!g_audio->AudioInValid(Audio::Id(handle))) {
|
|
||||||
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<int>(g_audio->AudioInInput(Audio::Id(handle), dest));
|
return g_audio->AudioInInput(Audio::Id(handle), dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI AudioInGetSilentState(int handle) {
|
int KYTY_SYSV_ABI AudioInGetSilentState(int handle) {
|
||||||
@@ -864,7 +935,7 @@ int KYTY_SYSV_ABI AudioInGetSilentState(int handle) {
|
|||||||
|
|
||||||
EXIT_IF(g_audio == nullptr);
|
EXIT_IF(g_audio == nullptr);
|
||||||
|
|
||||||
if (!g_audio->AudioInValid(Audio::Id(handle))) {
|
if (handle <= 0 || !g_audio->AudioInValid(Audio::Id(handle))) {
|
||||||
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
return AUDIO_IN_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -96,8 +96,11 @@ int KYTY_SYSV_ABI AudioOut2MasteringTerm();
|
|||||||
|
|
||||||
namespace AudioIn {
|
namespace AudioIn {
|
||||||
|
|
||||||
int KYTY_SYSV_ABI AudioInOpen(int user_id, uint32_t type, uint32_t index, uint32_t len,
|
int KYTY_SYSV_ABI AudioInOpen(int user_id, int type, int index, uint32_t len,
|
||||||
uint32_t freq, uint32_t param);
|
uint32_t freq, uint32_t param);
|
||||||
|
int KYTY_SYSV_ABI AudioInHqOpen(int user_id, int type, int index, uint32_t len,
|
||||||
|
uint32_t freq, uint32_t param);
|
||||||
|
int KYTY_SYSV_ABI AudioInClose(int handle);
|
||||||
int KYTY_SYSV_ABI AudioInInput(int handle, void* dest);
|
int KYTY_SYSV_ABI AudioInInput(int handle, void* dest);
|
||||||
int KYTY_SYSV_ABI AudioInGetSilentState(int handle);
|
int KYTY_SYSV_ABI AudioInGetSilentState(int handle);
|
||||||
|
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ namespace AudioIn = Audio::AudioIn;
|
|||||||
|
|
||||||
LIB_DEFINE(InitAudio_1_AudioIn) {
|
LIB_DEFINE(InitAudio_1_AudioIn) {
|
||||||
LIB_FUNC("5NE8Sjc7VC8", AudioIn::AudioInOpen);
|
LIB_FUNC("5NE8Sjc7VC8", AudioIn::AudioInOpen);
|
||||||
|
LIB_FUNC("nya-R5gDYhM", AudioIn::AudioInHqOpen);
|
||||||
|
LIB_FUNC("Jh6WbHhnI68", AudioIn::AudioInClose);
|
||||||
LIB_FUNC("LozEOU8+anM", AudioIn::AudioInInput);
|
LIB_FUNC("LozEOU8+anM", AudioIn::AudioInInput);
|
||||||
LIB_FUNC("BohEAQ7DlUE", AudioIn::AudioInGetSilentState);
|
LIB_FUNC("BohEAQ7DlUE", AudioIn::AudioInGetSilentState);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user