2020-12-05 13:08:24 +01:00
|
|
|
#include "stdafx.h"
|
2014-03-08 00:15:39 +01:00
|
|
|
#include "AudioDumper.h"
|
2017-01-25 00:22:19 +01:00
|
|
|
|
2025-04-08 18:46:57 +02:00
|
|
|
#include "util/date_time.h"
|
2020-06-01 07:58:14 +02:00
|
|
|
#include "Emu/System.h"
|
2014-03-08 00:15:39 +01:00
|
|
|
|
2022-05-05 15:47:44 +02:00
|
|
|
#include <bit>
|
|
|
|
|
|
2022-01-05 09:26:12 +01:00
|
|
|
AudioDumper::AudioDumper()
|
2014-03-08 00:15:39 +01:00
|
|
|
{
|
2022-01-05 09:26:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AudioDumper::~AudioDumper()
|
|
|
|
|
{
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-05 15:47:44 +02:00
|
|
|
void AudioDumper::Open(AudioChannelCnt ch, AudioFreq sample_rate, AudioSampleSize sample_size)
|
2022-01-05 09:26:12 +01:00
|
|
|
{
|
|
|
|
|
Close();
|
|
|
|
|
|
2022-05-05 15:47:44 +02:00
|
|
|
m_header = WAVHeader(ch, sample_rate, sample_size);
|
|
|
|
|
std::string path = fs::get_cache_dir() + "audio_";
|
|
|
|
|
if (const std::string id = Emu.GetTitleID(); !id.empty())
|
2015-01-16 15:36:53 +01:00
|
|
|
{
|
2022-05-05 15:47:44 +02:00
|
|
|
path += id + "_";
|
2015-01-16 15:36:53 +01:00
|
|
|
}
|
2022-05-05 15:47:44 +02:00
|
|
|
path += date_time::current_time_narrow<'_'>() + ".wav";
|
|
|
|
|
m_output.open(path, fs::rewrite);
|
|
|
|
|
m_output.seek(sizeof(m_header));
|
2014-03-08 00:15:39 +01:00
|
|
|
}
|
|
|
|
|
|
2022-01-05 09:26:12 +01:00
|
|
|
void AudioDumper::Close()
|
2014-03-08 00:15:39 +01:00
|
|
|
{
|
2016-02-01 22:51:35 +01:00
|
|
|
if (GetCh())
|
2015-01-16 15:36:53 +01:00
|
|
|
{
|
2022-05-05 15:47:44 +02:00
|
|
|
if (m_header.Size & 1)
|
|
|
|
|
{
|
|
|
|
|
const u8 pad_byte = 0;
|
|
|
|
|
m_output.write(pad_byte);
|
|
|
|
|
m_header.RIFF.Size += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-01 22:51:35 +01:00
|
|
|
m_output.seek(0);
|
2022-05-05 15:47:44 +02:00
|
|
|
m_output.write(m_header); // write file header
|
2022-01-05 09:26:12 +01:00
|
|
|
m_output.close();
|
|
|
|
|
m_header.FMT.NumChannels = 0;
|
2015-01-16 15:36:53 +01:00
|
|
|
}
|
2014-03-08 00:15:39 +01:00
|
|
|
}
|
|
|
|
|
|
2016-02-01 22:51:35 +01:00
|
|
|
void AudioDumper::WriteData(const void* buffer, u32 size)
|
2014-03-08 00:15:39 +01:00
|
|
|
{
|
2022-05-05 15:47:44 +02:00
|
|
|
if (GetCh() && size && buffer)
|
2014-03-19 01:32:23 +01:00
|
|
|
{
|
2022-05-05 15:47:44 +02:00
|
|
|
const u32 blk_size = GetCh() * GetSampleSize();
|
|
|
|
|
const u32 sample_cnt_per_ch = size / blk_size;
|
|
|
|
|
|
|
|
|
|
ensure(size - sample_cnt_per_ch * blk_size == 0);
|
|
|
|
|
|
|
|
|
|
if constexpr (std::endian::big == std::endian::native)
|
|
|
|
|
{
|
|
|
|
|
std::vector<u8> tmp_buf(size);
|
|
|
|
|
|
|
|
|
|
if (GetSampleSize() == sizeof(f32))
|
|
|
|
|
{
|
|
|
|
|
for (u32 sample_idx = 0; sample_idx < sample_cnt_per_ch * GetCh(); sample_idx++)
|
|
|
|
|
{
|
|
|
|
|
std::bit_cast<f32*>(tmp_buf.data())[sample_idx] = static_cast<const be_t<f32>*>(buffer)[sample_idx];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (u32 sample_idx = 0; sample_idx < sample_cnt_per_ch * GetCh(); sample_idx++)
|
|
|
|
|
{
|
|
|
|
|
std::bit_cast<s16*>(tmp_buf.data())[sample_idx] = static_cast<const be_t<s16>*>(buffer)[sample_idx];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(m_output.write(tmp_buf.data(), size) == size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ensure(m_output.write(buffer, size) == size);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-01 22:51:35 +01:00
|
|
|
m_header.Size += size;
|
|
|
|
|
m_header.RIFF.Size += size;
|
2022-05-05 15:47:44 +02:00
|
|
|
m_header.FACT.SampleLength += sample_cnt_per_ch;
|
2014-03-19 01:32:23 +01:00
|
|
|
}
|
2014-03-08 00:15:39 +01:00
|
|
|
}
|