mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
[orbis-kernel]: AudioOut: relatively correct parsing (#52)
This commit is contained in:
parent
b87f8f6ea0
commit
ca58c03eb6
|
|
@ -20,8 +20,32 @@ struct AudioOutChannelInfo {
|
||||||
Ref<EventFlag> evf;
|
Ref<EventFlag> evf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AudioOutParams {
|
||||||
|
std::uint64_t control{};
|
||||||
|
std::uint32_t formatChannels{};
|
||||||
|
float unk0{};
|
||||||
|
float unk1{};
|
||||||
|
float unk2{};
|
||||||
|
float unk3{};
|
||||||
|
float unk4{};
|
||||||
|
float unk5{};
|
||||||
|
float unk6{};
|
||||||
|
float unk7{};
|
||||||
|
std::uint32_t formatIsFloat{};
|
||||||
|
std::uint64_t freq{};
|
||||||
|
std::uint32_t formatIsStd{};
|
||||||
|
std::uint32_t seek{};
|
||||||
|
std::uint32_t seekPart{};
|
||||||
|
std::uint64_t unk8{};
|
||||||
|
std::uint32_t port{};
|
||||||
|
std::uint32_t unk9{};
|
||||||
|
std::uint64_t unk10{};
|
||||||
|
std::uint32_t sampleLength{};
|
||||||
|
};
|
||||||
|
|
||||||
struct AudioOut {
|
struct AudioOut {
|
||||||
std::mutex thrMtx;
|
std::mutex thrMtx;
|
||||||
|
std::mutex soxMtx;
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
AudioOutChannelInfo channelInfo;
|
AudioOutChannelInfo channelInfo;
|
||||||
std::atomic<bool> exit{false};
|
std::atomic<bool> exit{false};
|
||||||
|
|
@ -95,96 +119,75 @@ private:
|
||||||
MAP_SHARED, bufferFd, 0);
|
MAP_SHARED, bufferFd, 0);
|
||||||
auto bitPattern = 1u << info.port;
|
auto bitPattern = 1u << info.port;
|
||||||
|
|
||||||
int firstNonEmptyByteIndex = -1;
|
auto portOffset = 32 + 0x94 * info.port * 4;
|
||||||
|
|
||||||
for (std::size_t i = 24; i < controlStat.st_size; ++i) {
|
auto *params = reinterpret_cast<AudioOutParams *>(controlPtr + portOffset);
|
||||||
if (controlPtr[i] != 0) {
|
|
||||||
firstNonEmptyByteIndex = i - 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: following line triggers error, investigate _C shm layout
|
// samples length will be inited after some time, so we wait for it
|
||||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
while (params->sampleLength == 0) {
|
||||||
|
|
||||||
if (exit.load(std::memory_order::relaxed)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstNonEmptyByteIndex < 0) {
|
ORBIS_LOG_NOTICE("AudioOut: params", params->port, params->control,
|
||||||
ORBIS_LOG_ERROR("AudioOut: Failed to find first non zero byte index");
|
params->formatChannels, params->formatIsFloat,
|
||||||
std::abort();
|
params->formatIsStd, params->freq, params->sampleLength);
|
||||||
}
|
|
||||||
|
|
||||||
int outParamFirstByte = controlPtr[firstNonEmptyByteIndex + 8];
|
|
||||||
int isFloat = controlPtr[firstNonEmptyByteIndex + 44];
|
|
||||||
|
|
||||||
// int outParamThirdByte = *((char *)controlPtr + firstNonEmptyByteIndex +
|
|
||||||
// 44); // need to find the third index
|
|
||||||
|
|
||||||
unsigned inChannels = 2;
|
unsigned inChannels = 2;
|
||||||
unsigned inSamples = 256;
|
unsigned inSamples = params->sampleLength;
|
||||||
sox_rate_t sampleRate = 48000; // probably there is no point to parse
|
sox_rate_t sampleRate = 48000; // probably there is no point to parse
|
||||||
// frequency, because it's always 48000
|
// frequency, because it's always 48000
|
||||||
if (outParamFirstByte == 2 && isFloat == 0) {
|
if (params->formatChannels == 2 && !params->formatIsFloat) {
|
||||||
inChannels = 1;
|
inChannels = 1;
|
||||||
ORBIS_LOG_NOTICE(
|
ORBIS_LOG_NOTICE(
|
||||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO");
|
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO");
|
||||||
} else if (outParamFirstByte == 4 && isFloat == 0) {
|
} else if (params->formatChannels == 4 && !params->formatIsFloat) {
|
||||||
inChannels = 2;
|
inChannels = 2;
|
||||||
ORBIS_LOG_NOTICE(
|
ORBIS_LOG_NOTICE(
|
||||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO");
|
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO");
|
||||||
} else if (outParamFirstByte == 16 && isFloat == 0) {
|
} else if (params->formatChannels == 16 && !params->formatIsFloat &&
|
||||||
|
!params->formatIsStd) {
|
||||||
inChannels = 8;
|
inChannels = 8;
|
||||||
ORBIS_LOG_NOTICE(
|
ORBIS_LOG_NOTICE(
|
||||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH");
|
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH");
|
||||||
} else if (outParamFirstByte == 4 && isFloat == 1) {
|
} else if (params->formatChannels == 16 && !params->formatIsFloat &&
|
||||||
|
params->formatIsStd) {
|
||||||
|
inChannels = 8;
|
||||||
|
ORBIS_LOG_NOTICE(
|
||||||
|
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD");
|
||||||
|
} else if (params->formatChannels == 4 && params->formatIsFloat) {
|
||||||
inChannels = 1;
|
inChannels = 1;
|
||||||
ORBIS_LOG_NOTICE(
|
ORBIS_LOG_NOTICE(
|
||||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO");
|
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO");
|
||||||
} else if (outParamFirstByte == 8 && isFloat == 1) {
|
} else if (params->formatChannels == 8 && params->formatIsFloat) {
|
||||||
inChannels = 2;
|
inChannels = 2;
|
||||||
ORBIS_LOG_NOTICE(
|
ORBIS_LOG_NOTICE(
|
||||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO");
|
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO");
|
||||||
} else if (outParamFirstByte == 32 && isFloat == 1) {
|
} else if (params->formatChannels == 32 && params->formatIsFloat &&
|
||||||
|
!params->formatIsStd) {
|
||||||
inChannels = 8;
|
inChannels = 8;
|
||||||
ORBIS_LOG_NOTICE(
|
ORBIS_LOG_NOTICE(
|
||||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH");
|
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH");
|
||||||
|
} else if (params->formatChannels == 32 && params->formatIsFloat &&
|
||||||
|
params->formatIsStd) {
|
||||||
|
inChannels = 8;
|
||||||
|
ORBIS_LOG_NOTICE("AudioOut: format is "
|
||||||
|
"ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD");
|
||||||
} else {
|
} else {
|
||||||
ORBIS_LOG_ERROR("AudioOut: unknown output type");
|
ORBIS_LOG_ERROR("AudioOut: unknown format type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// it's need third byte
|
|
||||||
// if (outParamFirstByte == 16 && outParamSecondByte == 0 &&
|
|
||||||
// outParamThirdByte
|
|
||||||
// == 1) {
|
|
||||||
// printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD");
|
|
||||||
// }
|
|
||||||
// if (outParamFirstByte == 32 && outParamSecondByte == 1 &&
|
|
||||||
// outParamThirdByte
|
|
||||||
// == 1) {
|
|
||||||
// printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// length byte will be inited after some time, so we wait for it
|
|
||||||
int samplesLengthByte = 0;
|
|
||||||
while (true) {
|
|
||||||
samplesLengthByte = controlPtr[firstNonEmptyByteIndex + 97];
|
|
||||||
if (samplesLengthByte > 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inSamples = samplesLengthByte * 256;
|
|
||||||
|
|
||||||
sox_signalinfo_t out_si = {
|
sox_signalinfo_t out_si = {
|
||||||
.rate = sampleRate,
|
.rate = sampleRate,
|
||||||
.channels = inChannels,
|
.channels = inChannels,
|
||||||
.precision = SOX_SAMPLE_PRECISION,
|
.precision = SOX_SAMPLE_PRECISION,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// need to be locked because libsox doesn't like simultaneous opening of the
|
||||||
|
// output
|
||||||
|
std::unique_lock lock(soxMtx);
|
||||||
sox_format_t *output =
|
sox_format_t *output =
|
||||||
sox_open_write("default", &out_si, NULL, "alsa", NULL, NULL);
|
sox_open_write("default", &out_si, NULL, "alsa", NULL, NULL);
|
||||||
|
soxMtx.unlock();
|
||||||
|
|
||||||
if (!output) {
|
if (!output) {
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
@ -197,7 +200,7 @@ private:
|
||||||
while (!exit.load(std::memory_order::relaxed)) {
|
while (!exit.load(std::memory_order::relaxed)) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
|
||||||
if (isFloat == 0) {
|
if (!params->formatIsFloat) {
|
||||||
auto data = reinterpret_cast<const std::int16_t *>(audioBuffer);
|
auto data = reinterpret_cast<const std::int16_t *>(audioBuffer);
|
||||||
for (std::size_t i = 0; i < samples.size(); i++) {
|
for (std::size_t i = 0; i < samples.size(); i++) {
|
||||||
samples[i] = SOX_SIGNED_16BIT_TO_SAMPLE(data[i], clips);
|
samples[i] = SOX_SIGNED_16BIT_TO_SAMPLE(data[i], clips);
|
||||||
|
|
@ -217,9 +220,7 @@ private:
|
||||||
info.evf->set(bitPattern);
|
info.evf->set(bitPattern);
|
||||||
|
|
||||||
// set zero to freeing audiooutput
|
// set zero to freeing audiooutput
|
||||||
for (size_t i = 0; i < 8; ++i) {
|
params->control = 0;
|
||||||
controlPtr[firstNonEmptyByteIndex + i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sox_close(output);
|
sox_close(output);
|
||||||
|
|
|
||||||
|
|
@ -1234,8 +1234,8 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
||||||
}
|
}
|
||||||
} else if (syncCallParams.method == 0x12340002) { // something like open
|
} else if (syncCallParams.method == 0x12340002) { // something like open
|
||||||
struct SceSysAudioSystemIpcSomethingMethodArgs {
|
struct SceSysAudioSystemIpcSomethingMethodArgs {
|
||||||
uint32_t arg1;
|
uint32_t audioPort;
|
||||||
uint32_t arg2;
|
uint32_t channelId;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(SceSysAudioSystemIpcSomethingMethodArgs) == 0x8);
|
static_assert(sizeof(SceSysAudioSystemIpcSomethingMethodArgs) == 0x8);
|
||||||
|
|
@ -1249,12 +1249,30 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
||||||
ptr<SceSysAudioSystemIpcSomethingMethodArgs>(dataInfo.data));
|
ptr<SceSysAudioSystemIpcSomethingMethodArgs>(dataInfo.data));
|
||||||
|
|
||||||
ORBIS_LOG_TODO("impi: SceSysAudioSystemIpcSomethingMethodArgs",
|
ORBIS_LOG_TODO("impi: SceSysAudioSystemIpcSomethingMethodArgs",
|
||||||
args.arg1, args.arg2);
|
args.audioPort, args.channelId);
|
||||||
|
|
||||||
if (auto audioOut = g_context.audioOut) {
|
if (auto audioOut = g_context.audioOut) {
|
||||||
// here startToListen
|
// here startToListen
|
||||||
audioOut->start();
|
audioOut->start();
|
||||||
}
|
}
|
||||||
|
} else if (syncCallParams.method == 0x12340006) { // close port
|
||||||
|
struct SceSysAudioSystemIpcCloseAudioMethodArgs {
|
||||||
|
uint32_t audioPort;
|
||||||
|
uint32_t channelId;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(SceSysAudioSystemIpcCloseAudioMethodArgs) == 0x8);
|
||||||
|
|
||||||
|
if (dataInfo.size != sizeof(SceSysAudioSystemIpcCloseAudioMethodArgs)) {
|
||||||
|
return ErrorCode::INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceSysAudioSystemIpcCloseAudioMethodArgs args;
|
||||||
|
uread(args,
|
||||||
|
ptr<SceSysAudioSystemIpcCloseAudioMethodArgs>(dataInfo.data));
|
||||||
|
|
||||||
|
ORBIS_LOG_TODO("impi: SceSysAudioSystemIpcCloseAudioMethodArgs",
|
||||||
|
args.audioPort, args.channelId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue