mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-12 13:13:43 +00:00
Partial commit: Audio
This commit is contained in:
parent
766f1b2b01
commit
edd0965c1a
@ -1,9 +1,11 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "Utilities/Config.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/state.h"
|
|
||||||
|
|
||||||
#include "OpenALThread.h"
|
#include "OpenALThread.h"
|
||||||
|
|
||||||
|
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma comment(lib, "OpenAL32.lib")
|
#pragma comment(lib, "OpenAL32.lib")
|
||||||
#endif
|
#endif
|
||||||
@ -32,30 +34,27 @@ void printAlcError(ALCenum err, const char* situation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenALThread::~OpenALThread()
|
OpenALThread::OpenALThread()
|
||||||
{
|
{
|
||||||
Quit();
|
ALCdevice* m_device = alcOpenDevice(nullptr);
|
||||||
}
|
|
||||||
|
|
||||||
void OpenALThread::Init()
|
|
||||||
{
|
|
||||||
m_device = alcOpenDevice(nullptr);
|
|
||||||
checkForAlcError("alcOpenDevice");
|
checkForAlcError("alcOpenDevice");
|
||||||
|
|
||||||
m_context = alcCreateContext(m_device, nullptr);
|
ALCcontext* m_context = alcCreateContext(m_device, nullptr);
|
||||||
checkForAlcError("alcCreateContext");
|
checkForAlcError("alcCreateContext");
|
||||||
|
|
||||||
alcMakeContextCurrent(m_context);
|
alcMakeContextCurrent(m_context);
|
||||||
checkForAlcError("alcMakeContextCurrent");
|
checkForAlcError("alcMakeContextCurrent");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALThread::Quit()
|
OpenALThread::~OpenALThread()
|
||||||
{
|
{
|
||||||
m_context = alcGetCurrentContext();
|
if (ALCcontext* m_context = alcGetCurrentContext())
|
||||||
m_device = alcGetContextsDevice(m_context);
|
{
|
||||||
alcMakeContextCurrent(nullptr);
|
ALCdevice* m_device = alcGetContextsDevice(m_context);
|
||||||
alcDestroyContext(m_context);
|
alcMakeContextCurrent(nullptr);
|
||||||
alcCloseDevice(m_device);
|
alcDestroyContext(m_context);
|
||||||
|
alcCloseDevice(m_device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALThread::Play()
|
void OpenALThread::Play()
|
||||||
@ -103,7 +102,7 @@ void OpenALThread::Open(const void* src, int size)
|
|||||||
|
|
||||||
for (uint i = 0; i<g_al_buffers_count; ++i)
|
for (uint i = 0; i<g_al_buffers_count; ++i)
|
||||||
{
|
{
|
||||||
alBufferData(m_buffers[i], rpcs3::config.audio.convert_to_u16.value() ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, src, m_buffer_size, 48000);
|
alBufferData(m_buffers[i], g_cfg_audio_convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, src, m_buffer_size, 48000);
|
||||||
checkForAlError("alBufferData");
|
checkForAlError("alBufferData");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +137,7 @@ void OpenALThread::AddData(const void* src, int size)
|
|||||||
|
|
||||||
int bsize = size < m_buffer_size ? size : m_buffer_size;
|
int bsize = size < m_buffer_size ? size : m_buffer_size;
|
||||||
|
|
||||||
alBufferData(buffer, rpcs3::config.audio.convert_to_u16.value() ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, bsrc, bsize, 48000);
|
alBufferData(buffer, g_cfg_audio_convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, bsrc, bsize, 48000);
|
||||||
checkForAlError("alBufferData");
|
checkForAlError("alBufferData");
|
||||||
|
|
||||||
alSourceQueueBuffers(m_source, 1, &buffer);
|
alSourceQueueBuffers(m_source, 1, &buffer);
|
||||||
@ -149,4 +148,4 @@ void OpenALThread::AddData(const void* src, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Play();
|
Play();
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,19 @@
|
|||||||
class OpenALThread : public AudioThread
|
class OpenALThread : public AudioThread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static const uint g_al_buffers_count = 16;
|
static const uint g_al_buffers_count = 24;
|
||||||
|
|
||||||
ALuint m_source;
|
ALuint m_source;
|
||||||
ALuint m_buffers[g_al_buffers_count];
|
ALuint m_buffers[g_al_buffers_count];
|
||||||
ALCdevice* m_device;
|
|
||||||
ALCcontext* m_context;
|
|
||||||
ALsizei m_buffer_size;
|
ALsizei m_buffer_size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~OpenALThread();
|
OpenALThread();
|
||||||
|
virtual ~OpenALThread() override;
|
||||||
|
|
||||||
virtual void Init();
|
virtual void Play() override;
|
||||||
virtual void Quit();
|
virtual void Open(const void* src, int size) override;
|
||||||
virtual void Play();
|
virtual void Close() override;
|
||||||
virtual void Open(const void* src, int size);
|
virtual void Stop() override;
|
||||||
virtual void Close();
|
virtual void AddData(const void* src, int size) override;
|
||||||
virtual void Stop();
|
|
||||||
virtual void AddData(const void* src, int size);
|
|
||||||
};
|
};
|
||||||
|
@ -1,67 +1,31 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "AudioDumper.h"
|
#include "AudioDumper.h"
|
||||||
|
|
||||||
AudioDumper::AudioDumper() : m_header(0), m_init(false)
|
AudioDumper::AudioDumper(u16 ch)
|
||||||
|
: m_header(ch)
|
||||||
{
|
{
|
||||||
|
if (GetCh())
|
||||||
|
{
|
||||||
|
m_output.open(fs::get_config_dir() + "audio.wav", fs::rewrite);
|
||||||
|
m_output.write(m_header); // write initial file header
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDumper::~AudioDumper()
|
AudioDumper::~AudioDumper()
|
||||||
{
|
{
|
||||||
Finalize();
|
if (GetCh())
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioDumper::Init(u8 ch)
|
|
||||||
{
|
|
||||||
if ((m_init = m_output.open("audio.wav", fom::rewrite)))
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
#ifdef SKIP_EMPTY_AUDIO
|
|
||||||
bool do_save = false;
|
|
||||||
for (u32 i = 0; i < size / 8; i++)
|
|
||||||
{
|
|
||||||
if (((u64*)buffer)[i]) do_save = true;
|
|
||||||
}
|
|
||||||
for (u32 i = 0; i < size % 8; i++)
|
|
||||||
{
|
|
||||||
if (((u8*)buffer)[i + (size & ~7)]) do_save = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.seek(0);
|
||||||
m_output.write(&m_header, sizeof(m_header)); // write fixed file header
|
m_output.write(m_header); // rewrite file header
|
||||||
m_output.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioDumper::WriteData(const void* buffer, u32 size)
|
||||||
|
{
|
||||||
|
if (GetCh())
|
||||||
|
{
|
||||||
|
ASSERT(m_output.write(buffer, size) == size);
|
||||||
|
m_header.Size += size;
|
||||||
|
m_header.RIFF.Size += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,8 @@ struct WAVHeader
|
|||||||
u32 Size; // FileSize - 8
|
u32 Size; // FileSize - 8
|
||||||
u32 WAVE; // "WAVE"
|
u32 WAVE; // "WAVE"
|
||||||
|
|
||||||
|
RIFFHeader() = default;
|
||||||
|
|
||||||
RIFFHeader(u32 size)
|
RIFFHeader(u32 size)
|
||||||
: ID(*(u32*)"RIFF")
|
: ID(*(u32*)"RIFF")
|
||||||
, WAVE(*(u32*)"WAVE")
|
, WAVE(*(u32*)"WAVE")
|
||||||
@ -15,6 +17,7 @@ struct WAVHeader
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
} RIFF;
|
} RIFF;
|
||||||
|
|
||||||
struct FMTHeader
|
struct FMTHeader
|
||||||
{
|
{
|
||||||
u32 ID; // "fmt "
|
u32 ID; // "fmt "
|
||||||
@ -26,7 +29,9 @@ struct WAVHeader
|
|||||||
u16 BlockAlign; // NumChannels * BitsPerSample/8
|
u16 BlockAlign; // NumChannels * BitsPerSample/8
|
||||||
u16 BitsPerSample; // sizeof(float) * 8
|
u16 BitsPerSample; // sizeof(float) * 8
|
||||||
|
|
||||||
FMTHeader(u8 ch)
|
FMTHeader() = default;
|
||||||
|
|
||||||
|
FMTHeader(u16 ch)
|
||||||
: ID(*(u32*)"fmt ")
|
: ID(*(u32*)"fmt ")
|
||||||
, Size(16)
|
, Size(16)
|
||||||
, AudioFormat(3)
|
, AudioFormat(3)
|
||||||
@ -38,10 +43,13 @@ struct WAVHeader
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
} FMT;
|
} FMT;
|
||||||
|
|
||||||
u32 ID; // "data"
|
u32 ID; // "data"
|
||||||
u32 Size; // size of data (256 * NumChannels * sizeof(float))
|
u32 Size; // size of data (256 * NumChannels * sizeof(float))
|
||||||
|
|
||||||
WAVHeader(u8 ch)
|
WAVHeader() = default;
|
||||||
|
|
||||||
|
WAVHeader(u16 ch)
|
||||||
: ID(*(u32*)"data")
|
: ID(*(u32*)"data")
|
||||||
, Size(0)
|
, Size(0)
|
||||||
, FMT(ch)
|
, FMT(ch)
|
||||||
@ -50,21 +58,15 @@ struct WAVHeader
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class AudioDumper
|
class AudioDumper
|
||||||
{
|
{
|
||||||
WAVHeader m_header;
|
WAVHeader m_header;
|
||||||
fs::file m_output;
|
fs::file m_output;
|
||||||
bool m_init;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AudioDumper();
|
AudioDumper(u16 ch);
|
||||||
~AudioDumper();
|
~AudioDumper();
|
||||||
|
|
||||||
public:
|
void WriteData(const void* buffer, u32 size);
|
||||||
bool Init(u8 ch);
|
|
||||||
void WriteHeader();
|
|
||||||
size_t WriteData(const void* buffer, size_t size);
|
|
||||||
void Finalize();
|
|
||||||
const u16 GetCh() const { return m_header.FMT.NumChannels; }
|
const u16 GetCh() const { return m_header.FMT.NumChannels; }
|
||||||
};
|
};
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#include "stdafx.h"
|
|
||||||
#include "Emu/System.h"
|
|
||||||
#include "AudioManager.h"
|
|
||||||
|
|
||||||
void AudioManager::Init()
|
|
||||||
{
|
|
||||||
if (!m_audio_out) m_audio_out = Emu.GetCallbacks().get_audio();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioManager::Close()
|
|
||||||
{
|
|
||||||
m_audio_out.reset();
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AudioThread.h"
|
|
||||||
|
|
||||||
class AudioManager
|
|
||||||
{
|
|
||||||
std::shared_ptr<AudioThread> m_audio_out;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Init();
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
AudioThread& GetAudioOut() { return *m_audio_out; }
|
|
||||||
};
|
|
@ -3,10 +3,8 @@
|
|||||||
class AudioThread
|
class AudioThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~AudioThread() {}
|
virtual ~AudioThread() = default;
|
||||||
|
|
||||||
virtual void Init() = 0;
|
|
||||||
virtual void Quit() = 0;
|
|
||||||
virtual void Play() = 0;
|
virtual void Play() = 0;
|
||||||
virtual void Open(const void* src, int size) = 0;
|
virtual void Open(const void* src, int size) = 0;
|
||||||
virtual void Close() = 0;
|
virtual void Close() = 0;
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
#include "Utilities/Config.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/state.h"
|
|
||||||
|
|
||||||
#include "XAudio2Thread.h"
|
#include "XAudio2Thread.h"
|
||||||
|
|
||||||
XAudio2Thread::~XAudio2Thread()
|
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
|
||||||
{
|
|
||||||
Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
XAudio2Thread::XAudio2Thread() : m_xaudio2_instance(nullptr), m_master_voice(nullptr), m_source_voice(nullptr)
|
XAudio2Thread::XAudio2Thread()
|
||||||
{
|
: m_xaudio2_instance(nullptr)
|
||||||
}
|
, m_master_voice(nullptr)
|
||||||
|
, m_source_voice(nullptr)
|
||||||
void XAudio2Thread::Init()
|
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
@ -43,24 +39,23 @@ void XAudio2Thread::Init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XAudio2Thread::Quit()
|
XAudio2Thread::~XAudio2Thread()
|
||||||
{
|
{
|
||||||
if (m_source_voice != nullptr)
|
if (m_source_voice != nullptr)
|
||||||
{
|
{
|
||||||
Stop();
|
m_source_voice->Stop();
|
||||||
m_source_voice->DestroyVoice();
|
m_source_voice->DestroyVoice();
|
||||||
m_source_voice = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_master_voice != nullptr)
|
if (m_master_voice != nullptr)
|
||||||
{
|
{
|
||||||
m_master_voice->DestroyVoice();
|
m_master_voice->DestroyVoice();
|
||||||
m_master_voice = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_xaudio2_instance != nullptr)
|
if (m_xaudio2_instance != nullptr)
|
||||||
{
|
{
|
||||||
m_xaudio2_instance->StopEngine();
|
m_xaudio2_instance->StopEngine();
|
||||||
m_xaudio2_instance->Release();
|
m_xaudio2_instance->Release();
|
||||||
m_xaudio2_instance = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
@ -101,11 +96,11 @@ void XAudio2Thread::Open(const void* src, int size)
|
|||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
WORD sample_size = rpcs3::config.audio.convert_to_u16.value() ? sizeof(u16) : sizeof(float);
|
WORD sample_size = g_cfg_audio_convert_to_u16 ? sizeof(u16) : sizeof(float);
|
||||||
WORD channels = 8;
|
WORD channels = 8;
|
||||||
|
|
||||||
WAVEFORMATEX waveformatex;
|
WAVEFORMATEX waveformatex;
|
||||||
waveformatex.wFormatTag = rpcs3::config.audio.convert_to_u16.value() ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
|
waveformatex.wFormatTag = g_cfg_audio_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
|
||||||
waveformatex.nChannels = channels;
|
waveformatex.nChannels = channels;
|
||||||
waveformatex.nSamplesPerSec = 48000;
|
waveformatex.nSamplesPerSec = 48000;
|
||||||
waveformatex.nAvgBytesPerSec = 48000 * (DWORD)channels * (DWORD)sample_size;
|
waveformatex.nAvgBytesPerSec = 48000 * (DWORD)channels * (DWORD)sample_size;
|
||||||
@ -121,6 +116,8 @@ void XAudio2Thread::Open(const void* src, int size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_source_voice->SetVolume(4.0);
|
||||||
|
|
||||||
AddData(src, size);
|
AddData(src, size);
|
||||||
Play();
|
Play();
|
||||||
}
|
}
|
||||||
|
@ -11,21 +11,18 @@
|
|||||||
|
|
||||||
class XAudio2Thread : public AudioThread
|
class XAudio2Thread : public AudioThread
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
IXAudio2* m_xaudio2_instance;
|
IXAudio2* m_xaudio2_instance;
|
||||||
IXAudio2MasteringVoice* m_master_voice;
|
IXAudio2MasteringVoice* m_master_voice;
|
||||||
IXAudio2SourceVoice* m_source_voice;
|
IXAudio2SourceVoice* m_source_voice;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~XAudio2Thread();
|
|
||||||
XAudio2Thread();
|
XAudio2Thread();
|
||||||
|
virtual ~XAudio2Thread() override;
|
||||||
|
|
||||||
virtual void Init();
|
virtual void Play() override;
|
||||||
virtual void Quit();
|
virtual void Open(const void* src, int size) override;
|
||||||
virtual void Play();
|
virtual void Close() override;
|
||||||
virtual void Open(const void* src, int size);
|
virtual void Stop() override;
|
||||||
virtual void Close();
|
virtual void AddData(const void* src, int size) override;
|
||||||
virtual void Stop();
|
|
||||||
virtual void AddData(const void* src, int size);
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user