mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-29 04:33:04 +00:00
Promote stereo status to template parameter.
This commit is contained in:
parent
48be7c677e
commit
a4a983eb81
@ -17,7 +17,7 @@
|
||||
namespace MOS::MOS6560 {
|
||||
|
||||
// audio state
|
||||
class AudioGenerator: public ::Outputs::Speaker::SampleSource<AudioGenerator> {
|
||||
class AudioGenerator: public ::Outputs::Speaker::SampleSource<AudioGenerator, false> {
|
||||
public:
|
||||
AudioGenerator(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
|
||||
@ -28,7 +28,6 @@ class AudioGenerator: public ::Outputs::Speaker::SampleSource<AudioGenerator> {
|
||||
void get_samples(std::size_t number_of_samples, int16_t *target);
|
||||
void skip_samples(std::size_t number_of_samples);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
||||
|
@ -66,7 +66,7 @@ enum class Personality {
|
||||
|
||||
This AY has an attached mono or stereo mixer.
|
||||
*/
|
||||
template <bool stereo> class AY38910: public ::Outputs::Speaker::SampleSource<AY38910<stereo>> {
|
||||
template <bool stereo> class AY38910: public ::Outputs::Speaker::SampleSource<AY38910<stereo>, stereo> {
|
||||
public:
|
||||
/// Creates a new AY38910.
|
||||
AY38910(Personality, Concurrency::AsyncTaskQueue<false> &);
|
||||
@ -109,7 +109,6 @@ template <bool stereo> class AY38910: public ::Outputs::Speaker::SampleSource<AY
|
||||
void get_samples(std::size_t number_of_samples, int16_t *target);
|
||||
bool is_zero_level() const;
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
static constexpr bool is_stereo = stereo;
|
||||
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &task_queue_;
|
||||
|
@ -16,14 +16,13 @@ namespace Audio {
|
||||
/*!
|
||||
Provides a sample source that can programmatically be set to one of two values.
|
||||
*/
|
||||
class Toggle: public Outputs::Speaker::SampleSource<Toggle> {
|
||||
class Toggle: public Outputs::Speaker::SampleSource<Toggle, false> {
|
||||
public:
|
||||
Toggle(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
|
||||
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
void skip_samples(const std::size_t number_of_samples);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
void set_output(bool enabled);
|
||||
bool get_output() const;
|
||||
|
@ -20,7 +20,7 @@ namespace Konami {
|
||||
and five channels of output. The original SCC uses the same wave for channels
|
||||
four and five, the SCC+ supports different waves for the two channels.
|
||||
*/
|
||||
class SCC: public ::Outputs::Speaker::SampleSource<SCC> {
|
||||
class SCC: public ::Outputs::Speaker::SampleSource<SCC, false> {
|
||||
public:
|
||||
/// Creates a new SCC.
|
||||
SCC(Concurrency::AsyncTaskQueue<false> &task_queue);
|
||||
@ -31,7 +31,6 @@ class SCC: public ::Outputs::Speaker::SampleSource<SCC> {
|
||||
/// As per ::SampleSource; provides audio output.
|
||||
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
/// Writes to the SCC.
|
||||
void write(uint16_t address, uint8_t value);
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace Yamaha::OPL {
|
||||
|
||||
template <typename Child> class OPLBase: public ::Outputs::Speaker::SampleSource<Child> {
|
||||
template <typename Child, bool stereo> class OPLBase: public ::Outputs::Speaker::SampleSource<Child, stereo> {
|
||||
public:
|
||||
void write(uint16_t address, uint8_t value) {
|
||||
if(address & 1) {
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
namespace Yamaha::OPL {
|
||||
|
||||
class OPLL: public OPLBase<OPLL> {
|
||||
class OPLL: public OPLBase<OPLL, false> {
|
||||
public:
|
||||
/// Creates a new OPLL or VRC7.
|
||||
OPLL(Concurrency::AsyncTaskQueue<false> &task_queue, int audio_divider = 1, bool is_vrc7 = false);
|
||||
@ -27,7 +27,6 @@ class OPLL: public OPLBase<OPLL> {
|
||||
/// As per ::SampleSource; provides audio output.
|
||||
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
// The OPLL is generally 'half' as loud as it's told to be. This won't strictly be true in
|
||||
// rhythm mode, but it's correct for melodic output.
|
||||
@ -37,7 +36,7 @@ class OPLL: public OPLBase<OPLL> {
|
||||
uint8_t read(uint16_t address);
|
||||
|
||||
private:
|
||||
friend OPLBase<OPLL>;
|
||||
friend OPLBase<OPLL, false>;
|
||||
void write_register(uint8_t address, uint8_t value);
|
||||
|
||||
int audio_divider_ = 0;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace TI {
|
||||
|
||||
class SN76489: public Outputs::Speaker::SampleSource<SN76489> {
|
||||
class SN76489: public Outputs::Speaker::SampleSource<SN76489, false> {
|
||||
public:
|
||||
enum class Personality {
|
||||
SN76489,
|
||||
@ -31,7 +31,6 @@ class SN76489: public Outputs::Speaker::SampleSource<SN76489> {
|
||||
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||
bool is_zero_level() const;
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
private:
|
||||
int master_divider_ = 0;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
namespace Apple::IIgs::Sound {
|
||||
|
||||
class GLU: public Outputs::Speaker::SampleSource<GLU> {
|
||||
class GLU: public Outputs::Speaker::SampleSource<GLU, false> { // TODO: isn't this stereo?
|
||||
public:
|
||||
GLU(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
|
||||
@ -37,7 +37,6 @@ class GLU: public Outputs::Speaker::SampleSource<GLU> {
|
||||
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
void skip_samples(const std::size_t number_of_samples);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
||||
|
@ -23,7 +23,7 @@ namespace Apple::Macintosh {
|
||||
Designed to be clocked at half the rate of the real hardware — i.e.
|
||||
a shade less than 4Mhz.
|
||||
*/
|
||||
class Audio: public ::Outputs::Speaker::SampleSource<Audio> {
|
||||
class Audio: public ::Outputs::Speaker::SampleSource<Audio, false> {
|
||||
public:
|
||||
Audio(Concurrency::AsyncTaskQueue<false> &task_queue);
|
||||
|
||||
@ -53,7 +53,6 @@ class Audio: public ::Outputs::Speaker::SampleSource<Audio> {
|
||||
void get_samples(std::size_t number_of_samples, int16_t *target);
|
||||
bool is_zero_level() const;
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
constexpr static bool is_stereo = false;
|
||||
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &task_queue_;
|
||||
|
@ -17,7 +17,7 @@ namespace Atari2600 {
|
||||
// will give greater resolution to changes in audio state. 1, 2 and 19 are the only divisors of 38.
|
||||
constexpr int CPUTicksPerAudioTick = 2;
|
||||
|
||||
class TIASound: public Outputs::Speaker::SampleSource<TIASound> {
|
||||
class TIASound: public Outputs::Speaker::SampleSource<TIASound, false> {
|
||||
public:
|
||||
TIASound(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
|
||||
@ -28,7 +28,6 @@ class TIASound: public Outputs::Speaker::SampleSource<TIASound> {
|
||||
// To satisfy ::SampleSource.
|
||||
void get_samples(std::size_t number_of_samples, int16_t *target);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace Electron {
|
||||
|
||||
class SoundGenerator: public ::Outputs::Speaker::SampleSource<SoundGenerator> {
|
||||
class SoundGenerator: public ::Outputs::Speaker::SampleSource<SoundGenerator, false> {
|
||||
public:
|
||||
SoundGenerator(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
|
||||
@ -27,7 +27,6 @@ class SoundGenerator: public ::Outputs::Speaker::SampleSource<SoundGenerator> {
|
||||
void get_samples(std::size_t number_of_samples, int16_t *target);
|
||||
void skip_samples(std::size_t number_of_samples);
|
||||
void set_sample_volume_range(std::int16_t range);
|
||||
static constexpr bool is_stereo = false;
|
||||
|
||||
private:
|
||||
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
||||
|
@ -26,7 +26,7 @@ enum class Interrupt: uint8_t {
|
||||
/*!
|
||||
Models the audio-production subset of Dave's behaviour.
|
||||
*/
|
||||
class Audio: public Outputs::Speaker::SampleSource<Audio> {
|
||||
class Audio: public Outputs::Speaker::SampleSource<Audio, true> {
|
||||
public:
|
||||
Audio(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||
|
||||
@ -37,7 +37,6 @@ class Audio: public Outputs::Speaker::SampleSource<Audio> {
|
||||
|
||||
// MARK: - SampleSource.
|
||||
void set_sample_volume_range(int16_t range);
|
||||
static constexpr bool is_stereo = true;
|
||||
void get_samples(std::size_t number_of_samples, int16_t *target);
|
||||
|
||||
private:
|
||||
|
@ -31,7 +31,7 @@ template <typename... S> constexpr bool is_stereo() {
|
||||
An owner may optionally assign relative volumes.
|
||||
*/
|
||||
template <typename... T> class CompoundSource:
|
||||
public Outputs::Speaker::SampleSource<CompoundSource<T...>> {
|
||||
public Outputs::Speaker::SampleSource<CompoundSource<T...>, ::Outputs::Speaker::is_stereo<T...>()> {
|
||||
private:
|
||||
template <typename... S> class CompoundSourceHolder {
|
||||
public:
|
||||
@ -57,6 +57,8 @@ template <typename... T> class CompoundSource:
|
||||
public:
|
||||
CompoundSourceHolder(S &source, R &...next) : source_(source), next_source_(next...) {}
|
||||
|
||||
static constexpr bool is_stereo = S::is_stereo || CompoundSourceHolder<R...>::is_stereo;
|
||||
|
||||
template <bool output_stereo> void get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
||||
// Get the rest of the output.
|
||||
next_source_.template get_samples<output_stereo>(number_of_samples, target);
|
||||
@ -107,8 +109,6 @@ template <typename... T> class CompoundSource:
|
||||
return 1 + CompoundSourceHolder<R...>::size();
|
||||
}
|
||||
|
||||
static constexpr bool is_stereo = S::is_stereo || CompoundSourceHolder<R...>::is_stereo;
|
||||
|
||||
double total_scale(double *volumes) const {
|
||||
return (volumes[0] / source_.average_output_peak()) + next_source_.total_scale(&volumes[1]);
|
||||
}
|
||||
@ -128,7 +128,7 @@ template <typename... T> class CompoundSource:
|
||||
}
|
||||
|
||||
void get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
||||
source_holder_.template get_samples<is_stereo>(number_of_samples, target);
|
||||
source_holder_.template get_samples<::Outputs::Speaker::is_stereo<T...>()>(number_of_samples, target);
|
||||
}
|
||||
|
||||
void skip_samples(const std::size_t number_of_samples) {
|
||||
@ -155,11 +155,6 @@ template <typename... T> class CompoundSource:
|
||||
average_output_peak_ = 1.0 / source_holder_.total_scale(volumes_.data());
|
||||
}
|
||||
|
||||
/*!
|
||||
@c true if any of the sources owned by this CompoundSource is stereo.
|
||||
*/
|
||||
static constexpr bool is_stereo = ::Outputs::Speaker::is_stereo<T...>();
|
||||
|
||||
/*!
|
||||
@returns the average output peak given the sources owned by this CompoundSource and the
|
||||
current relative volumes.
|
||||
|
@ -23,13 +23,13 @@ template <> struct SampleT<false> { using type = std::int16_t; };
|
||||
This optional base class provides the interface expected to be exposed
|
||||
by the template parameter to LowpassSpeaker.
|
||||
*/
|
||||
template <typename SourceT>
|
||||
template <typename SourceT, bool stereo>
|
||||
class SampleSource {
|
||||
public:
|
||||
/*!
|
||||
Indicates whether this component will write stereo samples.
|
||||
*/
|
||||
static constexpr bool is_stereo = SourceT::is_stereo;
|
||||
static constexpr bool is_stereo = stereo;
|
||||
|
||||
/*!
|
||||
Should write the next @c number_of_samples to @c target.
|
||||
@ -56,7 +56,7 @@ class SampleSource {
|
||||
implementation below.
|
||||
*/
|
||||
void skip_samples(const std::size_t number_of_samples) {
|
||||
if constexpr (&SourceT::advance == &SampleSource<SourceT>::advance) {
|
||||
if constexpr (&SourceT::advance == &SampleSource<SourceT, stereo>::advance) {
|
||||
return;
|
||||
}
|
||||
std::int16_t scratch_pad[number_of_samples];
|
||||
|
Loading…
x
Reference in New Issue
Block a user