mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 04:02:42 +01:00
cellAudio updated, thread_t updated
This commit is contained in:
parent
42b748a881
commit
fd06f70387
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Log.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
@ -285,7 +286,7 @@ void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||
ucontext_t* const ctx = (ucontext_t*)uct;
|
||||
const u64 addr64 = (u64)info->si_addr - (u64)Memory.GetBaseAddr();
|
||||
//const bool is_writing = false; // TODO: get it correctly
|
||||
if (addr64 < 0x100000000ull)
|
||||
if (addr64 < 0x100000000ull && GetCurrentNamedThread())
|
||||
{
|
||||
const u32 addr = (u32)addr64;
|
||||
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) // RawSPU MMIO registers
|
||||
@ -384,7 +385,7 @@ NamedThreadBase* GetCurrentNamedThread()
|
||||
|
||||
void SetCurrentNamedThread(NamedThreadBase* value)
|
||||
{
|
||||
auto old_value = g_tls_this_thread;
|
||||
const auto old_value = g_tls_this_thread;
|
||||
|
||||
if (old_value == value)
|
||||
{
|
||||
@ -536,23 +537,40 @@ bool ThreadBase::TestDestroy() const
|
||||
return m_destroy;
|
||||
}
|
||||
|
||||
thread::thread(const std::string& name, std::function<void()> func) : m_name(name)
|
||||
thread_t::thread_t(const std::string& name, std::function<void()> func) : m_name(name), m_state(TS_NON_EXISTENT)
|
||||
{
|
||||
start(func);
|
||||
}
|
||||
|
||||
thread::thread(const std::string& name) : m_name(name)
|
||||
thread_t::thread_t(const std::string& name) : m_name(name), m_state(TS_NON_EXISTENT)
|
||||
{
|
||||
}
|
||||
|
||||
thread::thread()
|
||||
thread_t::thread_t() : m_state(TS_NON_EXISTENT)
|
||||
{
|
||||
}
|
||||
|
||||
void thread::start(std::function<void()> func)
|
||||
void thread_t::set_name(const std::string& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
thread_t::~thread_t()
|
||||
{
|
||||
if (m_state == TS_JOINABLE)
|
||||
{
|
||||
m_thr.detach();
|
||||
}
|
||||
}
|
||||
|
||||
void thread_t::start(std::function<void()> func)
|
||||
{
|
||||
if (m_state.exchange(TS_NON_EXISTENT) == TS_JOINABLE)
|
||||
{
|
||||
m_thr.join(); // forcefully join previously created thread
|
||||
}
|
||||
|
||||
std::string name = m_name;
|
||||
|
||||
m_thr = std::thread([func, name]()
|
||||
{
|
||||
SetCurrentThreadDebugName(name.c_str());
|
||||
@ -567,6 +585,11 @@ void thread::start(std::function<void()> func)
|
||||
SetCurrentNamedThread(&info);
|
||||
g_thread_count++;
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, name + " started");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
func();
|
||||
@ -580,6 +603,15 @@ void thread::start(std::function<void()> func)
|
||||
LOG_ERROR(GENERAL, "%s: %s", name.c_str(), e.c_str());
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_NOTICE(HLE, name + " aborted");
|
||||
}
|
||||
else if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, name + " ended");
|
||||
}
|
||||
|
||||
SetCurrentNamedThread(nullptr);
|
||||
g_thread_count--;
|
||||
|
||||
@ -587,21 +619,41 @@ void thread::start(std::function<void()> func)
|
||||
_set_se_translator(old_se_translator);
|
||||
#endif
|
||||
});
|
||||
|
||||
if (m_state.exchange(TS_JOINABLE) == TS_JOINABLE)
|
||||
{
|
||||
assert(!"thread_t::start() failed"); // probably started from another thread
|
||||
}
|
||||
}
|
||||
|
||||
void thread::detach()
|
||||
void thread_t::detach()
|
||||
{
|
||||
if (m_state.exchange(TS_NON_EXISTENT) == TS_JOINABLE)
|
||||
{
|
||||
m_thr.detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!"thread_t::detach() failed"); // probably joined or detached
|
||||
}
|
||||
}
|
||||
|
||||
void thread::join()
|
||||
void thread_t::join()
|
||||
{
|
||||
if (m_state.exchange(TS_NON_EXISTENT) == TS_JOINABLE)
|
||||
{
|
||||
m_thr.join();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!"thread_t::join() failed"); // probably joined or detached
|
||||
}
|
||||
}
|
||||
|
||||
bool thread::joinable() const
|
||||
bool thread_t::joinable() const
|
||||
{
|
||||
return m_thr.joinable();
|
||||
//return m_thr.joinable();
|
||||
return m_state == TS_JOINABLE;
|
||||
}
|
||||
|
||||
bool waiter_map_t::is_stopped(u64 signal_id)
|
||||
|
@ -54,18 +54,32 @@ public:
|
||||
virtual void Task() = 0;
|
||||
};
|
||||
|
||||
class thread
|
||||
class thread_t
|
||||
{
|
||||
enum thread_state_t
|
||||
{
|
||||
TS_NON_EXISTENT,
|
||||
TS_JOINABLE,
|
||||
};
|
||||
|
||||
std::atomic<thread_state_t> m_state;
|
||||
std::string m_name;
|
||||
std::thread m_thr;
|
||||
|
||||
public:
|
||||
thread(const std::string& name, std::function<void()> func);
|
||||
thread(const std::string& name);
|
||||
thread();
|
||||
thread_t(const std::string& name, std::function<void()> func);
|
||||
thread_t(const std::string& name);
|
||||
thread_t();
|
||||
~thread_t();
|
||||
|
||||
thread_t(const thread_t& right) = delete;
|
||||
thread_t(thread_t&& right) = delete;
|
||||
|
||||
thread_t& operator =(const thread_t& right) = delete;
|
||||
thread_t& operator =(thread_t&& right) = delete;
|
||||
|
||||
public:
|
||||
void set_name(const std::string& name);
|
||||
void start(std::function<void()> func);
|
||||
void detach();
|
||||
void join();
|
||||
|
@ -11,8 +11,6 @@ ALCenum g_last_alc_error = ALC_NO_ERROR;
|
||||
#define checkForAlError(sit) if((g_last_al_error = alGetError()) != AL_NO_ERROR) printAlError(g_last_al_error, sit)
|
||||
#define checkForAlcError(sit) if((g_last_alc_error = alcGetError(m_device)) != ALC_NO_ERROR) printAlcError(g_last_alc_error, sit)
|
||||
|
||||
static const ALenum g_audio_format = Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32;
|
||||
|
||||
void printAlError(ALenum err, const char* situation)
|
||||
{
|
||||
if (err != AL_NO_ERROR)
|
||||
@ -102,7 +100,7 @@ void OpenALThread::Open(const void* src, int size)
|
||||
|
||||
for (uint i = 0; i<g_al_buffers_count; ++i)
|
||||
{
|
||||
alBufferData(m_buffers[i], g_audio_format, src, m_buffer_size, 48000);
|
||||
alBufferData(m_buffers[i], Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32, src, m_buffer_size, 48000);
|
||||
checkForAlError("alBufferData");
|
||||
}
|
||||
|
||||
@ -137,7 +135,7 @@ void OpenALThread::AddData(const void* src, int size)
|
||||
|
||||
int bsize = size < m_buffer_size ? size : m_buffer_size;
|
||||
|
||||
alBufferData(buffer, g_audio_format, bsrc, bsize, 48000);
|
||||
alBufferData(buffer, Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32, bsrc, bsize, 48000);
|
||||
checkForAlError("alBufferData");
|
||||
|
||||
alSourceQueueBuffers(m_source, 1, &buffer);
|
||||
|
@ -1,22 +1,32 @@
|
||||
#include "stdafx.h"
|
||||
#include "AudioDumper.h"
|
||||
|
||||
AudioDumper::AudioDumper(u8 ch) : m_header(ch)
|
||||
AudioDumper::AudioDumper() : m_header(0), m_init(false)
|
||||
{
|
||||
}
|
||||
|
||||
AudioDumper::~AudioDumper()
|
||||
{
|
||||
Finalize();
|
||||
}
|
||||
|
||||
bool AudioDumper::Init()
|
||||
bool AudioDumper::Init(u8 ch)
|
||||
{
|
||||
return m_output.Open("audio.wav", rFile::write);
|
||||
if ((m_init = m_output.Open("audio.wav", rFile::write)))
|
||||
{
|
||||
m_header = WAVHeader(ch);
|
||||
WriteHeader();
|
||||
}
|
||||
|
||||
return m_init;
|
||||
}
|
||||
|
||||
void AudioDumper::WriteHeader()
|
||||
{
|
||||
if (m_init)
|
||||
{
|
||||
m_output.Write(&m_header, sizeof(m_header)); // write file header
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
||||
@ -31,17 +41,27 @@ size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
||||
{
|
||||
if (((u8*)buffer)[i + (size & ~7)]) do_save = true;
|
||||
}
|
||||
if (!do_save) return size; // ignore empty data
|
||||
|
||||
if (m_init && do_save)
|
||||
#else
|
||||
if (m_init)
|
||||
#endif
|
||||
{
|
||||
size_t ret = m_output.Write(buffer, size);
|
||||
m_header.Size += (u32)ret;
|
||||
m_header.RIFF.Size += (u32)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void AudioDumper::Finalize()
|
||||
{
|
||||
if (m_init)
|
||||
{
|
||||
m_output.Seek(0);
|
||||
m_output.Write(&m_header, sizeof(m_header)); // write fixed file header
|
||||
m_output.Close();
|
||||
}
|
||||
}
|
@ -55,15 +55,16 @@ struct WAVHeader
|
||||
|
||||
class AudioDumper
|
||||
{
|
||||
private:
|
||||
WAVHeader m_header;
|
||||
rFile m_output;
|
||||
bool m_init;
|
||||
|
||||
public:
|
||||
AudioDumper(u8 ch);
|
||||
AudioDumper();
|
||||
~AudioDumper();
|
||||
|
||||
bool Init();
|
||||
public:
|
||||
bool Init(u8 ch);
|
||||
void WriteHeader();
|
||||
size_t WriteData(const void* buffer, size_t size);
|
||||
void Finalize();
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
XAudio2Thread::~XAudio2Thread()
|
||||
{
|
||||
Quit();
|
||||
if (m_source_voice) Quit();
|
||||
}
|
||||
|
||||
void XAudio2Thread::Init()
|
||||
@ -87,13 +87,15 @@ void XAudio2Thread::Open(const void* src, int size)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
WORD sample_size = Ini.AudioConvertToU16.GetValue() ? sizeof(u16) : sizeof(float);
|
||||
|
||||
WAVEFORMATEX waveformatex;
|
||||
waveformatex.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
waveformatex.wFormatTag = Ini.AudioConvertToU16.GetValue() ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
|
||||
waveformatex.nChannels = 2;
|
||||
waveformatex.nSamplesPerSec = 48000;
|
||||
waveformatex.nAvgBytesPerSec = 48000 * 2 * sizeof(float);
|
||||
waveformatex.nBlockAlign = 2 * sizeof(float);
|
||||
waveformatex.wBitsPerSample = 32;
|
||||
waveformatex.nAvgBytesPerSec = 48000 * 2 * (DWORD)sample_size;
|
||||
waveformatex.nBlockAlign = 2 * sample_size;
|
||||
waveformatex.wBitsPerSample = sample_size * 8;
|
||||
waveformatex.cbSize = 0;
|
||||
|
||||
hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
|
||||
|
@ -280,6 +280,7 @@ void CPUThread::Task()
|
||||
|
||||
return "unknown function";
|
||||
}
|
||||
|
||||
case CPU_THREAD_PPU:
|
||||
{
|
||||
if ((u32)syscall == syscall)
|
||||
@ -290,6 +291,7 @@ void CPUThread::Task()
|
||||
{
|
||||
// TODO:
|
||||
//return SysCalls::GetSyscallName((u32)syscall);
|
||||
return "unknown syscall";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -302,13 +304,19 @@ void CPUThread::Task()
|
||||
}
|
||||
}
|
||||
|
||||
// fallthrough
|
||||
return "unknown function";
|
||||
}
|
||||
|
||||
case CPU_THREAD_SPU:
|
||||
case CPU_THREAD_RAW_SPU:
|
||||
default:
|
||||
{
|
||||
return "unknown syscall";
|
||||
if (!syscall)
|
||||
{
|
||||
return{};
|
||||
}
|
||||
|
||||
return "unknown function";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -2350,7 +2350,7 @@ void RSXThread::Task()
|
||||
m_last_flip_time = get_system_time() - 1000000;
|
||||
volatile bool is_vblank_stopped = false;
|
||||
|
||||
thread vblank("VBlank thread", [&]()
|
||||
thread_t vblank("VBlank thread", [&]()
|
||||
{
|
||||
const u64 start_time = get_system_time();
|
||||
|
||||
|
@ -82,7 +82,7 @@ void CallbackManager::Init()
|
||||
static_cast<PPUThread*>(m_cb_thread)->DoRun();
|
||||
}
|
||||
|
||||
thread cb_async_thread("CallbackManager::Async() thread", [this]()
|
||||
thread_t cb_async_thread("CallbackManager thread", [this]()
|
||||
{
|
||||
SetCurrentNamedThread(m_cb_thread);
|
||||
|
||||
@ -108,8 +108,6 @@ void CallbackManager::Init()
|
||||
m_cb_thread->WaitForAnySignal();
|
||||
}
|
||||
});
|
||||
|
||||
cb_async_thread.detach();
|
||||
}
|
||||
|
||||
void CallbackManager::Clear()
|
||||
|
@ -224,7 +224,7 @@ u32 adecOpen(AudioDecoder* adec_ptr)
|
||||
adec.id = adec_id;
|
||||
|
||||
adec.adecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback");
|
||||
adec.adecCb->SetName(fmt::format("AudioDecoder[%d] Callback", adec_id));
|
||||
adec.adecCb->SetEntry(0);
|
||||
adec.adecCb->SetPrio(1001);
|
||||
adec.adecCb->SetStackSize(0x10000);
|
||||
@ -232,11 +232,9 @@ u32 adecOpen(AudioDecoder* adec_ptr)
|
||||
adec.adecCb->InitRegs();
|
||||
adec.adecCb->DoRun();
|
||||
|
||||
thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [adec_ptr, sptr]()
|
||||
thread_t t(fmt::format("AudioDecoder[%d] Thread", adec_id), [adec_ptr, sptr]()
|
||||
{
|
||||
AudioDecoder& adec = *adec_ptr;
|
||||
cellAdec->Notice("Audio Decoder thread started");
|
||||
|
||||
AdecTask& task = adec.task;
|
||||
|
||||
while (true)
|
||||
@ -471,18 +469,15 @@ u32 adecOpen(AudioDecoder* adec_ptr)
|
||||
|
||||
default:
|
||||
{
|
||||
ADEC_ERROR("Audio Decoder thread error: unknown task(%d)", task.type);
|
||||
ADEC_ERROR("AudioDecoder thread error: unknown task(%d)", task.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adec.is_finished = true;
|
||||
if (adec.is_closed) cellAdec->Notice("Audio Decoder thread ended");
|
||||
if (Emu.IsStopped()) cellAdec->Warning("Audio Decoder thread aborted");
|
||||
if (Emu.IsStopped()) cellAdec->Warning("AudioDecoder thread aborted");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
||||
return adec_id;
|
||||
}
|
||||
|
||||
|
@ -11,145 +11,147 @@
|
||||
#include "Emu/Event.h"
|
||||
#include "Emu/Audio/AudioManager.h"
|
||||
#include "Emu/Audio/AudioDumper.h"
|
||||
#include "Emu/Audio/cellAudio.h"
|
||||
|
||||
#include "cellAudio.h"
|
||||
|
||||
Module *cellAudio = nullptr;
|
||||
|
||||
static std::mutex audioMutex;
|
||||
AudioConfig g_audio;
|
||||
|
||||
AudioConfig m_config;
|
||||
|
||||
static const bool g_is_u16 = Ini.AudioConvertToU16.GetValue();
|
||||
|
||||
// libaudio Functions
|
||||
|
||||
#define BUFFER_NUM 32
|
||||
#define BUFFER_SIZE 256
|
||||
int cellAudioInit()
|
||||
{
|
||||
cellAudio->Warning("cellAudioInit()");
|
||||
|
||||
if (m_config.m_is_audio_initialized)
|
||||
if (!g_audio.state.compare_and_swap_test(AUDIO_STATE_NOT_INITIALIZED, AUDIO_STATE_INITIALIZED))
|
||||
{
|
||||
return CELL_AUDIO_ERROR_ALREADY_INIT;
|
||||
}
|
||||
|
||||
m_config.m_is_audio_initialized = true;
|
||||
m_config.start_time = 0;
|
||||
m_config.counter = 0;
|
||||
|
||||
// alloc memory
|
||||
m_config.m_buffer = (u32)Memory.Alloc(128 * 1024 * m_config.AUDIO_PORT_COUNT, 1024);
|
||||
memset(vm::get_ptr<void>(m_config.m_buffer), 0, 128 * 1024 * m_config.AUDIO_PORT_COUNT);
|
||||
m_config.m_indexes = (u32)Memory.Alloc(sizeof(u64) * m_config.AUDIO_PORT_COUNT, 16);
|
||||
memset(vm::get_ptr<void>(m_config.m_indexes), 0, sizeof(u64) * m_config.AUDIO_PORT_COUNT);
|
||||
|
||||
thread t("Audio Thread", []()
|
||||
for (auto& port : g_audio.ports)
|
||||
{
|
||||
AudioDumper m_dump(8); // WAV file header (8 ch)
|
||||
|
||||
bool do_dump = Ini.AudioDumpToFile.GetValue();
|
||||
|
||||
if (do_dump && !m_dump.Init())
|
||||
{
|
||||
cellAudio->Error("cellAudioInit(): AudioDumper::Init() failed");
|
||||
return;
|
||||
port.state.write_relaxed(AUDIO_PORT_STATE_NOT_OPENED);
|
||||
}
|
||||
|
||||
cellAudio->Notice("Audio thread started");
|
||||
g_audio.start_time = 0;
|
||||
g_audio.counter = 0;
|
||||
g_audio.keys.clear();
|
||||
|
||||
if (Ini.AudioDumpToFile.GetValue())
|
||||
m_dump.WriteHeader();
|
||||
// alloc memory (only once until the emulator is stopped)
|
||||
g_audio.buffer = g_audio.buffer ? g_audio.buffer : vm::cast(Memory.MainMem.AllocAlign(128 * 1024 * AUDIO_PORT_COUNT, 4096));
|
||||
g_audio.indexes = g_audio.indexes ? g_audio.indexes : vm::cast(Memory.MainMem.AllocAlign(sizeof(u64) * AUDIO_PORT_COUNT, __alignof(u64)));
|
||||
|
||||
// clear memory
|
||||
memset(vm::get_ptr<void>(g_audio.buffer), 0, 128 * 1024 * AUDIO_PORT_COUNT);
|
||||
memset(vm::get_ptr<void>(g_audio.indexes), 0, sizeof(u64) * AUDIO_PORT_COUNT);
|
||||
|
||||
g_audio.audio_thread.start([]()
|
||||
{
|
||||
const bool do_dump = Ini.AudioDumpToFile.GetValue();
|
||||
|
||||
AudioDumper m_dump;
|
||||
if (do_dump && !m_dump.Init(8)) // Init AudioDumper for 8 channels
|
||||
{
|
||||
cellAudio->Error("AudioDumper::Init() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
float buf2ch[2 * BUFFER_SIZE]; // intermediate buffer for 2 channels
|
||||
float buf8ch[8 * BUFFER_SIZE]; // intermediate buffer for 8 channels
|
||||
|
||||
uint oal_buffer_offset = 0;
|
||||
const uint oal_buffer_size = 2 * BUFFER_SIZE;
|
||||
static const size_t out_buffer_size = 2 * BUFFER_SIZE;
|
||||
|
||||
std::unique_ptr<s16[]> oal_buffer[BUFFER_NUM];
|
||||
std::unique_ptr<float[]> oal_buffer_float[BUFFER_NUM];
|
||||
std::unique_ptr<float[]> out_buffer[BUFFER_NUM];
|
||||
|
||||
for (u32 i = 0; i < BUFFER_NUM; i++)
|
||||
{
|
||||
oal_buffer[i] = std::unique_ptr<s16[]>(new s16[oal_buffer_size] {} );
|
||||
oal_buffer_float[i] = std::unique_ptr<float[]>(new float[oal_buffer_size] {} );
|
||||
out_buffer[i].reset(new float[2 * BUFFER_SIZE] {});
|
||||
}
|
||||
|
||||
squeue_t<s16*, 31> queue;
|
||||
squeue_t<float*, 31> queue_float;
|
||||
squeue_t<float*, 31> out_queue;
|
||||
|
||||
std::vector<u64> keys;
|
||||
|
||||
g_audio.start_time = get_system_time();
|
||||
|
||||
thread_t iat("Internal Audio Thread", [&out_queue]()
|
||||
{
|
||||
const bool use_u16 = Ini.AudioConvertToU16.GetValue();
|
||||
|
||||
Emu.GetAudioManager().GetAudioOut().Init();
|
||||
|
||||
// Note: What if the ini value changes?
|
||||
if (g_is_u16)
|
||||
Emu.GetAudioManager().GetAudioOut().Open(oal_buffer[0].get(), oal_buffer_size * sizeof(s16));
|
||||
bool opened = false;
|
||||
|
||||
while (g_audio.state.read_relaxed() == AUDIO_STATE_INITIALIZED && !Emu.IsStopped())
|
||||
{
|
||||
float* buffer;
|
||||
if (out_queue.pop(buffer))
|
||||
{
|
||||
if (use_u16)
|
||||
{
|
||||
// convert the data from float to u16 with clipping:
|
||||
// 2x MULPS
|
||||
// 2x MAXPS (optional)
|
||||
// 2x MINPS (optional)
|
||||
// 2x CVTPS2DQ (converts float to s32)
|
||||
// PACKSSDW (converts s32 to s16 with signed saturation)
|
||||
|
||||
u16 buf_u16[out_buffer_size];
|
||||
for (size_t i = 0; i < out_buffer_size; i += 8)
|
||||
{
|
||||
static const __m128 float2u16 = { 0x8000, 0x8000, 0x8000, 0x8000 };
|
||||
(__m128i&)(buf_u16[i]) = _mm_packs_epi32(
|
||||
_mm_cvtps_epi32(_mm_mul_ps((__m128&)(buffer[i]), float2u16)),
|
||||
_mm_cvtps_epi32(_mm_mul_ps((__m128&)(buffer[i + 4]), float2u16)));
|
||||
}
|
||||
|
||||
if (!opened)
|
||||
{
|
||||
Emu.GetAudioManager().GetAudioOut().Open(buf_u16, out_buffer_size * sizeof(u16));
|
||||
opened = true;
|
||||
}
|
||||
else
|
||||
Emu.GetAudioManager().GetAudioOut().Open(oal_buffer_float[0].get(), oal_buffer_size * sizeof(float));
|
||||
|
||||
|
||||
m_config.start_time = get_system_time();
|
||||
|
||||
volatile bool internal_finished = false;
|
||||
|
||||
thread iat("Internal Audio Thread", [oal_buffer_size, &queue, &queue_float, &internal_finished]()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
s16* oal_buffer = nullptr;
|
||||
float* oal_buffer_float = nullptr;
|
||||
|
||||
if (g_is_u16)
|
||||
queue.pop(oal_buffer);
|
||||
else
|
||||
queue_float.pop(oal_buffer_float);
|
||||
|
||||
if (g_is_u16)
|
||||
{
|
||||
if (oal_buffer)
|
||||
{
|
||||
Emu.GetAudioManager().GetAudioOut().AddData(oal_buffer, oal_buffer_size * sizeof(s16));
|
||||
continue;
|
||||
Emu.GetAudioManager().GetAudioOut().AddData(buf_u16, out_buffer_size * sizeof(u16));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oal_buffer_float)
|
||||
if (!opened)
|
||||
{
|
||||
Emu.GetAudioManager().GetAudioOut().AddData(oal_buffer_float, oal_buffer_size * sizeof(float));
|
||||
continue;
|
||||
Emu.GetAudioManager().GetAudioOut().Open(buffer, out_buffer_size * sizeof(float));
|
||||
opened = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Emu.GetAudioManager().GetAudioOut().AddData(buffer, out_buffer_size * sizeof(float));
|
||||
}
|
||||
}
|
||||
internal_finished = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Emu.GetAudioManager().GetAudioOut().Quit();
|
||||
});
|
||||
iat.detach();
|
||||
|
||||
while (m_config.m_is_audio_initialized)
|
||||
while (g_audio.state.read_relaxed() == AUDIO_STATE_INITIALIZED && !Emu.IsStopped())
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
cellAudio->Warning("Audio thread aborted");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
const u64 stamp0 = get_system_time();
|
||||
|
||||
// TODO: send beforemix event (in ~2,6 ms before mixing)
|
||||
|
||||
// precise time of sleeping: 5,(3) ms (or 256/48000 sec)
|
||||
if (m_config.counter * 256000000 / 48000 >= stamp0 - m_config.start_time)
|
||||
if (g_audio.counter * 256000000 / 48000 >= stamp0 - g_audio.start_time)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
m_config.counter++;
|
||||
g_audio.counter++;
|
||||
|
||||
const u32 oal_pos = m_config.counter % BUFFER_NUM;
|
||||
const u32 out_pos = g_audio.counter % BUFFER_NUM;
|
||||
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
@ -159,15 +161,13 @@ int cellAudioInit()
|
||||
bool first_mix = true;
|
||||
|
||||
// mixing:
|
||||
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
||||
for (auto& port : g_audio.ports)
|
||||
{
|
||||
if (!m_config.m_ports[i].m_is_audio_port_started) continue;
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[i];
|
||||
if (port.state.read_relaxed() != AUDIO_PORT_STATE_STARTED) continue;
|
||||
|
||||
const u32 block_size = port.channel * 256;
|
||||
const u32 position = port.tag % port.block; // old value
|
||||
const u32 buf_addr = m_config.m_buffer + (i * 128 * 1024) + (position * block_size * sizeof(float));
|
||||
const u32 buf_addr = port.addr + position * block_size * sizeof(float);
|
||||
|
||||
auto buf = vm::get_ptr<be_t<float>>(buf_addr);
|
||||
|
||||
@ -327,29 +327,12 @@ int cellAudioInit()
|
||||
memset(buf, 0, block_size * sizeof(float));
|
||||
}
|
||||
|
||||
// convert the data from float to u16 with clipping:
|
||||
|
||||
if (!first_mix)
|
||||
{
|
||||
// 2x MULPS
|
||||
// 2x MAXPS (optional)
|
||||
// 2x MINPS (optional)
|
||||
// 2x CVTPS2DQ (converts float to s32)
|
||||
// PACKSSDW (converts s32 to s16 with signed saturation)
|
||||
|
||||
if (g_is_u16)
|
||||
{
|
||||
for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i += 8)
|
||||
{
|
||||
static const __m128 float2u16 = { 0x8000, 0x8000, 0x8000, 0x8000 };
|
||||
(__m128i&)(oal_buffer[oal_pos][oal_buffer_offset + i]) = _mm_packs_epi32(
|
||||
_mm_cvtps_epi32(_mm_mul_ps((__m128&)(buf2ch[i]), float2u16)),
|
||||
_mm_cvtps_epi32(_mm_mul_ps((__m128&)(buf2ch[i + 4]), float2u16)));
|
||||
}
|
||||
}
|
||||
else
|
||||
for (u32 i = 0; i < (sizeof(buf2ch) / sizeof(float)); i++)
|
||||
{
|
||||
oal_buffer_float[oal_pos][oal_buffer_offset + i] = buf2ch[i];
|
||||
out_buffer[out_pos][i] = buf2ch[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,41 +340,32 @@ int cellAudioInit()
|
||||
|
||||
if (first_mix)
|
||||
{
|
||||
if (g_is_u16) memset(&oal_buffer[oal_pos][0], 0, oal_buffer_size * sizeof(s16));
|
||||
else memset(&oal_buffer_float[oal_pos][0], 0, oal_buffer_size * sizeof(float));
|
||||
memset(out_buffer[out_pos].get(), 0, out_buffer_size * sizeof(float));
|
||||
}
|
||||
oal_buffer_offset += sizeof(buf2ch) / sizeof(float);
|
||||
|
||||
if(oal_buffer_offset >= oal_buffer_size)
|
||||
{
|
||||
if (g_is_u16)
|
||||
queue.push(&oal_buffer[oal_pos][0]);
|
||||
|
||||
queue_float.push(&oal_buffer_float[oal_pos][0]);
|
||||
oal_buffer_offset = 0;
|
||||
}
|
||||
out_queue.push(out_buffer[out_pos].get());
|
||||
|
||||
//const u64 stamp2 = get_system_time();
|
||||
|
||||
// send aftermix event (normal audio event)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(audioMutex);
|
||||
std::lock_guard<std::mutex> lock(g_audio.mutex);
|
||||
// update indexes:
|
||||
auto indexes = vm::ptr<u64>::make(m_config.m_indexes);
|
||||
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
||||
auto indexes = vm::ptr<u64>::make(g_audio.indexes);
|
||||
for (u32 i = 0; i < AUDIO_PORT_COUNT; i++)
|
||||
{
|
||||
if (!m_config.m_ports[i].m_is_audio_port_started) continue;
|
||||
AudioPortConfig& port = g_audio.ports[i];
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[i];
|
||||
if (port.state.read_relaxed() != AUDIO_PORT_STATE_STARTED) continue;
|
||||
|
||||
u32 position = port.tag % port.block; // old value
|
||||
port.counter = m_config.counter;
|
||||
port.counter = g_audio.counter;
|
||||
port.tag++; // absolute index of block that will be read
|
||||
indexes[i] = (position + 1) % port.block; // write new value
|
||||
}
|
||||
// load keys:
|
||||
keys.resize(m_config.m_keys.size());
|
||||
memcpy(keys.data(), m_config.m_keys.data(), sizeof(u64) * keys.size());
|
||||
keys.resize(g_audio.keys.size());
|
||||
memcpy(keys.data(), g_audio.keys.data(), sizeof(u64) * keys.size());
|
||||
}
|
||||
for (u32 i = 0; i < keys.size(); i++)
|
||||
{
|
||||
@ -407,65 +381,31 @@ int cellAudioInit()
|
||||
{
|
||||
if (m_dump.WriteData(&buf8ch, sizeof(buf8ch)) != sizeof(buf8ch)) // write file data
|
||||
{
|
||||
cellAudio->Error("cellAudioInit(): AudioDumper::WriteData() failed");
|
||||
goto abort;
|
||||
cellAudio->Error("AudioDumper::WriteData() failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (m_dump.GetCh() == 2)
|
||||
{
|
||||
if (m_dump.WriteData(&buf2ch, sizeof(buf2ch)) != sizeof(buf2ch)) // write file data
|
||||
{
|
||||
cellAudio->Error("cellAudioInit(): AudioDumper::WriteData() failed");
|
||||
goto abort;
|
||||
cellAudio->Error("AudioDumper::WriteData() failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cellAudio->Error("cellAudioInit(): unknown AudioDumper::GetCh() value (%d)", m_dump.GetCh());
|
||||
goto abort;
|
||||
cellAudio->Error("AudioDumper::GetCh() returned unknown value (%d)", m_dump.GetCh());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//LOG_NOTICE(HLE, "Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)",
|
||||
//stamp0 - m_config.start_time, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
|
||||
}
|
||||
cellAudio->Notice("Audio thread ended");
|
||||
abort:
|
||||
queue.push(nullptr);
|
||||
queue_float.push(nullptr);
|
||||
|
||||
if(do_dump)
|
||||
m_dump.Finalize();
|
||||
|
||||
m_config.m_is_audio_initialized = false;
|
||||
|
||||
m_config.m_keys.clear();
|
||||
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
||||
{
|
||||
AudioPortConfig& port = m_config.m_ports[i];
|
||||
port.m_is_audio_port_opened = false;
|
||||
port.m_is_audio_port_started = false;
|
||||
}
|
||||
m_config.m_port_in_use = 0;
|
||||
|
||||
while (!internal_finished)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
m_config.m_is_audio_finalized = true;
|
||||
iat.join();
|
||||
});
|
||||
t.detach();
|
||||
|
||||
while (!m_config.start_time) // waiting for initialization
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
cellAudio->Warning("cellAudioInit() aborted");
|
||||
return CELL_OK;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -474,26 +414,13 @@ int cellAudioQuit()
|
||||
{
|
||||
cellAudio->Warning("cellAudioQuit()");
|
||||
|
||||
if (!m_config.m_is_audio_initialized)
|
||||
if (!g_audio.state.compare_and_swap_test(AUDIO_STATE_INITIALIZED, AUDIO_STATE_FINALIZED))
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
m_config.m_is_audio_initialized = false;
|
||||
|
||||
while (!m_config.m_is_audio_finalized)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
cellAudio->Warning("cellAudioQuit(): aborted");
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
Memory.Free(m_config.m_buffer);
|
||||
Memory.Free(m_config.m_indexes);
|
||||
|
||||
g_audio.audio_thread.join();
|
||||
g_audio.state.exchange(AUDIO_STATE_NOT_INITIALIZED);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -506,22 +433,17 @@ int cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32> portN
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (m_config.m_port_in_use >= m_config.AUDIO_PORT_COUNT)
|
||||
for (u32 i = 0; i < AUDIO_PORT_COUNT; i++)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_FULL;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
||||
if (g_audio.ports[i].state.compare_and_swap_test(AUDIO_PORT_STATE_NOT_OPENED, AUDIO_PORT_STATE_OPENED))
|
||||
{
|
||||
if (!m_config.m_ports[i].m_is_audio_port_opened)
|
||||
{
|
||||
AudioPortConfig& port = m_config.m_ports[i];
|
||||
AudioPortConfig& port = g_audio.ports[i];
|
||||
|
||||
port.channel = (u8)audioParam->nChannel;
|
||||
port.block = (u8)audioParam->nBlock;
|
||||
port.attr = audioParam->attr;
|
||||
port.addr = m_config.m_buffer + (128 * 1024 * i);
|
||||
port.read_index_addr = m_config.m_indexes + (sizeof(u64) * i);
|
||||
port.addr = g_audio.buffer + (128 * 1024 * i);
|
||||
port.read_index_addr = g_audio.indexes + (sizeof(u64) * i);
|
||||
port.size = port.channel * port.block * 256 * sizeof(float);
|
||||
if (port.attr & CELL_AUDIO_PORTATTR_INITLEVEL)
|
||||
{
|
||||
@ -536,11 +458,7 @@ int cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32> portN
|
||||
cellAudio->Warning("*** audio port opened(nChannel=%d, nBlock=%d, attr=0x%llx, level=%f): port = %d",
|
||||
port.channel, port.block, port.attr, port.level, i);
|
||||
|
||||
port.m_is_audio_port_opened = true;
|
||||
port.m_is_audio_port_started = false;
|
||||
port.tag = 0;
|
||||
|
||||
m_config.m_port_in_use++;
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
@ -552,25 +470,20 @@ int cellAudioGetPortConfig(u32 portNum, vm::ptr<CellAudioPortConfig> portConfig)
|
||||
{
|
||||
cellAudio->Warning("cellAudioGetPortConfig(portNum=0x%x, portConfig_addr=0x%x)", portNum, portConfig.addr());
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_opened)
|
||||
switch (auto state = g_audio.ports[portNum].state.read_sync())
|
||||
{
|
||||
portConfig->status = CELL_AUDIO_STATUS_CLOSE;
|
||||
}
|
||||
else if (m_config.m_ports[portNum].m_is_audio_port_started)
|
||||
{
|
||||
portConfig->status = CELL_AUDIO_STATUS_RUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
portConfig->status = CELL_AUDIO_STATUS_READY;
|
||||
case AUDIO_PORT_STATE_NOT_OPENED: portConfig->status = CELL_AUDIO_STATUS_CLOSE; break;
|
||||
case AUDIO_PORT_STATE_OPENED: portConfig->status = CELL_AUDIO_STATUS_READY; break;
|
||||
case AUDIO_PORT_STATE_STARTED: portConfig->status = CELL_AUDIO_STATUS_RUN; break;
|
||||
default: throw fmt::format("cellAudioGetPortConfig(%d): invalid port state (0x%x)", portNum, state);
|
||||
}
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[portNum];
|
||||
AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
portConfig->nChannel = port.channel;
|
||||
portConfig->nBlock = port.block;
|
||||
@ -589,93 +502,80 @@ int cellAudioPortStart(u32 portNum)
|
||||
{
|
||||
cellAudio->Warning("cellAudioPortStart(portNum=0x%x)", portNum);
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_opened)
|
||||
switch (auto state = g_audio.ports[portNum].state.compare_and_swap(AUDIO_PORT_STATE_OPENED, AUDIO_PORT_STATE_STARTED))
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_OPEN;
|
||||
case AUDIO_PORT_STATE_NOT_OPENED: return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
case AUDIO_PORT_STATE_STARTED: return CELL_AUDIO_ERROR_PORT_ALREADY_RUN;
|
||||
case AUDIO_PORT_STATE_OPENED: return CELL_OK;
|
||||
default: throw fmt::format("cellAudioPortStart(%d): invalid port state (0x%x)", portNum, state);
|
||||
}
|
||||
|
||||
if (m_config.m_ports[portNum].m_is_audio_port_started)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_ALREADY_RUN;
|
||||
}
|
||||
|
||||
m_config.m_ports[portNum].m_is_audio_port_started = true;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellAudioPortClose(u32 portNum)
|
||||
{
|
||||
cellAudio->Warning("cellAudioPortClose(portNum=0x%x)", portNum);
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_opened)
|
||||
switch (auto state = g_audio.ports[portNum].state.exchange(AUDIO_PORT_STATE_NOT_OPENED))
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
case AUDIO_PORT_STATE_NOT_OPENED: return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
case AUDIO_PORT_STATE_STARTED: return CELL_OK;
|
||||
case AUDIO_PORT_STATE_OPENED: return CELL_OK;
|
||||
default: throw fmt::format("cellAudioPortClose(%d): invalid port state (0x%x)", portNum, state);
|
||||
}
|
||||
|
||||
m_config.m_ports[portNum].m_is_audio_port_started = false;
|
||||
m_config.m_ports[portNum].m_is_audio_port_opened = false;
|
||||
m_config.m_port_in_use--;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellAudioPortStop(u32 portNum)
|
||||
{
|
||||
cellAudio->Warning("cellAudioPortStop(portNum=0x%x)",portNum);
|
||||
cellAudio->Warning("cellAudioPortStop(portNum=0x%x)", portNum);
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_opened)
|
||||
switch (auto state = g_audio.ports[portNum].state.compare_and_swap(AUDIO_PORT_STATE_STARTED, AUDIO_PORT_STATE_OPENED))
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
case AUDIO_PORT_STATE_NOT_OPENED: return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
case AUDIO_PORT_STATE_STARTED: return CELL_OK;
|
||||
case AUDIO_PORT_STATE_OPENED: return CELL_AUDIO_ERROR_PORT_OPEN;
|
||||
default: throw fmt::format("cellAudioPortStop(%d): invalid port state (0x%x)", portNum, state);
|
||||
}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_started)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_RUN;
|
||||
}
|
||||
|
||||
m_config.m_ports[portNum].m_is_audio_port_started = false;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr<u64> stamp)
|
||||
{
|
||||
cellAudio->Log("cellAudioGetPortTimestamp(portNum=0x%x, tag=0x%llx, stamp_addr=0x%x)", portNum, tag, stamp.addr());
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_opened)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
}
|
||||
//if (!g_audio.ports[portNum].is_audio_port_opened)
|
||||
//{
|
||||
// return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
//}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_started)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_RUN;
|
||||
}
|
||||
//if (!g_audio.ports[portNum].is_audio_port_started)
|
||||
//{
|
||||
// return CELL_AUDIO_ERROR_PORT_NOT_RUN;
|
||||
//}
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[portNum];
|
||||
AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
std::lock_guard<std::mutex> lock(audioMutex);
|
||||
std::lock_guard<std::mutex> lock(g_audio.mutex);
|
||||
|
||||
*stamp = m_config.start_time + (port.counter + (tag - port.tag)) * 256000000 / 48000;
|
||||
*stamp = g_audio.start_time + (port.counter + (tag - port.tag)) * 256000000 / 48000;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -684,22 +584,22 @@ int cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr<u64> tag)
|
||||
{
|
||||
cellAudio->Log("cellAudioGetPortBlockTag(portNum=0x%x, blockNo=0x%llx, tag_addr=0x%x)", portNum, blockNo, tag.addr());
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_opened)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
}
|
||||
//if (!g_audio.ports[portNum].is_audio_port_opened)
|
||||
//{
|
||||
// return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
//}
|
||||
|
||||
if (!m_config.m_ports[portNum].m_is_audio_port_started)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_RUN;
|
||||
}
|
||||
//if (!g_audio.ports[portNum].is_audio_port_started)
|
||||
//{
|
||||
// return CELL_AUDIO_ERROR_PORT_NOT_RUN;
|
||||
//}
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[portNum];
|
||||
AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
if (blockNo >= port.block)
|
||||
{
|
||||
@ -707,17 +607,17 @@ int cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr<u64> tag)
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(audioMutex);
|
||||
std::lock_guard<std::mutex> lock(g_audio.mutex);
|
||||
|
||||
u64 tag_base = port.tag;
|
||||
if (tag_base % port.block > blockNo)
|
||||
{
|
||||
tag_base &= ~(port.block-1);
|
||||
tag_base &= ~(port.block - 1);
|
||||
tag_base += port.block;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag_base &= ~(port.block-1);
|
||||
tag_base &= ~(port.block - 1);
|
||||
}
|
||||
*tag = tag_base + blockNo;
|
||||
|
||||
@ -728,24 +628,24 @@ int cellAudioSetPortLevel(u32 portNum, float level)
|
||||
{
|
||||
cellAudio->Todo("cellAudioSetPortLevel(portNum=0x%x, level=%f)", portNum, level);
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[portNum];
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (!port.m_is_audio_port_opened)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
}
|
||||
AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
if (!port.m_is_audio_port_started)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_RUN;
|
||||
}
|
||||
//if (!port.is_audio_port_opened)
|
||||
//{
|
||||
// return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
//}
|
||||
|
||||
std::lock_guard<std::mutex> lock(audioMutex);
|
||||
//if (!port.is_audio_port_started)
|
||||
//{
|
||||
// return CELL_AUDIO_ERROR_PORT_NOT_RUN;
|
||||
//}
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_audio.mutex);
|
||||
|
||||
port.level = level; // TODO
|
||||
|
||||
@ -757,7 +657,7 @@ int cellAudioCreateNotifyEventQueue(vm::ptr<u32> id, vm::ptr<u64> key)
|
||||
{
|
||||
cellAudio->Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.addr(), key.addr());
|
||||
|
||||
std::lock_guard<std::mutex> lock(audioMutex);
|
||||
std::lock_guard<std::mutex> lock(g_audio.mutex);
|
||||
|
||||
u64 event_key = 0;
|
||||
while (Emu.GetEventManager().CheckKey((event_key << 48) | 0x80004d494f323221))
|
||||
@ -790,16 +690,16 @@ int cellAudioSetNotifyEventQueue(u64 key)
|
||||
{
|
||||
cellAudio->Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);
|
||||
|
||||
std::lock_guard<std::mutex> lock(audioMutex);
|
||||
std::lock_guard<std::mutex> lock(g_audio.mutex);
|
||||
|
||||
for (u32 i = 0; i < m_config.m_keys.size(); i++) // check for duplicates
|
||||
for (u32 i = 0; i < g_audio.keys.size(); i++) // check for duplicates
|
||||
{
|
||||
if (m_config.m_keys[i] == key)
|
||||
if (g_audio.keys[i] == key)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
}
|
||||
m_config.m_keys.push_back(key);
|
||||
g_audio.keys.push_back(key);
|
||||
|
||||
/*EventQueue* eq;
|
||||
if (!Emu.GetEventManager().GetEventQueue(key, eq))
|
||||
@ -822,14 +722,14 @@ int cellAudioRemoveNotifyEventQueue(u64 key)
|
||||
{
|
||||
cellAudio->Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key);
|
||||
|
||||
std::lock_guard<std::mutex> lock(audioMutex);
|
||||
std::lock_guard<std::mutex> lock(g_audio.mutex);
|
||||
|
||||
bool found = false;
|
||||
for (u32 i = 0; i < m_config.m_keys.size(); i++)
|
||||
for (u32 i = 0; i < g_audio.keys.size(); i++)
|
||||
{
|
||||
if (m_config.m_keys[i] == key)
|
||||
if (g_audio.keys[i] == key)
|
||||
{
|
||||
m_config.m_keys.erase(m_config.m_keys.begin() + i);
|
||||
g_audio.keys.erase(g_audio.keys.begin() + i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@ -860,14 +760,14 @@ int cellAudioRemoveNotifyEventQueueEx(u64 key, u32 iFlags)
|
||||
|
||||
s32 cellAudioAddData(u32 portNum, vm::ptr<float> src, u32 samples, float volume)
|
||||
{
|
||||
cellAudio->Log("cellAudioAddData(portNum=%d, src_addr=0x%x, samples=%d, volume=%f)", portNum, src.addr(), samples, volume);
|
||||
cellAudio->Log("cellAudioAddData(portNum=%d, src=0x%x, samples=%d, volume=%f)", portNum, src, samples, volume);
|
||||
|
||||
if (!m_config.m_is_audio_initialized)
|
||||
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT || !src || src.addr() % 4)
|
||||
if (portNum >= AUDIO_PORT_COUNT || !src || src.addr() % 4)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
@ -879,7 +779,7 @@ s32 cellAudioAddData(u32 portNum, vm::ptr<float> src, u32 samples, float volume)
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const AudioPortConfig& port = m_config.m_ports[portNum];
|
||||
const AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
const auto dst = vm::ptr<float>::make(port.addr + (port.tag % port.block) * port.channel * 256 * sizeof(float));
|
||||
|
||||
@ -893,19 +793,14 @@ s32 cellAudioAddData(u32 portNum, vm::ptr<float> src, u32 samples, float volume)
|
||||
|
||||
s32 cellAudioAdd2chData(u32 portNum, vm::ptr<float> src, u32 samples, float volume)
|
||||
{
|
||||
cellAudio->Log("cellAudioAdd2chData(portNum=%d, src_addr=0x%x, samples=%d, volume=%f)", portNum, src.addr(), samples, volume);
|
||||
cellAudio->Log("cellAudioAdd2chData(portNum=%d, src=0x%x, samples=%d, volume=%f)", portNum, src, samples, volume);
|
||||
|
||||
if (!m_config.m_is_audio_initialized)
|
||||
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT || !src || src.addr() % 4)
|
||||
if (portNum >= AUDIO_PORT_COUNT || !src || src.addr() % 4)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
@ -917,7 +812,7 @@ s32 cellAudioAdd2chData(u32 portNum, vm::ptr<float> src, u32 samples, float volu
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const AudioPortConfig& port = m_config.m_ports[portNum];
|
||||
const AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
const auto dst = vm::ptr<float>::make(port.addr + (port.tag % port.block) * port.channel * 256 * sizeof(float));
|
||||
|
||||
@ -961,24 +856,19 @@ s32 cellAudioAdd2chData(u32 portNum, vm::ptr<float> src, u32 samples, float volu
|
||||
|
||||
s32 cellAudioAdd6chData(u32 portNum, vm::ptr<float> src, float volume)
|
||||
{
|
||||
cellAudio->Log("cellAudioAdd6chData(portNum=%d, src_addr=0x%x, volume=%f)", portNum, src.addr(), volume);
|
||||
cellAudio->Log("cellAudioAdd6chData(portNum=%d, src=0x%x, volume=%f)", portNum, src, volume);
|
||||
|
||||
if (!m_config.m_is_audio_initialized)
|
||||
if (g_audio.state.read_relaxed() != AUDIO_STATE_INITIALIZED)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT)
|
||||
if (portNum >= AUDIO_PORT_COUNT || !src || src.addr() % 4)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (portNum >= m_config.AUDIO_PORT_COUNT || !src || src.addr() % 4)
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const AudioPortConfig& port = m_config.m_ports[portNum];
|
||||
const AudioPortConfig& port = g_audio.ports[portNum];
|
||||
|
||||
const auto dst = vm::ptr<float>::make(port.addr + (port.tag % port.block) * port.channel * 256 * sizeof(float));
|
||||
|
||||
@ -1036,6 +926,10 @@ void cellAudio_init(Module *pxThis)
|
||||
{
|
||||
cellAudio = pxThis;
|
||||
|
||||
g_audio.state.write_relaxed(AUDIO_STATE_NOT_INITIALIZED);
|
||||
g_audio.buffer = 0;
|
||||
g_audio.indexes = 0;
|
||||
|
||||
REG_FUNC(cellAudio, cellAudioInit);
|
||||
REG_FUNC(cellAudio, cellAudioPortClose);
|
||||
REG_FUNC(cellAudio, cellAudioPortStop);
|
||||
@ -1060,3 +954,8 @@ void cellAudio_init(Module *pxThis)
|
||||
REG_FUNC(cellAudio, cellAudioSetPersonalDevice);
|
||||
REG_FUNC(cellAudio, cellAudioUnsetPersonalDevice);
|
||||
}
|
||||
|
||||
void cellAudio_load()
|
||||
{
|
||||
// never called :(
|
||||
}
|
||||
|
@ -72,10 +72,32 @@ struct CellAudioPortConfig
|
||||
be_t<u32> portAddr;
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
BUFFER_NUM = 32,
|
||||
BUFFER_SIZE = 256,
|
||||
AUDIO_PORT_COUNT = 8,
|
||||
};
|
||||
|
||||
enum AudioState : u32
|
||||
{
|
||||
AUDIO_STATE_NOT_INITIALIZED,
|
||||
AUDIO_STATE_INITIALIZED,
|
||||
AUDIO_STATE_FINALIZED,
|
||||
};
|
||||
|
||||
enum AudioPortState : u32
|
||||
{
|
||||
AUDIO_PORT_STATE_NOT_OPENED,
|
||||
AUDIO_PORT_STATE_OPENED,
|
||||
AUDIO_PORT_STATE_STARTED,
|
||||
};
|
||||
|
||||
struct AudioPortConfig
|
||||
{
|
||||
bool m_is_audio_port_opened;
|
||||
bool m_is_audio_port_started;
|
||||
std::mutex mutex;
|
||||
atomic_le_t<AudioPortState> state;
|
||||
|
||||
u8 channel;
|
||||
u8 block;
|
||||
float level;
|
||||
@ -89,34 +111,20 @@ struct AudioPortConfig
|
||||
|
||||
struct AudioConfig //custom structure
|
||||
{
|
||||
enum
|
||||
{
|
||||
AUDIO_PORT_COUNT = 8,
|
||||
};
|
||||
AudioPortConfig m_ports[AUDIO_PORT_COUNT];
|
||||
u32 m_buffer; // 1 MB memory for audio ports
|
||||
u32 m_indexes; // current block indexes and other info
|
||||
bool m_is_audio_initialized;
|
||||
bool m_is_audio_finalized;
|
||||
u32 m_port_in_use;
|
||||
std::mutex mutex;
|
||||
atomic_le_t<AudioState> state;
|
||||
thread_t audio_thread;
|
||||
|
||||
AudioPortConfig ports[AUDIO_PORT_COUNT];
|
||||
u32 buffer; // 1 MB memory for audio ports
|
||||
u32 indexes; // current block indexes and other info
|
||||
u64 counter;
|
||||
u64 start_time;
|
||||
std::vector<u64> m_keys;
|
||||
std::vector<u64> keys;
|
||||
|
||||
AudioConfig()
|
||||
: m_is_audio_initialized(false)
|
||||
, m_is_audio_finalized(false)
|
||||
, m_port_in_use(0)
|
||||
, counter(0)
|
||||
AudioConfig() : audio_thread("Audio Thread")
|
||||
{
|
||||
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);
|
||||
m_port_in_use = 0;
|
||||
}
|
||||
};
|
||||
|
||||
extern AudioConfig m_config;
|
||||
extern AudioConfig g_audio;
|
@ -306,7 +306,7 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
|
||||
dmux.id = dmux_id;
|
||||
|
||||
dmux.dmuxCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback");
|
||||
dmux.dmuxCb->SetName(fmt::format("Demuxer[%d] Callback", dmux_id));
|
||||
dmux.dmuxCb->SetEntry(0);
|
||||
dmux.dmuxCb->SetPrio(1001);
|
||||
dmux.dmuxCb->SetStackSize(0x10000);
|
||||
@ -314,10 +314,9 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
|
||||
dmux.dmuxCb->InitRegs();
|
||||
dmux.dmuxCb->DoRun();
|
||||
|
||||
thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [dmux_ptr, sptr]()
|
||||
thread_t t(fmt::format("Demuxer[%d] Thread", dmux_id), [dmux_ptr, sptr]()
|
||||
{
|
||||
Demuxer& dmux = *dmux_ptr;
|
||||
cellDmux->Notice("Demuxer thread started (mem=0x%x, size=0x%x, cb_addr=0x%x, arg=0x%x)", dmux.memAddr, dmux.memSize, dmux.cbFunc.addr(), dmux.cbArg);
|
||||
|
||||
DemuxerTask task;
|
||||
DemuxerStream stream = {};
|
||||
@ -761,11 +760,8 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
|
||||
|
||||
dmux.is_finished = true;
|
||||
if (Emu.IsStopped()) cellDmux->Warning("Demuxer thread aborted");
|
||||
if (dmux.is_closed) cellDmux->Notice("Demuxer thread ended");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
||||
return dmux_id;
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
||||
|
||||
std::string msg = msgString.get_ptr();
|
||||
|
||||
thread t("MsgDialog thread", [type, msg, callback, userData, extParam]()
|
||||
thread_t t("MsgDialog Thread", [type, msg, callback, userData, extParam]()
|
||||
{
|
||||
switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE)
|
||||
{
|
||||
@ -186,7 +186,6 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
||||
g_msg_dialog_state = msgDialogNone;
|
||||
});
|
||||
});
|
||||
t.detach();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
vdec.id = vdec_id;
|
||||
|
||||
vdec.vdecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback");
|
||||
vdec.vdecCb->SetName(fmt::format("VideoDecoder[%d] Callback", vdec_id));
|
||||
vdec.vdecCb->SetEntry(0);
|
||||
vdec.vdecCb->SetPrio(1001);
|
||||
vdec.vdecCb->SetStackSize(0x10000);
|
||||
@ -222,11 +222,9 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
vdec.vdecCb->InitRegs();
|
||||
vdec.vdecCb->DoRun();
|
||||
|
||||
thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [vdec_ptr, sptr]()
|
||||
thread_t t(fmt::format("VideoDecoder[%d] Thread", vdec_id), [vdec_ptr, sptr]()
|
||||
{
|
||||
VideoDecoder& vdec = *vdec_ptr;
|
||||
cellVdec->Notice("Video Decoder thread started");
|
||||
|
||||
VdecTask& task = vdec.task;
|
||||
|
||||
while (true)
|
||||
@ -431,7 +429,15 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
{
|
||||
if (vdec.last_pts == -1)
|
||||
{
|
||||
vdec.last_pts = 0x8000; //av_frame_get_best_effort_timestamp(frame.data);
|
||||
u64 ts = av_frame_get_best_effort_timestamp(frame.data);
|
||||
if (ts != AV_NOPTS_VALUE)
|
||||
{
|
||||
vdec.last_pts = ts;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdec.last_pts = 0;
|
||||
}
|
||||
}
|
||||
else switch (vdec.frc_set)
|
||||
{
|
||||
@ -539,18 +545,15 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
|
||||
default:
|
||||
{
|
||||
VDEC_ERROR("Video Decoder thread error: unknown task(%d)", task.type);
|
||||
VDEC_ERROR("VideoDecoder thread error: unknown task(%d)", task.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdec.is_finished = true;
|
||||
if (Emu.IsStopped()) cellVdec->Warning("Video Decoder thread aborted");
|
||||
if (vdec.is_closed) cellVdec->Notice("Video Decoder thread ended");
|
||||
if (Emu.IsStopped()) cellVdec->Warning("VideoDecoder thread aborted");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
||||
return vdec_id;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "Emu/SysCalls/CB_FUNC.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Audio/cellAudio.h"
|
||||
#include "cellAudio.h"
|
||||
#include "libmixer.h"
|
||||
|
||||
Module *libmixer = nullptr;
|
||||
@ -298,9 +298,9 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
|
||||
surMixer = *config;
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
AudioPortConfig& port = g_audio.ports[SUR_PORT];
|
||||
|
||||
if (port.m_is_audio_port_opened)
|
||||
if (!port.state.compare_and_swap_test(AUDIO_PORT_STATE_NOT_OPENED, AUDIO_PORT_STATE_OPENED))
|
||||
{
|
||||
return CELL_LIBMIXER_ERROR_FULL;
|
||||
}
|
||||
@ -309,22 +309,19 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
port.block = 16;
|
||||
port.attr = 0;
|
||||
port.level = 1.0f;
|
||||
port.tag = 0;
|
||||
|
||||
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)",
|
||||
(u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8);
|
||||
|
||||
mixcount = 0;
|
||||
surMixerCb.set(0);
|
||||
|
||||
thread t("Surmixer Thread", []()
|
||||
libmixer->Warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)",
|
||||
(u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8);
|
||||
|
||||
thread_t t("Surmixer Thread", []()
|
||||
{
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
AudioPortConfig& port = g_audio.ports[SUR_PORT];
|
||||
|
||||
PPUThread& cb_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
cb_thread.SetName("Surmixer Callback Thread");
|
||||
@ -335,7 +332,7 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
cb_thread.InitRegs();
|
||||
cb_thread.DoRun();
|
||||
|
||||
while (port.m_is_audio_port_opened)
|
||||
while (port.state.read_relaxed() != AUDIO_PORT_STATE_NOT_OPENED)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
@ -349,7 +346,7 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (port.m_is_audio_port_started)
|
||||
if (port.state.read_relaxed() == AUDIO_PORT_STATE_STARTED)
|
||||
{
|
||||
//u64 stamp0 = get_system_time();
|
||||
|
||||
@ -440,7 +437,7 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
|
||||
//u64 stamp2 = get_system_time();
|
||||
|
||||
auto buf = vm::get_ptr<be_t<float>>(m_config.m_buffer + (128 * 1024 * SUR_PORT) + (mixcount % port.block) * port.channel * 256 * sizeof(float));
|
||||
auto buf = vm::get_ptr<be_t<float>>(g_audio.buffer + (128 * 1024 * SUR_PORT) + (mixcount % port.block) * port.channel * 256 * sizeof(float));
|
||||
|
||||
for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++)
|
||||
{
|
||||
@ -464,7 +461,6 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
Emu.GetCPU().RemoveThread(cb_thread.GetId());
|
||||
surMixerCb.set(0);
|
||||
});
|
||||
t.detach();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -515,12 +511,7 @@ int cellSurMixerStart()
|
||||
{
|
||||
libmixer->Warning("cellSurMixerStart()");
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
|
||||
if (port.m_is_audio_port_opened)
|
||||
{
|
||||
port.m_is_audio_port_started = true;
|
||||
}
|
||||
g_audio.ports[SUR_PORT].state.compare_and_swap(AUDIO_PORT_STATE_OPENED, AUDIO_PORT_STATE_STARTED);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -535,14 +526,7 @@ int cellSurMixerFinalize()
|
||||
{
|
||||
libmixer->Warning("cellSurMixerFinalize()");
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
|
||||
if (port.m_is_audio_port_opened)
|
||||
{
|
||||
port.m_is_audio_port_started = false;
|
||||
port.m_is_audio_port_opened = false;
|
||||
m_config.m_port_in_use--;
|
||||
}
|
||||
g_audio.ports[SUR_PORT].state.compare_and_swap(AUDIO_PORT_STATE_OPENED, AUDIO_PORT_STATE_NOT_OPENED);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -581,12 +565,7 @@ int cellSurMixerPause(u32 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;
|
||||
}
|
||||
g_audio.ports[SUR_PORT].state.compare_and_swap(AUDIO_PORT_STATE_STARTED, AUDIO_PORT_STATE_OPENED);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -603,7 +582,7 @@ int cellSurMixerGetTimestamp(u64 tag, vm::ptr<u64> stamp)
|
||||
{
|
||||
libmixer->Log("cellSurMixerGetTimestamp(tag=0x%llx, stamp_addr=0x%x)", tag, stamp.addr());
|
||||
|
||||
*stamp = m_config.start_time + (tag) * 256000000 / 48000; // ???
|
||||
*stamp = g_audio.start_time + (tag) * 256000000 / 48000; // ???
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -966,11 +966,7 @@ int cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<u32> id, vm::ptr<void(*)(vm::p
|
||||
const u32 xid = g_FsAioReadID++;
|
||||
*id = xid;
|
||||
|
||||
{
|
||||
thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func));
|
||||
t.detach();
|
||||
}
|
||||
|
||||
thread_t t("CellFsAio Reading Thread", std::bind(fsAioRead, fd, aio, xid, func));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -411,6 +411,7 @@
|
||||
<ClInclude Include="Emu\SysCalls\Modules.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAdec.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAtrac.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAudio.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellCamera.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellDmux.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellFiber.h" />
|
||||
|
@ -1279,5 +1279,8 @@
|
||||
<ClInclude Include="Emu\Audio\XAudio2\XAudio2Thread.h">
|
||||
<Filter>Emu\Audio\XAudio2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAudio.h">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user