1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-18 13:29:41 +00:00

Promote stereo status to template parameter.

This commit is contained in:
Thomas Harte 2024-02-08 15:21:47 -05:00
parent 48be7c677e
commit a4a983eb81
14 changed files with 20 additions and 36 deletions

View File

@ -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_;

View File

@ -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_;

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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_;

View File

@ -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_;

View File

@ -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_;

View File

@ -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_;

View File

@ -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:

View File

@ -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.

View File

@ -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];