2018-12-20 23:35:49 +01:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include "Utilities/types.h"
|
|
|
|
|
|
#include "Emu/System.h"
|
|
|
|
|
|
|
|
|
|
|
|
enum : u32
|
|
|
|
|
|
{
|
|
|
|
|
|
DEFAULT_AUDIO_SAMPLING_RATE = 48000,
|
|
|
|
|
|
MAX_AUDIO_BUFFERS = 64,
|
|
|
|
|
|
AUDIO_BUFFER_SAMPLES = 256
|
|
|
|
|
|
};
|
2015-01-11 00:46:10 +01:00
|
|
|
|
|
2018-12-16 18:40:50 +01:00
|
|
|
|
class AudioBackend
|
2015-01-11 00:46:10 +01:00
|
|
|
|
{
|
|
|
|
|
|
public:
|
2018-12-16 18:40:50 +01:00
|
|
|
|
enum Capabilities : u32
|
|
|
|
|
|
{
|
2018-12-27 00:12:21 +01:00
|
|
|
|
PLAY_PAUSE_FLUSH = 0x1, // Implements Play, Pause, Flush
|
|
|
|
|
|
IS_PLAYING = 0x2, // Implements IsPlaying
|
|
|
|
|
|
GET_NUM_ENQUEUED_SAMPLES = 0x4, // Implements GetNumEnqueuedSamples
|
|
|
|
|
|
SET_FREQUENCY_RATIO = 0x8, // Implements SetFrequencyRatio
|
2018-12-16 18:40:50 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
virtual ~AudioBackend() = default;
|
2015-01-11 00:46:10 +01:00
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
/*
|
|
|
|
|
|
* Pure virtual methods
|
|
|
|
|
|
*/
|
2018-12-16 18:40:50 +01:00
|
|
|
|
virtual const char* GetName() const = 0;
|
|
|
|
|
|
virtual u32 GetCapabilities() const = 0;
|
|
|
|
|
|
|
2018-12-21 02:16:54 +01:00
|
|
|
|
virtual void Open(u32 num_buffers) = 0;
|
2015-01-11 00:46:10 +01:00
|
|
|
|
virtual void Close() = 0;
|
2018-12-20 23:35:49 +01:00
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
virtual bool AddData(const void* src, u32 num_samples) = 0;
|
2018-12-16 18:40:50 +01:00
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Virtual methods - should be implemented depending on backend capabilities
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Start playing enqueued data
|
|
|
|
|
|
// Should be implemented if capabilities & PLAY_PAUSE_FLUSH
|
|
|
|
|
|
virtual void Play()
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::throw_exception("Play() not implemented");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Pause playing enqueued data
|
|
|
|
|
|
// Should be implemented if capabilities & PLAY_PAUSE_FLUSH
|
|
|
|
|
|
virtual void Pause()
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::throw_exception("Pause() not implemented");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Pause audio, and unqueue all currently queued buffers
|
|
|
|
|
|
// Should be implemented if capabilities & PLAY_PAUSE_FLUSH
|
|
|
|
|
|
virtual void Flush()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
fmt::throw_exception("Flush() not implemented");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Returns true if audio is currently being played, false otherwise
|
|
|
|
|
|
// Should be implemented if capabilities & IS_PLAYING
|
2018-12-16 18:40:50 +01:00
|
|
|
|
virtual bool IsPlaying()
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::throw_exception("IsPlaying() not implemented");
|
2018-12-21 03:13:22 +01:00
|
|
|
|
}
|
2018-12-20 23:35:49 +01:00
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
// Returns the number of currently enqueued samples
|
|
|
|
|
|
// Should be implemented if capabilities & GET_NUM_ENQUEUED_SAMPLES
|
2018-12-16 18:40:50 +01:00
|
|
|
|
virtual u64 GetNumEnqueuedSamples()
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::throw_exception("GetNumEnqueuedSamples() not implemented");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
// Sets a new frequency ratio. Backend is allowed to modify the ratio value, e.g. clamping it to the allowed range
|
|
|
|
|
|
// Returns the new frequency ratio set
|
|
|
|
|
|
// Should be implemented if capabilities & SET_FREQUENCY_RATIO
|
2018-12-21 02:16:54 +01:00
|
|
|
|
virtual f32 SetFrequencyRatio(f32 /* new_ratio */) // returns the new ratio
|
2018-12-16 22:12:58 +01:00
|
|
|
|
{
|
|
|
|
|
|
fmt::throw_exception("SetFrequencyRatio() not implemented");
|
|
|
|
|
|
return 1.0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Helper methods
|
|
|
|
|
|
*/
|
2018-12-20 23:35:49 +01:00
|
|
|
|
static u32 get_sampling_rate()
|
|
|
|
|
|
{
|
|
|
|
|
|
const u32 sampling_period_multiplier_u32 = g_cfg.audio.sampling_period_multiplier;
|
|
|
|
|
|
|
|
|
|
|
|
if (sampling_period_multiplier_u32 == 100)
|
|
|
|
|
|
return DEFAULT_AUDIO_SAMPLING_RATE;
|
|
|
|
|
|
|
|
|
|
|
|
const f32 sampling_period_multiplier = sampling_period_multiplier_u32 / 100.0f;
|
|
|
|
|
|
const f32 sampling_rate_multiplier = 1.0f / sampling_period_multiplier;
|
|
|
|
|
|
return static_cast<u32>(DEFAULT_AUDIO_SAMPLING_RATE * sampling_rate_multiplier);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static u32 get_sample_size()
|
|
|
|
|
|
{
|
|
|
|
|
|
return g_cfg.audio.convert_to_u16 ? sizeof(u16) : sizeof(float);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static u32 get_channels()
|
|
|
|
|
|
{
|
|
|
|
|
|
return g_cfg.audio.downmix_to_2ch ? 2 : 8;
|
|
|
|
|
|
}
|
2018-12-16 22:12:58 +01:00
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
bool has_capability(u32 cap) const
|
2018-12-16 22:12:58 +01:00
|
|
|
|
{
|
2018-12-21 03:13:22 +01:00
|
|
|
|
return (cap & GetCapabilities()) == cap;
|
2018-12-16 22:12:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void dump_capabilities(std::string& out) const
|
|
|
|
|
|
{
|
|
|
|
|
|
u32 count = 0;
|
|
|
|
|
|
u32 capabilities = GetCapabilities();
|
|
|
|
|
|
|
2018-12-21 03:13:22 +01:00
|
|
|
|
if (capabilities & PLAY_PAUSE_FLUSH)
|
2018-12-16 22:12:58 +01:00
|
|
|
|
{
|
2018-12-21 03:13:22 +01:00
|
|
|
|
fmt::append(out, "PLAY_PAUSE_FLUSH");
|
2018-12-16 22:12:58 +01:00
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (capabilities & IS_PLAYING)
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::append(out, "%sIS_PLAYING", count > 0 ? " | " : "");
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (capabilities & GET_NUM_ENQUEUED_SAMPLES)
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::append(out, "%sGET_NUM_ENQUEUED_SAMPLES", count > 0 ? " | " : "");
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (capabilities & SET_FREQUENCY_RATIO)
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::append(out, "%sSET_FREQUENCY_RATIO", count > 0 ? " | " : "");
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
fmt::append(out, "NONE");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2015-06-19 17:49:38 +02:00
|
|
|
|
};
|