[Audio] Remove manual memory allocations
* Remove explicit calls to new or malloc in favor of owned objects. * Move AudioSdl to the sdl frontend, it is no longer used by the wx frontend.
This commit is contained in:
parent
56320ec6d1
commit
64abd3e8dc
|
@ -1,4 +1,3 @@
|
||||||
add_subdirectory(audio_sdl)
|
|
||||||
add_subdirectory(av_recording)
|
add_subdirectory(av_recording)
|
||||||
add_subdirectory(draw_text)
|
add_subdirectory(draw_text)
|
||||||
add_subdirectory(filters)
|
add_subdirectory(filters)
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
add_library(vbam-components-audio-sdl OBJECT)
|
|
||||||
|
|
||||||
target_sources(vbam-components-audio-sdl
|
|
||||||
PRIVATE audio_sdl.cpp
|
|
||||||
PUBLIC audio_sdl.h
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(vbam-components-audio-sdl
|
|
||||||
PUBLIC ${SDL2_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(vbam-components-audio-sdl
|
|
||||||
PUBLIC vbam-core-base ${VBAM_SDL2_LIBS}
|
|
||||||
)
|
|
|
@ -2,8 +2,9 @@
|
||||||
#define VBAM_CORE_BASE_SYSTEM_H_
|
#define VBAM_CORE_BASE_SYSTEM_H_
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class SoundDriver;
|
#include "core/base/sound_driver.h"
|
||||||
|
|
||||||
enum IMAGE_TYPE {
|
enum IMAGE_TYPE {
|
||||||
IMAGE_UNKNOWN = -1,
|
IMAGE_UNKNOWN = -1,
|
||||||
|
@ -89,7 +90,7 @@ extern bool systemReadJoypads();
|
||||||
extern uint32_t systemReadJoypad(int);
|
extern uint32_t systemReadJoypad(int);
|
||||||
extern uint32_t systemGetClock();
|
extern uint32_t systemGetClock();
|
||||||
extern void systemSetTitle(const char*);
|
extern void systemSetTitle(const char*);
|
||||||
extern SoundDriver* systemSoundInit();
|
extern std::unique_ptr<SoundDriver> systemSoundInit();
|
||||||
extern void systemOnWriteDataToSoundBuffer(const uint16_t* finalWave, int length);
|
extern void systemOnWriteDataToSoundBuffer(const uint16_t* finalWave, int length);
|
||||||
extern void systemOnSoundShutdown();
|
extern void systemOnSoundShutdown();
|
||||||
extern void systemScreenMessage(const char*);
|
extern void systemScreenMessage(const char*);
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define NR51 0x81
|
#define NR51 0x81
|
||||||
#define NR52 0x84
|
#define NR52 0x84
|
||||||
|
|
||||||
SoundDriver* soundDriver = 0;
|
std::unique_ptr<SoundDriver> soundDriver;
|
||||||
|
|
||||||
extern bool stopState; // TODO: silence sound when true
|
extern bool stopState; // TODO: silence sound when true
|
||||||
|
|
||||||
|
@ -469,10 +469,7 @@ static void remake_stereo_buffer()
|
||||||
|
|
||||||
void soundShutdown()
|
void soundShutdown()
|
||||||
{
|
{
|
||||||
if (soundDriver) {
|
soundDriver.reset();
|
||||||
delete soundDriver;
|
|
||||||
soundDriver = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
systemOnSoundShutdown();
|
systemOnSoundShutdown();
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,16 @@
|
||||||
class SoundRetro : public SoundDriver {
|
class SoundRetro : public SoundDriver {
|
||||||
public:
|
public:
|
||||||
SoundRetro();
|
SoundRetro();
|
||||||
virtual ~SoundRetro();
|
~SoundRetro() override;
|
||||||
|
|
||||||
virtual bool init(long sampleRate);
|
private:
|
||||||
virtual void pause();
|
// SoundDriver implementation.
|
||||||
virtual void reset();
|
bool init(long sampleRate) override;
|
||||||
virtual void resume();
|
void pause() override;
|
||||||
virtual void write(uint16_t* finalWave, int length);
|
void reset() override;
|
||||||
virtual void setThrottle(unsigned short throttle);
|
void resume() override;
|
||||||
|
void write(uint16_t *finalWave, int length) override;
|
||||||
|
void setThrottle(unsigned short throttle_) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __VBA_SOUND_RETRO_H__
|
#endif // __VBA_SOUND_RETRO_H__
|
||||||
|
|
|
@ -1949,10 +1949,10 @@ uint32_t systemGetClock(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDriver* systemSoundInit(void)
|
std::unique_ptr<SoundDriver> systemSoundInit(void)
|
||||||
{
|
{
|
||||||
soundShutdown();
|
soundShutdown();
|
||||||
return new SoundRetro();
|
return std::make_unique<SoundRetro>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(const char* defaultMsg, ...)
|
void log(const char* defaultMsg, ...)
|
||||||
|
|
|
@ -7,6 +7,8 @@ add_executable(vbam WIN32)
|
||||||
|
|
||||||
target_sources(vbam
|
target_sources(vbam
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
audio_sdl.cpp
|
||||||
|
audio_sdl.h
|
||||||
ConfigManager.cpp
|
ConfigManager.cpp
|
||||||
ConfigManager.h
|
ConfigManager.h
|
||||||
dictionary.c
|
dictionary.c
|
||||||
|
@ -38,15 +40,19 @@ if(ENABLE_LIRC)
|
||||||
set(LIRC_CLIENT_LIBRARY lirc_client)
|
set(LIRC_CLIENT_LIBRARY lirc_client)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(vbam
|
||||||
|
PRIVATE ${SDL2_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(vbam
|
target_link_libraries(vbam
|
||||||
vbam-core
|
vbam-core
|
||||||
vbam-components-audio-sdl
|
|
||||||
vbam-components-draw-text
|
vbam-components-draw-text
|
||||||
vbam-components-filters
|
vbam-components-filters
|
||||||
vbam-components-filters-agb
|
vbam-components-filters-agb
|
||||||
vbam-components-filters-interframe
|
vbam-components-filters-interframe
|
||||||
vbam-components-user-config
|
vbam-components-user-config
|
||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
|
${VBAM_SDL2_LIBS}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
|
@ -68,6 +68,8 @@
|
||||||
#pragma comment(lib, "OpenGL32")
|
#pragma comment(lib, "OpenGL32")
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#define strdup _strdup
|
||||||
|
|
||||||
#endif // defined(_WIN32)
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
@ -91,7 +93,6 @@
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "components/audio_sdl/audio_sdl.h"
|
|
||||||
#include "components/draw_text/draw_text.h"
|
#include "components/draw_text/draw_text.h"
|
||||||
#include "components/filters_agb/filters_agb.h"
|
#include "components/filters_agb/filters_agb.h"
|
||||||
#include "components/user_config/user_config.h"
|
#include "components/user_config/user_config.h"
|
||||||
|
@ -110,6 +111,7 @@
|
||||||
#include "core/gba/gbaRtc.h"
|
#include "core/gba/gbaRtc.h"
|
||||||
#include "core/gba/gbaSound.h"
|
#include "core/gba/gbaSound.h"
|
||||||
#include "sdl/ConfigManager.h"
|
#include "sdl/ConfigManager.h"
|
||||||
|
#include "sdl/audio_sdl.h"
|
||||||
#include "sdl/filters.h"
|
#include "sdl/filters.h"
|
||||||
#include "sdl/inputSDL.h"
|
#include "sdl/inputSDL.h"
|
||||||
|
|
||||||
|
@ -2315,11 +2317,10 @@ uint8_t systemGetSensorDarkness()
|
||||||
return 0xE8;
|
return 0xE8;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDriver* systemSoundInit()
|
std::unique_ptr<SoundDriver> systemSoundInit() {
|
||||||
{
|
|
||||||
soundShutdown();
|
soundShutdown();
|
||||||
|
|
||||||
return new SoundSDL();
|
return std::make_unique<SoundSDL>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void systemOnSoundShutdown()
|
void systemOnSoundShutdown()
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
#include "components/audio_sdl/audio_sdl.h"
|
#include "sdl/audio_sdl.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
|
@ -15,34 +15,34 @@
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
#ifndef VBAM_COMPONENTS_AUDIO_SDL_AUDIO_SDL_H_
|
#ifndef VBAM_SDL_AUDIO_SDL_H_
|
||||||
#define VBAM_COMPONENTS_AUDIO_SDL_AUDIO_SDL_H_
|
#define VBAM_SDL_AUDIO_SDL_H_
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#include "core/base/ringbuffer.h"
|
#include "core/base/ringbuffer.h"
|
||||||
#include "core/base/sound_driver.h"
|
#include "core/base/sound_driver.h"
|
||||||
|
|
||||||
class SoundSDL : public SoundDriver {
|
class SoundSDL final : public SoundDriver {
|
||||||
public:
|
public:
|
||||||
SoundSDL();
|
SoundSDL();
|
||||||
virtual ~SoundSDL();
|
~SoundSDL() override;
|
||||||
|
|
||||||
virtual bool init(long sampleRate);
|
|
||||||
virtual void pause();
|
|
||||||
virtual void reset();
|
|
||||||
virtual void resume();
|
|
||||||
virtual void write(uint16_t *finalWave, int length);
|
|
||||||
virtual void setThrottle(unsigned short throttle_);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void soundCallback(void* data, uint8_t* stream, int length);
|
|
||||||
virtual void read(uint16_t* stream, int length);
|
|
||||||
virtual bool should_wait();
|
|
||||||
virtual std::size_t buffer_size();
|
|
||||||
virtual void deinit();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void soundCallback(void* data, uint8_t* stream, int length);
|
||||||
|
void read(uint16_t* stream, int length);
|
||||||
|
bool should_wait();
|
||||||
|
std::size_t buffer_size();
|
||||||
|
void deinit();
|
||||||
|
|
||||||
|
// SoundDriver implementation.
|
||||||
|
bool init(long sampleRate) override;
|
||||||
|
void pause() override;
|
||||||
|
void reset() override;
|
||||||
|
void resume() override;
|
||||||
|
void write(uint16_t *finalWave, int length) override;
|
||||||
|
void setThrottle(unsigned short throttle_) override;
|
||||||
|
|
||||||
RingBuffer<uint16_t> samples_buf;
|
RingBuffer<uint16_t> samples_buf;
|
||||||
|
|
||||||
SDL_AudioDeviceID sound_device = 0;
|
SDL_AudioDeviceID sound_device = 0;
|
||||||
|
@ -60,4 +60,4 @@ private:
|
||||||
static const double buftime;
|
static const double buftime;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VBAM_COMPONENTS_AUDIO_SDL_AUDIO_SDL_H_
|
#endif // VBAM_SDL_AUDIO_SDL_H_
|
|
@ -38,15 +38,15 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DirectSound();
|
DirectSound();
|
||||||
virtual ~DirectSound();
|
~DirectSound() override;
|
||||||
|
|
||||||
bool init(long sampleRate) override; // initialize the primary and secondary sound buffer
|
// SoundDriver implementation.
|
||||||
void setThrottle(unsigned short throttle_) override; // set game speed
|
bool init(long sampleRate) override;
|
||||||
void pause() override; // pause the secondary sound buffer
|
void pause() override;
|
||||||
void reset() override; // stop and reset the secondary sound buffer
|
void reset() override;
|
||||||
void resume() override; // resume the secondary sound buffer
|
void resume() override;
|
||||||
void write(uint16_t* finalWave,
|
void write(uint16_t *finalWave, int length) override;
|
||||||
int length) override; // write the emulated sound to the secondary sound buffer
|
void setThrottle(unsigned short throttle_) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
DirectSound::DirectSound()
|
DirectSound::DirectSound()
|
||||||
|
@ -336,9 +336,9 @@ void DirectSound::write(uint16_t* finalWave, int)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDriver* newDirectSound()
|
std::unique_ptr<SoundDriver> newDirectSound()
|
||||||
{
|
{
|
||||||
return new DirectSound();
|
return std::make_unique<DirectSound>();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct devnames {
|
struct devnames {
|
||||||
|
|
|
@ -60,7 +60,7 @@ int FAGetDev(FAudio* fa)
|
||||||
if (audio_device.empty())
|
if (audio_device.empty())
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
int ret = GetFADevices(fa, NULL, NULL, &audio_device);
|
int ret = GetFADevices(fa, nullptr, nullptr, &audio_device);
|
||||||
return ret < 0 ? 0 : ret;
|
return ret < 0 ? 0 : ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,19 +94,18 @@ public:
|
||||||
private:
|
private:
|
||||||
void* buffer_end_event_;
|
void* buffer_end_event_;
|
||||||
|
|
||||||
static void StaticOnBufferEnd(FAudioVoiceCallback* callback, void * pBufferContext) {
|
static void StaticOnBufferEnd(FAudioVoiceCallback* callback, void*) {
|
||||||
FAudio_BufferNotify* self = static_cast<FAudio_BufferNotify*>(callback);
|
FAudio_BufferNotify* self = static_cast<FAudio_BufferNotify*>(callback);
|
||||||
if (self != nullptr && self->buffer_end_event_ != NULL)
|
if (self != nullptr && self->buffer_end_event_ != nullptr) {
|
||||||
{
|
|
||||||
SetEvent(self->buffer_end_event_);
|
SetEvent(self->buffer_end_event_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void StaticOnVoiceProcessingPassStart(FAudioVoiceCallback* callback, uint32_t BytesRequired) {}
|
static void StaticOnVoiceProcessingPassStart(FAudioVoiceCallback*, uint32_t) {}
|
||||||
static void StaticOnVoiceProcessingPassEnd(FAudioVoiceCallback* callback) {}
|
static void StaticOnVoiceProcessingPassEnd(FAudioVoiceCallback*) {}
|
||||||
static void StaticOnStreamEnd(FAudioVoiceCallback* callback) {}
|
static void StaticOnStreamEnd(FAudioVoiceCallback*) {}
|
||||||
static void StaticOnBufferStart(FAudioVoiceCallback* callback, void * pBufferContext) {}
|
static void StaticOnBufferStart(FAudioVoiceCallback*, void*) {}
|
||||||
static void StaticOnLoopEnd(FAudioVoiceCallback* callback, void * pBufferContext) {}
|
static void StaticOnLoopEnd(FAudioVoiceCallback*, void*) {}
|
||||||
static void StaticOnVoiceError(FAudioVoiceCallback* callback, void * pBufferContext, uint32_t Error) {}
|
static void StaticOnVoiceError(FAudioVoiceCallback*, void*, uint32_t) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FAudio_Output
|
class FAudio_Output
|
||||||
|
@ -115,31 +114,27 @@ public:
|
||||||
FAudio_Output();
|
FAudio_Output();
|
||||||
~FAudio_Output();
|
~FAudio_Output();
|
||||||
|
|
||||||
// Initialization
|
|
||||||
bool init(long sampleRate);
|
|
||||||
|
|
||||||
// Sound Data Feed
|
|
||||||
void write(uint16_t* finalWave, int length);
|
|
||||||
|
|
||||||
// Play Control
|
|
||||||
void pause();
|
|
||||||
void resume();
|
|
||||||
void reset();
|
|
||||||
void close();
|
|
||||||
void device_change();
|
void device_change();
|
||||||
|
|
||||||
// Configuration Changes
|
|
||||||
void setThrottle(unsigned short throttle_);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// SoundDriver implementation.
|
||||||
|
bool init(long sampleRate) override;
|
||||||
|
void pause() override;
|
||||||
|
void reset() override;
|
||||||
|
void resume() override;
|
||||||
|
void write(uint16_t* finalWave, int length) override;
|
||||||
|
void setThrottle(unsigned short throttle_) override;
|
||||||
|
|
||||||
bool failed;
|
bool failed;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
bool playing;
|
bool playing;
|
||||||
uint32_t freq;
|
uint32_t freq_;
|
||||||
uint32_t bufferCount;
|
const uint32_t buffer_count_;
|
||||||
uint8_t* buffers;
|
std::vector<uint8_t> buffers_;
|
||||||
int currentBuffer;
|
int currentBuffer;
|
||||||
int soundBufferLen;
|
int sound_buffer_len_;
|
||||||
|
|
||||||
volatile bool device_changed;
|
volatile bool device_changed;
|
||||||
|
|
||||||
|
@ -180,21 +175,18 @@ public:
|
||||||
FAudio_Device_Notifier f_notifier;
|
FAudio_Device_Notifier f_notifier;
|
||||||
|
|
||||||
// Class Implementation
|
// Class Implementation
|
||||||
FAudio_Output::FAudio_Output()
|
FAudio_Output::FAudio_Output() : buffer_count_(OPTION(kSoundBuffers)) {
|
||||||
{
|
|
||||||
failed = false;
|
failed = false;
|
||||||
initialized = false;
|
initialized = false;
|
||||||
playing = false;
|
playing = false;
|
||||||
freq = 0;
|
freq_ = 0;
|
||||||
bufferCount = OPTION(kSoundBuffers);
|
|
||||||
buffers = NULL;
|
|
||||||
currentBuffer = 0;
|
currentBuffer = 0;
|
||||||
device_changed = false;
|
device_changed = false;
|
||||||
faud = NULL;
|
faud = nullptr;
|
||||||
mVoice = NULL;
|
mVoice = nullptr;
|
||||||
sVoice = NULL;
|
sVoice = nullptr;
|
||||||
memset(&buf, NULL, sizeof(buf));
|
memset(&buf, 0, sizeof(buf));
|
||||||
memset(&vState, NULL, sizeof(vState));
|
memset(&vState, 0, sizeof(vState));
|
||||||
f_notifier.do_register(this);
|
f_notifier.do_register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,22 +206,17 @@ void FAudio_Output::close()
|
||||||
}
|
}
|
||||||
|
|
||||||
FAudioVoice_DestroyVoice(sVoice);
|
FAudioVoice_DestroyVoice(sVoice);
|
||||||
sVoice = NULL;
|
sVoice = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if (buffers) {
|
|
||||||
free(buffers);
|
|
||||||
buffers = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mVoice) {
|
if (mVoice) {
|
||||||
FAudioVoice_DestroyVoice(mVoice);
|
FAudioVoice_DestroyVoice(mVoice);
|
||||||
mVoice = NULL;
|
mVoice = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faud) {
|
if (faud) {
|
||||||
FAudio_Release(faud);
|
FAudio_Release(faud);
|
||||||
faud = NULL;
|
faud = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,30 +244,30 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
freq = sampleRate;
|
freq_ = sampleRate;
|
||||||
// calculate the number of samples per frame first
|
// calculate the number of samples per frame first
|
||||||
// then multiply it with the size of a sample frame (16 bit * stereo)
|
// then multiply it with the size of a sample frame (16 bit * stereo)
|
||||||
soundBufferLen = (freq / 60) * 4;
|
sound_buffer_len_ = (freq_ / 60) * 4;
|
||||||
// create own buffers to store sound data because it must not be
|
// create own buffers to store sound data because it must not be
|
||||||
// manipulated while the voice plays from it
|
// manipulated while the voice plays from it.
|
||||||
buffers = (uint8_t*)malloc((bufferCount + 1) * soundBufferLen);
|
// +1 because we need one temporary buffer when all others are in use.
|
||||||
// + 1 because we need one temporary buffer when all others are in use
|
buffers_.resize((buffer_count_ + 1) * sound_buffer_len_);
|
||||||
FAudioWaveFormatEx wfx;
|
static const uint16_t kNumChannels = 2;
|
||||||
memset(&wfx, NULL, sizeof(wfx));
|
static const uint16_t kBitsPerSample = 16;
|
||||||
wfx.wFormatTag = FAUDIO_FORMAT_PCM;
|
static const uint16_t kBlockAlign = kNumChannels * (kBitsPerSample / 8);
|
||||||
wfx.nChannels = 2;
|
FAudioWaveFormatEx wfx {
|
||||||
wfx.nSamplesPerSec = freq;
|
/*.wFormatTag=*/ FAUDIO_FORMAT_PCM,
|
||||||
wfx.wBitsPerSample = 16;
|
/*.nChannels=*/kNumChannels,
|
||||||
wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
|
/*.nSamplesPerSec=*/freq_,
|
||||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
/*.nAvgBytesPerSec=*/freq_ * kBlockAlign,
|
||||||
|
/*.nBlockAlign=*/kNumChannels * (kBitsPerSample / 8),
|
||||||
|
/*.wBitsPerSample=*/kBitsPerSample,
|
||||||
|
/*.cbSize=*/0,
|
||||||
|
};
|
||||||
|
|
||||||
// create sound receiver
|
// create sound receiver
|
||||||
hr = FAudio_CreateMasteringVoice(faud,
|
hr = FAudio_CreateMasteringVoice(faud, &mVoice, FAUDIO_DEFAULT_CHANNELS,
|
||||||
&mVoice,
|
FAUDIO_DEFAULT_SAMPLERATE, 0, FAGetDev(faud), nullptr);
|
||||||
FAUDIO_DEFAULT_CHANNELS,
|
|
||||||
FAUDIO_DEFAULT_SAMPLERATE,
|
|
||||||
0,
|
|
||||||
FAGetDev(faud),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (hr != 0) {
|
if (hr != 0) {
|
||||||
wxLogError(_("FAudio: Creating mastering voice failed!"));
|
wxLogError(_("FAudio: Creating mastering voice failed!"));
|
||||||
|
@ -289,8 +276,7 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create sound emitter
|
// create sound emitter
|
||||||
//This should be FAudio_CreateSourceVoice()
|
hr = FAudio_CreateSourceVoice(faud, &sVoice, &wfx, 0, 4.0f, ¬ify, nullptr, nullptr);
|
||||||
hr = FAudio_CreateSourceVoice(faud, &sVoice, &wfx, 0, 4.0f, ¬ify, NULL, NULL);
|
|
||||||
|
|
||||||
if (hr != 0) {
|
if (hr != 0) {
|
||||||
wxLogError(_("FAudio: Creating source voice failed!"));
|
wxLogError(_("FAudio: Creating source voice failed!"));
|
||||||
|
@ -301,13 +287,8 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
if (OPTION(kSoundUpmix)) {
|
if (OPTION(kSoundUpmix)) {
|
||||||
// set up stereo upmixing
|
// set up stereo upmixing
|
||||||
FAudioDeviceDetails dd {};
|
FAudioDeviceDetails dd {};
|
||||||
//memset(&dd, NULL, sizeof(dd));
|
|
||||||
assert(FAudio_GetDeviceDetails(faud, 0, &dd) == 0);
|
assert(FAudio_GetDeviceDetails(faud, 0, &dd) == 0);
|
||||||
float* matrix = NULL;
|
std::vector<float> matrix(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels);
|
||||||
matrix = (float*)malloc(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels);
|
|
||||||
|
|
||||||
if (matrix == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool matrixAvailable = true;
|
bool matrixAvailable = true;
|
||||||
|
|
||||||
|
@ -398,12 +379,10 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matrixAvailable) {
|
if (matrixAvailable) {
|
||||||
hr = FAudioVoice_SetOutputMatrix(sVoice, NULL, 2, dd.OutputFormat.Format.nChannels, matrix, FAUDIO_DEFAULT_CHANNELS);
|
hr = FAudioVoice_SetOutputMatrix(sVoice, nullptr, 2, dd.OutputFormat.Format.nChannels,
|
||||||
|
matrix.data(), FAUDIO_DEFAULT_CHANNELS);
|
||||||
assert(hr == 0);
|
assert(hr == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(matrix);
|
|
||||||
matrix = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
|
@ -415,8 +394,7 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FAudio_Output::write(uint16_t* finalWave, int length)
|
void FAudio_Output::write(uint16_t* finalWave, int) {
|
||||||
{
|
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
if (!initialized || failed)
|
if (!initialized || failed)
|
||||||
return;
|
return;
|
||||||
|
@ -425,14 +403,14 @@ void FAudio_Output::write(uint16_t* finalWave, int length)
|
||||||
if (device_changed) {
|
if (device_changed) {
|
||||||
close();
|
close();
|
||||||
|
|
||||||
if (!init(freq))
|
if (!init(freq_))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FAudioSourceVoice_GetState(sVoice, &vState, flags);
|
FAudioSourceVoice_GetState(sVoice, &vState, flags);
|
||||||
assert(vState.BuffersQueued <= bufferCount);
|
assert(vState.BuffersQueued <= buffer_count_);
|
||||||
|
|
||||||
if (vState.BuffersQueued < bufferCount) {
|
if (vState.BuffersQueued < buffer_count_) {
|
||||||
if (vState.BuffersQueued == 0) {
|
if (vState.BuffersQueued == 0) {
|
||||||
// buffers ran dry
|
// buffers ran dry
|
||||||
if (systemVerbose & VERBOSE_SOUNDOUTPUT) {
|
if (systemVerbose & VERBOSE_SOUNDOUTPUT) {
|
||||||
|
@ -458,12 +436,12 @@ void FAudio_Output::write(uint16_t* finalWave, int length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy & protect the audio data in own memory area while playing it
|
// copy & protect the audio data in own memory area while playing it
|
||||||
memcpy(&buffers[currentBuffer * soundBufferLen], finalWave, soundBufferLen);
|
memcpy(&buffers_[currentBuffer * sound_buffer_len_], finalWave, sound_buffer_len_);
|
||||||
buf.AudioBytes = soundBufferLen;
|
buf.AudioBytes = sound_buffer_len_;
|
||||||
buf.pAudioData = &buffers[currentBuffer * soundBufferLen];
|
buf.pAudioData = &buffers_[currentBuffer * sound_buffer_len_];
|
||||||
currentBuffer++;
|
currentBuffer++;
|
||||||
currentBuffer %= (bufferCount + 1); // + 1 because we need one temporary buffer
|
currentBuffer %= (buffer_count_ + 1); // + 1 because we need one temporary buffer
|
||||||
uint32_t hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, NULL);
|
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, nullptr);
|
||||||
assert(hr == 0);
|
assert(hr == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,7 +451,7 @@ void FAudio_Output::pause()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (playing) {
|
if (playing) {
|
||||||
uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
assert(hr == 0);
|
assert(hr == 0);
|
||||||
playing = false;
|
playing = false;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +463,7 @@ void FAudio_Output::resume()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!playing) {
|
if (!playing) {
|
||||||
uint32_t hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
[[maybe_unused]] int32_t hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
assert(hr == 0);
|
assert(hr == 0);
|
||||||
playing = true;
|
playing = true;
|
||||||
}
|
}
|
||||||
|
@ -497,7 +475,7 @@ void FAudio_Output::reset()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (playing) {
|
if (playing) {
|
||||||
uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
assert(hr == 0);
|
assert(hr == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +492,8 @@ void FAudio_Output::setThrottle(unsigned short throttle_)
|
||||||
if (throttle_ == 0)
|
if (throttle_ == 0)
|
||||||
throttle_ = 100;
|
throttle_ = 100;
|
||||||
|
|
||||||
uint32_t hr = FAudioSourceVoice_SetFrequencyRatio(sVoice, (float)throttle_ / 100.0f, FAUDIO_COMMIT_NOW);
|
[[maybe_unused]] uint32_t hr =
|
||||||
|
FAudioSourceVoice_SetFrequencyRatio(sVoice, (float)throttle_ / 100.0f, FAUDIO_COMMIT_NOW);
|
||||||
assert(hr == 0);
|
assert(hr == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,15 +524,16 @@ HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::QueryInterface(REFIID riid, VO
|
||||||
} else if (__uuidof(IMMNotificationClient) == riid) {
|
} else if (__uuidof(IMMNotificationClient) == riid) {
|
||||||
*ppvInterface = (IMMNotificationClient*)this;
|
*ppvInterface = (IMMNotificationClient*)this;
|
||||||
} else {
|
} else {
|
||||||
*ppvInterface = NULL;
|
*ppvInterface = nullptr;
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId)
|
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDefaultDeviceChanged(EDataFlow flow,
|
||||||
{
|
ERole,
|
||||||
|
LPCWSTR pwstrDeviceId) {
|
||||||
if (flow == eRender && last_device.compare(pwstrDeviceId) != 0) {
|
if (flow == eRender && last_device.compare(pwstrDeviceId) != 0) {
|
||||||
last_device = pwstrDeviceId;
|
last_device = pwstrDeviceId;
|
||||||
EnterCriticalSection(&lock);
|
EnterCriticalSection(&lock);
|
||||||
|
@ -568,16 +548,26 @@ HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDefaultDeviceChanged(EDataFl
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDeviceAdded(LPCWSTR pwstrDeviceId) { return S_OK; }
|
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDeviceAdded(LPCWSTR) {
|
||||||
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDeviceRemoved(LPCWSTR pwstrDeviceId) { return S_OK; }
|
return S_OK;
|
||||||
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { return S_OK; }
|
}
|
||||||
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { return S_OK; }
|
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDeviceRemoved(LPCWSTR) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnDeviceStateChanged(LPCWSTR, DWORD) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
HRESULT STDMETHODCALLTYPE FAudio_Device_Notifier::OnPropertyValueChanged(LPCWSTR,
|
||||||
|
const PROPERTYKEY) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void FAudio_Device_Notifier::do_register(FAudio_Output* p_instance)
|
void FAudio_Device_Notifier::do_register(FAudio_Output* p_instance)
|
||||||
{
|
{
|
||||||
if (InterlockedIncrement(®istered) == 1) {
|
if (InterlockedIncrement(®istered) == 1) {
|
||||||
pEnumerator = NULL;
|
pEnumerator = nullptr;
|
||||||
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
|
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
|
||||||
|
__uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
pEnumerator->RegisterEndpointNotificationCallback(this);
|
pEnumerator->RegisterEndpointNotificationCallback(this);
|
||||||
|
@ -595,7 +585,7 @@ void FAudio_Device_Notifier::do_unregister(FAudio_Output* p_instance)
|
||||||
if (pEnumerator) {
|
if (pEnumerator) {
|
||||||
pEnumerator->UnregisterEndpointNotificationCallback(this);
|
pEnumerator->UnregisterEndpointNotificationCallback(this);
|
||||||
pEnumerator->Release();
|
pEnumerator->Release();
|
||||||
pEnumerator = NULL;
|
pEnumerator = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +607,7 @@ void FAudio_Device_Notifier::do_unregister(FAudio_Output* p_instance)
|
||||||
bool GetFADevices(wxArrayString& names, wxArrayString& ids)
|
bool GetFADevices(wxArrayString& names, wxArrayString& ids)
|
||||||
{
|
{
|
||||||
uint32_t hr;
|
uint32_t hr;
|
||||||
FAudio* fa = NULL;
|
FAudio* fa = nullptr;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
flags = FAUDIO_DEBUG_ENGINE;
|
flags = FAUDIO_DEBUG_ENGINE;
|
||||||
|
@ -629,13 +619,12 @@ bool GetFADevices(wxArrayString& names, wxArrayString& ids)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetFADevices(fa, &names, &ids, NULL);
|
GetFADevices(fa, &names, &ids, nullptr);
|
||||||
FAudio_Release(fa);
|
FAudio_Release(fa);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class Declaration
|
// Class Declaration
|
||||||
SoundDriver* newFAudio_Output()
|
std::unique_ptr<SoundDriver> newFAudio_Output() {
|
||||||
{
|
return std::make_unique<FAudio_Output>();
|
||||||
return new FAudio_Output();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ struct OPENALFNTABLE;
|
||||||
class OpenAL : public SoundDriver {
|
class OpenAL : public SoundDriver {
|
||||||
public:
|
public:
|
||||||
OpenAL();
|
OpenAL();
|
||||||
virtual ~OpenAL();
|
~OpenAL() override;
|
||||||
|
|
||||||
static bool GetDevices(wxArrayString& names, wxArrayString& ids);
|
static bool GetDevices(wxArrayString& names, wxArrayString& ids);
|
||||||
bool init(long sampleRate); // initialize the sound buffer queue
|
bool init(long sampleRate); // initialize the sound buffer queue
|
||||||
|
@ -327,10 +327,10 @@ void OpenAL::write(uint16_t* finalWave, int length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDriver* newOpenAL()
|
std::unique_ptr<SoundDriver> newOpenAL()
|
||||||
{
|
{
|
||||||
winlog("newOpenAL\n");
|
winlog("newOpenAL\n");
|
||||||
return new OpenAL();
|
return std::make_unique<OpenAL>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetOALDevices(wxArrayString& names, wxArrayString& ids)
|
bool GetOALDevices(wxArrayString& names, wxArrayString& ids)
|
||||||
|
|
|
@ -1227,7 +1227,7 @@ void systemGbBorderOn()
|
||||||
}
|
}
|
||||||
|
|
||||||
class SoundDriver;
|
class SoundDriver;
|
||||||
SoundDriver* systemSoundInit()
|
std::unique_ptr<SoundDriver> systemSoundInit()
|
||||||
{
|
{
|
||||||
soundShutdown();
|
soundShutdown();
|
||||||
|
|
||||||
|
|
|
@ -714,21 +714,21 @@ private:
|
||||||
// I should add this to SoundDriver, but wxArrayString is wx-specific
|
// I should add this to SoundDriver, but wxArrayString is wx-specific
|
||||||
// I suppose I could make subclass wxSoundDriver. maybe later.
|
// I suppose I could make subclass wxSoundDriver. maybe later.
|
||||||
class SoundDriver;
|
class SoundDriver;
|
||||||
extern SoundDriver* newOpenAL();
|
extern std::unique_ptr<SoundDriver> newOpenAL();
|
||||||
extern bool GetOALDevices(wxArrayString& names, wxArrayString& ids);
|
extern bool GetOALDevices(wxArrayString& names, wxArrayString& ids);
|
||||||
|
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
extern SoundDriver* newDirectSound();
|
extern std::unique_ptr<SoundDriver> newDirectSound();
|
||||||
extern bool GetDSDevices(wxArrayString& names, wxArrayString& ids);
|
extern bool GetDSDevices(wxArrayString& names, wxArrayString& ids);
|
||||||
#endif // defined(__WXMSW__)
|
#endif // defined(__WXMSW__)
|
||||||
|
|
||||||
#if defined(VBAM_ENABLE_XAUDIO2)
|
#if defined(VBAM_ENABLE_XAUDIO2)
|
||||||
extern SoundDriver* newXAudio2_Output();
|
extern std::unique_ptr<SoundDriver> newXAudio2_Output();
|
||||||
extern bool GetXA2Devices(wxArrayString& names, wxArrayString& ids);
|
extern bool GetXA2Devices(wxArrayString& names, wxArrayString& ids);
|
||||||
#endif // defined(VBAM_ENABLE_XAUDIO2)
|
#endif // defined(VBAM_ENABLE_XAUDIO2)
|
||||||
|
|
||||||
#if defined(VBAM_ENABLE_FAUDIO)
|
#if defined(VBAM_ENABLE_FAUDIO)
|
||||||
extern SoundDriver* newFAudio_Output();
|
extern std::unique_ptr<SoundDriver> newFAudio_Output();
|
||||||
extern bool GetFADevices(wxArrayString& names, wxArrayString& ids);
|
extern bool GetFADevices(wxArrayString& names, wxArrayString& ids);
|
||||||
#endif // defined(VBAM_ENABLE_FAUDIO)
|
#endif // defined(VBAM_ENABLE_FAUDIO)
|
||||||
|
|
||||||
|
|
|
@ -236,25 +236,20 @@ class XAudio2_Output
|
||||||
: public SoundDriver {
|
: public SoundDriver {
|
||||||
public:
|
public:
|
||||||
XAudio2_Output();
|
XAudio2_Output();
|
||||||
~XAudio2_Output();
|
~XAudio2_Output() override;
|
||||||
|
|
||||||
// Initialization
|
|
||||||
bool init(long sampleRate);
|
|
||||||
|
|
||||||
// Sound Data Feed
|
|
||||||
void write(uint16_t* finalWave, int length);
|
|
||||||
|
|
||||||
// Play Control
|
|
||||||
void pause();
|
|
||||||
void resume();
|
|
||||||
void reset();
|
|
||||||
void close();
|
|
||||||
void device_change();
|
void device_change();
|
||||||
|
|
||||||
// Configuration Changes
|
|
||||||
void setThrottle(unsigned short throttle);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// SoundDriver implementation.
|
||||||
|
bool init(long sampleRate) override;
|
||||||
|
void pause() override;
|
||||||
|
void reset() override;
|
||||||
|
void resume() override;
|
||||||
|
void write(uint16_t *finalWave, int length) override;
|
||||||
|
void setThrottle(unsigned short throttle_) override;
|
||||||
|
|
||||||
bool failed;
|
bool failed;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
bool playing;
|
bool playing;
|
||||||
|
@ -614,7 +609,7 @@ void xaudio2_device_changed(XAudio2_Output* instance)
|
||||||
instance->device_change();
|
instance->device_change();
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDriver* newXAudio2_Output()
|
std::unique_ptr<SoundDriver> newXAudio2_Output()
|
||||||
{
|
{
|
||||||
return new XAudio2_Output();
|
return std::make_unique<XAudio2_Output>();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue