1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 11:13:19 +01:00

SSPlayer funcs in libmixer

This commit is contained in:
Nekotekina 2014-07-05 23:24:14 +04:00
parent d16953d392
commit 60f3ed3543
2 changed files with 360 additions and 88 deletions

View File

@ -21,8 +21,13 @@ std::mutex mixer_mutex;
float mixdata[8*256]; float mixdata[8*256];
u64 mixcount = 0; u64 mixcount = 0;
std::vector<SSPlayer> ssp;
int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 samples) int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 samples)
{ {
libmixer->Log("cellAANAddData(handle=%d, port=%d, offset=0x%x, addr=0x%x, samples=%d)",
aan_handle, aan_port, offset, addr, samples);
u32 type = aan_port >> 16; u32 type = aan_port >> 16;
u32 port = aan_port & 0xffff; u32 port = aan_port & 0xffff;
@ -40,17 +45,11 @@ int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 sampl
type = 0; break; type = 0; break;
} }
if (aan_handle == 0x11111111 && samples == 256 && type && offset == 0) if (aan_handle != 0x11111111 || samples != 256 || !type || offset != 0)
{ {
libmixer->Log("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr=0x%x, samples=0x%x)", libmixer->Error("cellAANAddData(handle=%d, port=%d, offset=0x%x, addr=0x%x, samples=%d): invalid parameters",
aan_handle, aan_port, offset, addr, samples); aan_handle, aan_port, offset, addr, samples);
} return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
else
{
libmixer->Error("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr=0x%x, samples=0x%x)",
aan_handle, aan_port, offset, addr, samples);
Emu.Pause();
return CELL_OK;
} }
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -109,74 +108,386 @@ int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 sampl
int cellAANConnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo) int cellAANConnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo)
{ {
libmixer->Error("cellAANConnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcePortNo=0x%x)", libmixer->Warning("cellAANConnect(receive=%d, receivePortNo=%d, source=%d, sourcePortNo=%d)",
receive, receivePortNo, source, sourcePortNo); receive, receivePortNo, source, sourcePortNo);
std::lock_guard<std::mutex> lock(mixer_mutex);
if (source >= ssp.size() || !ssp[source].m_created)
{
libmixer->Error("cellAANConnect(): invalid source (%d)", source);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
ssp[source].m_connected = true;
return CELL_OK; return CELL_OK;
} }
int cellAANDisconnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo) int cellAANDisconnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo)
{ {
libmixer->Error("cellAANDisconnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcePortNo=0x%x)", libmixer->Warning("cellAANDisconnect(receive=%d, receivePortNo=%d, source=%d, sourcePortNo=%d)",
receive, receivePortNo, source, sourcePortNo); receive, receivePortNo, source, sourcePortNo);
std::lock_guard<std::mutex> lock(mixer_mutex);
if (source >= ssp.size() || !ssp[source].m_created)
{
libmixer->Error("cellAANDisconnect(): invalid source (%d)", source);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
ssp[source].m_connected = false;
return CELL_OK; return CELL_OK;
} }
int cellSSPlayerCreate(mem32_t handle, mem_ptr_t<CellSSPlayerConfig> config) int cellSSPlayerCreate(mem32_t handle, mem_ptr_t<CellSSPlayerConfig> config)
{ {
libmixer->Error("cellSSPlayerCreate(handle_addr=0x%x, config_addr=0x%x)", libmixer->Warning("cellSSPlayerCreate(handle_addr=0x%x, config_addr=0x%x)",
handle.GetAddr(), config.GetAddr()); handle.GetAddr(), config.GetAddr());
if (!config.IsGood())
{
return CELL_EFAULT;
}
if (config->outputMode != 0 || config->channels - 1 >= 2)
{
libmixer->Error("cellSSPlayerCreate(config.outputMode=%d, config.channels=%d): invalid parameters",
(u32)config->outputMode, (u32)config->channels);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
std::lock_guard<std::mutex> lock(mixer_mutex);
SSPlayer p;
p.m_created = true;
p.m_connected = false;
p.m_active = false;
p.m_channels = config->channels;
ssp.push_back(p);
handle = ssp.size() - 1;
return CELL_OK; return CELL_OK;
} }
int cellSSPlayerRemove(u32 handle) int cellSSPlayerRemove(u32 handle)
{ {
libmixer->Error("cellSSPlayerRemove(handle=%d)", handle); libmixer->Warning("cellSSPlayerRemove(handle=%d)", handle);
std::lock_guard<std::mutex> lock(mixer_mutex);
if (handle >= ssp.size() || !ssp[handle].m_created)
{
libmixer->Error("cellSSPlayerRemove(): SSPlayer not found (%d)", handle);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
ssp[handle].m_active = false;
ssp[handle].m_created = false;
ssp[handle].m_connected = false;
return CELL_OK; return CELL_OK;
} }
int cellSSPlayerSetWave(u32 handle, mem_ptr_t<CellSSPlayerWaveParam> waveInfo, mem_ptr_t<CellSSPlayerCommonParam> commonInfo) int cellSSPlayerSetWave(u32 handle, mem_ptr_t<CellSSPlayerWaveParam> waveInfo, mem_ptr_t<CellSSPlayerCommonParam> commonInfo)
{ {
libmixer->Error("cellSSPlayerSetWave(handle=%d, waveInfo_addr=0x%x, commonInfo_addr=0x%x)", libmixer->Warning("cellSSPlayerSetWave(handle=%d, waveInfo_addr=0x%x, commonInfo_addr=0x%x)",
handle, waveInfo.GetAddr(), commonInfo.GetAddr()); handle, waveInfo.GetAddr(), commonInfo.GetAddr());
if (!waveInfo.IsGood() || (commonInfo.GetAddr() && !commonInfo.IsGood()))
{
return CELL_EFAULT;
}
std::lock_guard<std::mutex> lock(mixer_mutex);
if (handle >= ssp.size() || !ssp[handle].m_created)
{
libmixer->Error("cellSSPlayerSetWave(): SSPlayer not found (%d)", handle);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
// TODO: check parameters
ssp[handle].m_addr = waveInfo->addr;
ssp[handle].m_samples = waveInfo->samples;
ssp[handle].m_loop_start = waveInfo->loopStartOffset - 1;
ssp[handle].m_loop_mode = commonInfo.GetAddr() ? commonInfo->loopMode : CELL_SSPLAYER_ONESHOT;
ssp[handle].m_position = waveInfo->startOffset - 1;
return CELL_OK; return CELL_OK;
} }
int cellSSPlayerPlay(u32 handle, mem_ptr_t<CellSSPlayerRuntimeInfo> info) int cellSSPlayerPlay(u32 handle, mem_ptr_t<CellSSPlayerRuntimeInfo> info)
{ {
libmixer->Error("cellSSPlayerPlay(handle=%d, info_addr=0x%x)", handle, info.GetAddr()); libmixer->Warning("cellSSPlayerPlay(handle=%d, info_addr=0x%x)", handle, info.GetAddr());
if (!info.IsGood())
{
return CELL_EFAULT;
}
std::lock_guard<std::mutex> lock(mixer_mutex);
if (handle >= ssp.size() || !ssp[handle].m_created)
{
libmixer->Error("cellSSPlayerPlay(): SSPlayer not found (%d)", handle);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
// TODO: check parameters
ssp[handle].m_active = true;
ssp[handle].m_level = info->level;
ssp[handle].m_speed = info->speed;
ssp[handle].m_x = info->position.x;
ssp[handle].m_y = info->position.y;
ssp[handle].m_z = info->position.z;
return CELL_OK; return CELL_OK;
} }
int cellSSPlayerStop(u32 handle, u32 mode) int cellSSPlayerStop(u32 handle, u32 mode)
{ {
libmixer->Error("cellSSPlayerStop(handle=%d, mode=0x%x)", handle, mode); libmixer->Warning("cellSSPlayerStop(handle=%d, mode=0x%x)", handle, mode);
std::lock_guard<std::mutex> lock(mixer_mutex);
if (handle >= ssp.size() || !ssp[handle].m_created)
{
libmixer->Error("cellSSPlayerStop(): SSPlayer not found (%d)", handle);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
// TODO: transition to stop state
ssp[handle].m_active = false;
return CELL_OK; return CELL_OK;
} }
int cellSSPlayerSetParam(u32 handle, mem_ptr_t<CellSSPlayerRuntimeInfo> info) int cellSSPlayerSetParam(u32 handle, mem_ptr_t<CellSSPlayerRuntimeInfo> info)
{ {
libmixer->Error("cellSSPlayerSetParam(handle=%d, info_addr=0x%x)", handle, info.GetAddr()); libmixer->Warning("cellSSPlayerSetParam(handle=%d, info_addr=0x%x)", handle, info.GetAddr());
if (!info.IsGood())
{
return CELL_EFAULT;
}
std::lock_guard<std::mutex> lock(mixer_mutex);
if (handle >= ssp.size() || !ssp[handle].m_created)
{
libmixer->Error("cellSSPlayerSetParam(): SSPlayer not found (%d)", handle);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
}
// TODO: check parameters
ssp[handle].m_level = info->level;
ssp[handle].m_speed = info->speed;
ssp[handle].m_x = info->position.x;
ssp[handle].m_y = info->position.y;
ssp[handle].m_z = info->position.z;
return CELL_OK; return CELL_OK;
} }
s32 cellSSPlayerGetState(u32 handle) int cellSSPlayerGetState(u32 handle)
{ {
libmixer->Error("cellSSPlayerGetState(handle=%d) -> OFF", handle); libmixer->Warning("cellSSPlayerGetState(handle=%d)", handle);
std::lock_guard<std::mutex> lock(mixer_mutex);
if (handle >= ssp.size() || !ssp[handle].m_created)
{
libmixer->Warning("cellSSPlayerGetState(): SSPlayer not found (%d)", handle);
return CELL_SSPLAYER_STATE_ERROR;
}
if (ssp[handle].m_active)
{
return CELL_SSPLAYER_STATE_ON;
}
return CELL_SSPLAYER_STATE_OFF; return CELL_SSPLAYER_STATE_OFF;
} }
int cellSurMixerCreate(const mem_ptr_t<CellSurMixerConfig> config) int cellSurMixerCreate(const mem_ptr_t<CellSurMixerConfig> config)
{ {
libmixer->Warning("cellSurMixerCreate(config_addr=0x%x)", config.GetAddr()); libmixer->Warning("cellSurMixerCreate(config_addr=0x%x)", config.GetAddr());
surMixer = *config; surMixer = *config;
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
if (port.m_is_audio_port_opened)
{
return CELL_LIBMIXER_ERROR_FULL;
}
port.channel = 8;
port.block = 16;
port.attr = 0;
port.level = 1.0f;
libmixer->Warning("*** audio port opened(default)");
port.m_is_audio_port_opened = true;
port.tag = 0;
m_config.m_port_in_use++;
libmixer->Warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)", libmixer->Warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)",
(u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8); (u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8);
thread t("Surmixer Thread", []()
{
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
CPUThread* mixerCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
mixerCb->SetName("Surmixer Callback");
mixcount = 0;
while (port.m_is_audio_port_opened)
{
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "Surmixer aborted");
break;
}
if (mixcount > (port.tag + 15)) // preemptive buffer filling (probably hack)
{
Sleep(1);
continue;
}
if (port.m_is_audio_port_started)
{
u64 stamp0 = get_system_time();
memset(mixdata, 0, sizeof(mixdata));
if (surMixerCb) mixerCb->ExecAsCallback(surMixerCb, true, surMixerCbArg, mixcount, 256);
u64 stamp1 = get_system_time();
{
std::lock_guard<std::mutex> lock(mixer_mutex);
for (auto& p : ssp) if (p.m_active && p.m_created)
{
float left = 0.0f;
float right = 0.0f;
float speed = fabs(p.m_speed);
float fpos = 0.0f;
for (int i = 0; i < 256; i++) if (p.m_active)
{
u32 pos = p.m_position;
int pos_inc = 0;
if (p.m_speed > 0.0f) // select direction
{
pos_inc = 1;
}
else if (p.m_speed < 0.0f)
{
pos_inc = -1;
}
int shift = i - (int)fpos; // change playback speed (simple and rough)
if (shift > 0)
{
// slow playback
pos_inc = 0; // duplicate one sample at this time
fpos += 1.0f;
fpos += speed;
}
else if (shift < 0)
{
// fast playback
i--; // mix two sample into one at this time
fpos -= 1.0f;
}
else
{
fpos += speed;
}
p.m_position += (u32)pos_inc;
if (p.m_channels == 1) // get mono data
{
mem16_t v(p.m_addr + pos * sizeof(u16));
left = right = (float)(s16)re16(v.GetValue()) / 0x8000 * p.m_level;
}
else if (p.m_channels == 2) // get stereo data
{
mem16_t v1(p.m_addr + (pos * 2 + 0) * sizeof(u16));
mem16_t v2(p.m_addr + (pos * 2 + 1) * sizeof(u16));
left = (float)(s16)re16(v1.GetValue()) / 0x8000 * p.m_level;
right = (float)(s16)re16(v2.GetValue()) / 0x8000 * p.m_level;
}
if (p.m_connected) // mix
{
// TODO: m_x, m_y, m_z ignored
mixdata[i * 8 + 0] += left;
mixdata[i * 8 + 1] += right;
}
if ((p.m_position == p.m_samples && p.m_speed > 0.0f) ||
(p.m_position == ~0 && p.m_speed < 0.0f)) // loop or stop
{
if (p.m_loop_mode == CELL_SSPLAYER_LOOP_ON)
{
p.m_position = p.m_loop_start;
}
else if (p.m_loop_mode == CELL_SSPLAYER_ONESHOT_CONT)
{
p.m_position -= (u32)pos_inc; // restore position
}
else // oneshot
{
p.m_active = false;
p.m_position = p.m_loop_start; // TODO: check value
}
}
}
}
}
u64 stamp2 = get_system_time();
auto buf = (be_t<float>*)&Memory[m_config.m_buffer + (128 * 1024 * SUR_PORT) + (mixcount % port.block) * port.channel * 256 * sizeof(float)];
for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++)
{
// reverse byte order
buf[i] = mixdata[i];
}
u64 stamp3 = get_system_time();
//ConLog.Write("Libmixer perf: start=%lld (cb=%lld, ssp=%lld, finalize=%lld)", stamp0 - m_config.start_time, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2);
}
mixcount++;
}
{
std::lock_guard<std::mutex> lock(mixer_mutex);
ssp.clear();
}
Emu.GetCPU().RemoveThread(mixerCb->GetId());
});
t.detach();
return CELL_OK; return CELL_OK;
} }
int cellSurMixerGetAANHandle(mem32_t handle) int cellSurMixerGetAANHandle(mem32_t handle)
{ {
libmixer->Warning("cellSurMixerGetAANHandle(handle_addr=0x%x) -> 0x11111111", handle.GetAddr()); libmixer->Warning("cellSurMixerGetAANHandle(handle_addr=0x%x) -> %d", handle.GetAddr(), 0x11111111);
handle = 0x11111111; handle = 0x11111111;
return CELL_OK; return CELL_OK;
} }
@ -212,72 +523,9 @@ int cellSurMixerStart()
if (port.m_is_audio_port_opened) if (port.m_is_audio_port_opened)
{ {
return CELL_LIBMIXER_ERROR_FULL; port.m_is_audio_port_started = true;
} }
port.channel = 8;
port.block = 16;
port.attr = 0;
port.level = 1.0f;
libmixer->Warning("*** audio port opened(default)");
port.m_is_audio_port_opened = true;
port.tag = 0;
m_config.m_port_in_use++;
port.m_is_audio_port_started = true;
thread t("Surmixer Thread", []()
{
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
CPUThread* mixerCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
mixerCb->SetName("Surmixer Callback");
mixcount = 0;
while (port.m_is_audio_port_started)
{
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "Surmixer aborted");
return;
}
if (mixcount > (port.tag + 15)) // preemptive buffer filling (probably hack)
{
Sleep(1);
continue;
}
u64 stamp0 = get_system_time();
memset(mixdata, 0, sizeof(mixdata));
mixerCb->ExecAsCallback(surMixerCb, true, surMixerCbArg, mixcount, 256);
u64 stamp1 = get_system_time();
auto buf = (be_t<float>*)&Memory[m_config.m_buffer + (128 * 1024 * SUR_PORT) + (mixcount % port.block) * port.channel * 256 * sizeof(float)];
for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++)
{
// reverse byte order
buf[i] = mixdata[i];
}
u64 stamp2 = get_system_time();
//ConLog.Write("Libmixer perf: start=%d (cb=%d, finalize=%d)",
//stamp0 - m_config.start_time, stamp1-stamp0, stamp2-stamp1);
mixcount++;
}
Emu.GetCPU().RemoveThread(mixerCb->GetId());
});
t.detach();
return CELL_OK; return CELL_OK;
} }
@ -336,7 +584,15 @@ int cellSurMixerChStripSetParameter(u32 type, u32 index, mem_ptr_t<CellSurMixerC
int cellSurMixerPause(u32 type) int cellSurMixerPause(u32 type)
{ {
libmixer->Error("cellSurMixerPause(type=%d)", type); libmixer->Warning("cellSurMixerPause(type=%d)", type);
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
if (port.m_is_audio_port_opened)
{
port.m_is_audio_port_started = false;
}
return CELL_OK; return CELL_OK;
} }

View File

@ -119,7 +119,7 @@ struct CellSSPlayerConfig
struct CellSSPlayerWaveParam struct CellSSPlayerWaveParam
{ {
void *addr; be_t<u32> addr;
be_t<s32> format; be_t<s32> format;
be_t<u32> samples; be_t<u32> samples;
be_t<u32> loopStartOffset; be_t<u32> loopStartOffset;
@ -158,10 +158,26 @@ struct CellSurMixerConfig
struct CellSurMixerChStripParam struct CellSurMixerChStripParam
{ {
be_t<u32> param; be_t<u32> param;
void *attribute; be_t<u32> attribute_addr;
be_t<s32> dBSwitch; be_t<s32> dBSwitch;
be_t<float> floatVal; be_t<float> floatVal;
be_t<s32> intVal; be_t<s32> intVal;
}; };
CellSSPlayerWaveParam current_SSPlayerWaveParam; struct SSPlayer
{
bool m_created; // SSPlayerCreate/Remove
bool m_connected; // AANConnect/Disconnect
bool m_active; // SSPlayerPlay/Stop
u32 m_channels; // 1 or 2
u32 m_addr;
u32 m_samples;
u32 m_loop_start;
u32 m_loop_mode;
u32 m_position;
float m_level;
float m_speed;
float m_x;
float m_y;
float m_z;
};