From 4375b9dd2a4d947d325e832a3e83dbb110987cb3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 16 Feb 2014 19:23:58 +0400 Subject: [PATCH] Audio port output in .wav file --- rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 122 ++++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 7 +- rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 21 ++-- rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp | 10 +- rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/SC_Time.cpp | 35 ++++-- 6 files changed, 168 insertions(+), 31 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index b794ea53b5..65260d72eb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -8,6 +8,8 @@ void cellAudio_load(); void cellAudio_unload(); Module cellAudio(0x0011, cellAudio_init, cellAudio_load, cellAudio_unload); +extern u64 get_system_time(); + enum { //libaudio Error Codes @@ -61,6 +63,56 @@ enum CELL_SOUND_SYNTH2_ERROR_ALREADY_INITIALIZED = 0x80310203, }; +struct WAVHeader +{ + struct RIFFHeader + { + u32 ID; // "RIFF" + u32 Size; // FileSize - 8 + u32 WAVE; // "WAVE" + + RIFFHeader(u32 size) + : ID(*(u32*)"RIFF") + , WAVE(*(u32*)"WAVE") + , Size(size) + { + } + } RIFF; + struct FMTHeader + { + u32 ID; // "fmt " + u32 Size; // 16 + u16 AudioFormat; // 1 for PCM, 3 for IEEE Floating Point + u16 NumChannels; // 1, 2, 6, 8 + u32 SampleRate; // 48000 + u32 ByteRate; // SampleRate * NumChannels * BitsPerSample/8 + u16 BlockAlign; // NumChannels * BitsPerSample/8 + u16 BitsPerSample; // sizeof(float) * 8 + + FMTHeader(u8 ch) + : ID(*(u32*)"fmt ") + , Size(16) + , AudioFormat(3) + , NumChannels(ch) + , SampleRate(48000) + , ByteRate(SampleRate * ch * sizeof(float)) + , BlockAlign(ch * sizeof(float)) + , BitsPerSample(sizeof(float) * 8) + { + } + } FMT; + u32 ID; // "data" + u32 Size; // size of data (256 * NumChannels * sizeof(float)) + + WAVHeader(u8 ch) + : ID(*(u32*)"data") + , Size(0) + , FMT(ch) + , RIFF(sizeof(RIFFHeader) + sizeof(FMTHeader)) + { + } +}; + //libaudio datatypes struct CellAudioPortParam @@ -368,16 +420,76 @@ int cellAudioPortStart(u32 portNum) thread t(t_name, [portNum]() { - AudioPortConfig& ref = *m_config.m_ports[portNum]; - mem64_t index(ref.m_index); + AudioPortConfig& port = *m_config.m_ports[portNum]; + mem64_t index(port.m_index); // index storage + + if (port.m_param.nChannel > 8) + { + ConLog.Error("Port aborted: invalid channel count (%d)", port.m_param.nChannel); + return; + } + + WAVHeader header(port.m_param.nChannel); // WAV file header + + wxString output_name = "audioport0.wav"; + output_name[9] = '0' + portNum; + + wxFile output(output_name, wxFile::write); // create output file + if (!output.IsOpened()) + { + ConLog.Error("Port aborted: cannot write %s", output_name.wx_str()); + return; + } ConLog.Write("Port started"); - while (ref.m_is_audio_port_started && !Emu.IsStopped()) + + u64 start_time = get_system_time(); + u32 counter = 0; + + output.Write(&header, sizeof(header)); // write file header + + const u32 block_size = port.m_param.nChannel * 256 * sizeof(float); + + u32 buffer[32*256]; // buffer for max channel count (8) + + while (port.m_is_audio_port_started) { - Sleep(5); - index = (index.GetValue() + 1) % ref.m_param.nBlock; + // Sleep(5); // precise time of sleeping: 5,(3) ms (or 256/48000 sec) + if ((u64)counter * 256000000 / 48000 >= get_system_time() - start_time) + { + Sleep(1); + continue; + } + + counter++; + + u32 position = index.GetValue(); // get old value + + memcpy(buffer, Memory + port.m_buffer + position * block_size, block_size); + + index = (position + 1) % port.m_param.nBlock; // write new value + + for (u32 i = 0; i < block_size; i++) + { + buffer[i] = re(buffer[i]); // reverse byte order + } + + output.Write(&buffer, block_size); // write file data + header.Size += block_size; // update file header + header.RIFF.Size += block_size; + + if (Emu.IsStopped()) + { + ConLog.Warning("Port aborted"); + goto abort; + } } ConLog.Write("Port finished"); + abort: + output.Seek(0); + output.Write(&header, sizeof(header)); // write fixed file header + + output.Close(); }); t.detach(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 2ce2fd58cf..355cc277ff 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -463,9 +463,14 @@ int cellSysutilCheckCallback() CPUThread& thr = Emu.GetCallbackThread(); - while (Emu.IsRunning() && thr.IsAlive()) + while (thr.IsAlive()) { Sleep(1); + if (Emu.IsStopped()) + { + ConLog.Warning("cellSysutilCheckCallback() aborted"); + break; + } } return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 33bc0b1b80..ac29d660f5 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -5,8 +5,6 @@ void sys_fs_init(); Module sys_fs(0x000e, sys_fs_init); -std::atomic g_FsAioReadID = 0; - bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp) { if (version > 4 || flags & 0x7EFFFFC0){ @@ -137,12 +135,21 @@ int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) return CELL_OK; } -SMutex aio_mutex; +std::atomic g_FsAioReadID = 0; +std::atomic g_FsAioReadCur = 0; bool aio_init; void fsAioRead(u32 fd, mem_ptr_t aio, int xid, mem_func_ptr_t xaio, u32 error, int xid, u64 size)> func) { - //SMutexLocker lock (aio_mutex); + while (g_FsAioReadCur != xid) + { + Sleep(1); + if (Emu.IsStopped()) + { + ConLog.Warning("fsAioRead() aborted"); + return; + } + } vfsFileBase* orig_file; if(!sys_fs.CheckId(fd, orig_file)) return; @@ -186,6 +193,8 @@ void fsAioRead(u32 fd, mem_ptr_t aio, int xid, mem_func_ptr_t aio, mem32_t aio_id, mem_func_ptr_t xaio, u32 error, int xid, u64 size)> func) @@ -199,7 +208,7 @@ int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_t aio, mem32_t aio_id, mem_func_ptr_t attr) wxString(attr->name, 8).wx_str(), (u32)attr->protocol, wxString(is_recursive ? "true" : "false").wx_str(), mutex_id.GetValue()); + // TODO: unlock mutex when owner thread does exit + return CELL_OK; } int sys_mutex_destroy(u32 mutex_id) { - sys_mtx.Warning("sys_mutex_destroy(mutex_id=0x%x)", mutex_id); + sys_mtx.Warning("sys_mutex_destroy(mutex_id=%d)", mutex_id); Mutex* mutex; if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) @@ -80,7 +82,7 @@ int sys_mutex_destroy(u32 mutex_id) int sys_mutex_lock(u32 mutex_id, u64 timeout) { - sys_mtx.Log("sys_mutex_lock(mutex_id=0x%x, timeout=0x%llx)", mutex_id, timeout); + sys_mtx.Log("sys_mutex_lock(mutex_id=%d, timeout=0x%llx)", mutex_id, timeout); Mutex* mutex; if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) @@ -134,7 +136,7 @@ abort: int sys_mutex_trylock(u32 mutex_id) { - sys_mtx.Log("sys_mutex_trylock(mutex_id=0x%x)", mutex_id); + sys_mtx.Log("sys_mutex_trylock(mutex_id=%d)", mutex_id); Mutex* mutex; if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) @@ -170,7 +172,7 @@ int sys_mutex_trylock(u32 mutex_id) int sys_mutex_unlock(u32 mutex_id) { - sys_mtx.Log("sys_mutex_unlock(mutex_id=0x%x)", mutex_id); + sys_mtx.Log("sys_mutex_unlock(mutex_id=%d)", mutex_id); Mutex* mutex; if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp index c70d43838d..e4259ab0f1 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp @@ -247,12 +247,12 @@ int cellPadSetPortSetting(u32 port_no, u32 port_setting) int cellPadInfoPressMode(u32 port_no) { - sys_io.Log("cellPadInfoPressMode(port_no=%d)", port_no); + sys_io.Error("cellPadInfoPressMode(port_no=%d)", port_no); return CELL_OK; } int cellPadInfoSensorMode(u32 port_no) { - sys_io.Log("cellPadInfoSensorMode(port_no=%d)", port_no); + sys_io.Error("cellPadInfoSensorMode(port_no=%d)", port_no); return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp index f6b7c7912a..045a17172f 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp @@ -10,7 +10,8 @@ #include SysCallBase sys_time("sys_time"); -static const u64 timebase_frequency = 79800000; + +//static const u64 timebase_frequency = 79800000; extern int cellSysutilGetSystemParamInt(int id, mem32_t value); int sys_time_get_timezone(mem32_t timezone, mem32_t summertime) @@ -23,11 +24,26 @@ int sys_time_get_timezone(mem32_t timezone, mem32_t summertime) return CELL_OK; } +u64 get_system_time() +{ +#ifdef _WIN32 + LARGE_INTEGER cycle; + LARGE_INTEGER freq; + QueryPerformanceCounter(&cycle); + QueryPerformanceFrequency(&freq); + return cycle.QuadPart * 1000000 / freq.QuadPart; +#else + struct timespec ts; + if (!clock_gettime(CLOCK_MONOTONIC, &ts)) + return ts.tv_sec * (s64)10000000 + (s64)ts.tv_nsec / (s64)100; +#endif +} + int sys_time_get_current_time(u32 sec_addr, u32 nsec_addr) { sys_time.Log("sys_time_get_current_time(sec_addr=0x%x, nsec_addr=0x%x)", sec_addr, nsec_addr); - u64 time = sys_time_get_system_time(); + u64 time = get_system_time(); Memory.Write64(sec_addr, time / 1000000); Memory.Write64(nsec_addr, time % 1000000); @@ -38,21 +54,15 @@ int sys_time_get_current_time(u32 sec_addr, u32 nsec_addr) s64 sys_time_get_system_time() { sys_time.Log("sys_time_get_system_time()"); -#ifdef _WIN32 - LARGE_INTEGER cycle; - QueryPerformanceCounter(&cycle); - return cycle.QuadPart; -#else - struct timespec ts; - if (!clock_gettime(CLOCK_MONOTONIC, &ts)) - return ts.tv_sec * (s64)10000000 + (s64)ts.tv_nsec / (s64)100; -#endif + return get_system_time(); } u64 sys_time_get_timebase_frequency() { sys_time.Log("sys_time_get_timebase_frequency()"); + return 1000000; + /* #ifdef _WIN32 static LARGE_INTEGER frequency = {0ULL}; @@ -60,6 +70,7 @@ u64 sys_time_get_timebase_frequency() return frequency.QuadPart; #else - return 10000000; + return 10000000; #endif + */ }