mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
Audio port output in .wav file
This commit is contained in:
parent
848c5dadf0
commit
4375b9dd2a
@ -8,6 +8,8 @@ void cellAudio_load();
|
|||||||
void cellAudio_unload();
|
void cellAudio_unload();
|
||||||
Module cellAudio(0x0011, cellAudio_init, cellAudio_load, cellAudio_unload);
|
Module cellAudio(0x0011, cellAudio_init, cellAudio_load, cellAudio_unload);
|
||||||
|
|
||||||
|
extern u64 get_system_time();
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
//libaudio Error Codes
|
//libaudio Error Codes
|
||||||
@ -61,6 +63,56 @@ enum
|
|||||||
CELL_SOUND_SYNTH2_ERROR_ALREADY_INITIALIZED = 0x80310203,
|
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
|
//libaudio datatypes
|
||||||
struct CellAudioPortParam
|
struct CellAudioPortParam
|
||||||
@ -368,16 +420,76 @@ int cellAudioPortStart(u32 portNum)
|
|||||||
|
|
||||||
thread t(t_name, [portNum]()
|
thread t(t_name, [portNum]()
|
||||||
{
|
{
|
||||||
AudioPortConfig& ref = *m_config.m_ports[portNum];
|
AudioPortConfig& port = *m_config.m_ports[portNum];
|
||||||
mem64_t index(ref.m_index);
|
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");
|
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);
|
// Sleep(5); // precise time of sleeping: 5,(3) ms (or 256/48000 sec)
|
||||||
index = (index.GetValue() + 1) % ref.m_param.nBlock;
|
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");
|
ConLog.Write("Port finished");
|
||||||
|
abort:
|
||||||
|
output.Seek(0);
|
||||||
|
output.Write(&header, sizeof(header)); // write fixed file header
|
||||||
|
|
||||||
|
output.Close();
|
||||||
});
|
});
|
||||||
t.detach();
|
t.detach();
|
||||||
|
|
||||||
|
@ -463,9 +463,14 @@ int cellSysutilCheckCallback()
|
|||||||
|
|
||||||
CPUThread& thr = Emu.GetCallbackThread();
|
CPUThread& thr = Emu.GetCallbackThread();
|
||||||
|
|
||||||
while (Emu.IsRunning() && thr.IsAlive())
|
while (thr.IsAlive())
|
||||||
{
|
{
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("cellSysutilCheckCallback() aborted");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
void sys_fs_init();
|
void sys_fs_init();
|
||||||
Module sys_fs(0x000e, sys_fs_init);
|
Module sys_fs(0x000e, sys_fs_init);
|
||||||
|
|
||||||
std::atomic<u32> g_FsAioReadID = 0;
|
|
||||||
|
|
||||||
bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp)
|
bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp)
|
||||||
{
|
{
|
||||||
if (version > 4 || flags & 0x7EFFFFC0){
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMutex aio_mutex;
|
std::atomic<u32> g_FsAioReadID = 0;
|
||||||
|
std::atomic<u32> g_FsAioReadCur = 0;
|
||||||
bool aio_init;
|
bool aio_init;
|
||||||
|
|
||||||
void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, u32 error, int xid, u64 size)> func)
|
void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> 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;
|
vfsFileBase* orig_file;
|
||||||
if(!sys_fs.CheckId(fd, orig_file)) return;
|
if(!sys_fs.CheckId(fd, orig_file)) return;
|
||||||
@ -186,6 +193,8 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
|||||||
//start callback thread
|
//start callback thread
|
||||||
if(func)
|
if(func)
|
||||||
func.async(aio, error, xid, res);
|
func.async(aio, error, xid, res);
|
||||||
|
|
||||||
|
g_FsAioReadCur++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, u32 error, int xid, u64 size)> func)
|
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, u32 error, int xid, u64 size)> func)
|
||||||
@ -199,7 +208,7 @@ int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void
|
|||||||
|
|
||||||
if (!aio_init)
|
if (!aio_init)
|
||||||
{
|
{
|
||||||
return CELL_ENXIO;
|
//return CELL_ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfsFileBase* orig_file;
|
vfsFileBase* orig_file;
|
||||||
@ -211,10 +220,8 @@ int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void
|
|||||||
aio_id = xid;
|
aio_id = xid;
|
||||||
|
|
||||||
{
|
{
|
||||||
//SMutexLocker lock(aio_mutex);
|
|
||||||
thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func));
|
thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func));
|
||||||
t.detach();
|
t.detach();
|
||||||
//fsAioRead(fd, aio, xid, func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -42,12 +42,14 @@ int sys_mutex_create(mem32_t mutex_id, mem_ptr_t<sys_mutex_attribute> attr)
|
|||||||
wxString(attr->name, 8).wx_str(), (u32)attr->protocol,
|
wxString(attr->name, 8).wx_str(), (u32)attr->protocol,
|
||||||
wxString(is_recursive ? "true" : "false").wx_str(), mutex_id.GetValue());
|
wxString(is_recursive ? "true" : "false").wx_str(), mutex_id.GetValue());
|
||||||
|
|
||||||
|
// TODO: unlock mutex when owner thread does exit
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_mutex_destroy(u32 mutex_id)
|
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;
|
Mutex* mutex;
|
||||||
if (!Emu.GetIdManager().GetIDData(mutex_id, 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)
|
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;
|
Mutex* mutex;
|
||||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||||
@ -134,7 +136,7 @@ abort:
|
|||||||
|
|
||||||
int sys_mutex_trylock(u32 mutex_id)
|
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;
|
Mutex* mutex;
|
||||||
if (!Emu.GetIdManager().GetIDData(mutex_id, 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)
|
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;
|
Mutex* mutex;
|
||||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||||
|
@ -247,12 +247,12 @@ int cellPadSetPortSetting(u32 port_no, u32 port_setting)
|
|||||||
|
|
||||||
int cellPadInfoPressMode(u32 port_no)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellPadInfoSensorMode(u32 port_no)
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
@ -10,7 +10,8 @@
|
|||||||
#include <sys/timeb.h>
|
#include <sys/timeb.h>
|
||||||
|
|
||||||
SysCallBase sys_time("sys_time");
|
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);
|
extern int cellSysutilGetSystemParamInt(int id, mem32_t value);
|
||||||
|
|
||||||
int sys_time_get_timezone(mem32_t timezone, mem32_t summertime)
|
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;
|
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)
|
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);
|
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(sec_addr, time / 1000000);
|
||||||
Memory.Write64(nsec_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()
|
s64 sys_time_get_system_time()
|
||||||
{
|
{
|
||||||
sys_time.Log("sys_time_get_system_time()");
|
sys_time.Log("sys_time_get_system_time()");
|
||||||
#ifdef _WIN32
|
return get_system_time();
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 sys_time_get_timebase_frequency()
|
u64 sys_time_get_timebase_frequency()
|
||||||
{
|
{
|
||||||
sys_time.Log("sys_time_get_timebase_frequency()");
|
sys_time.Log("sys_time_get_timebase_frequency()");
|
||||||
|
return 1000000;
|
||||||
|
|
||||||
|
/*
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static LARGE_INTEGER frequency = {0ULL};
|
static LARGE_INTEGER frequency = {0ULL};
|
||||||
|
|
||||||
@ -60,6 +70,7 @@ u64 sys_time_get_timebase_frequency()
|
|||||||
|
|
||||||
return frequency.QuadPart;
|
return frequency.QuadPart;
|
||||||
#else
|
#else
|
||||||
return 10000000;
|
return 10000000;
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user