openMSX
DACSound16S.cc
Go to the documentation of this file.
1 #include "DACSound16S.hh"
2 #include "DeviceConfig.hh"
3 #include "MSXMotherBoard.hh"
4 #include "DynamicClock.hh"
5 #include "serialize.hh"
6 
7 namespace openmsx {
8 
9 constexpr unsigned DUMMY_INPUT_RATE = 44100; // actual rate depends on frequency setting
10 
11 DACSound16S::DACSound16S(std::string_view name_, std::string_view desc,
12  const DeviceConfig& config)
13  : SoundDevice(config.getMotherBoard().getMSXMixer(), name_, desc, 1, DUMMY_INPUT_RATE, false)
14  , lastWrittenValue(0)
15 {
16  registerSound(config);
17 }
18 
20 {
22 }
23 
24 void DACSound16S::setOutputRate(unsigned sampleRate)
25 {
26  setInputRate(sampleRate);
27 }
28 
29 void DACSound16S::reset(EmuTime::param time)
30 {
31  writeDAC(0, time);
32 }
33 
34 void DACSound16S::writeDAC(int16_t value, EmuTime::param time)
35 {
36  int delta = value - lastWrittenValue;
37  if (delta == 0) return;
38  lastWrittenValue = value;
39 
42  blip.addDelta(t, delta);
43 }
44 
45 void DACSound16S::generateChannels(float** bufs, unsigned num)
46 {
47  // Note: readSamples() replaces the values in the buffer (it doesn't
48  // add the new values to the existing values in the buffer). That's OK
49  // because this is a single-channel SoundDevice.
50  if (!blip.readSamples<1>(bufs[0], num)) {
51  bufs[0] = nullptr;
52  }
53 }
54 
55 bool DACSound16S::updateBuffer(unsigned length, float* buffer,
56  EmuTime::param /*time*/)
57 {
58  return mixChannels(buffer, length);
59 }
60 
61 template<typename Archive>
62 void DACSound16S::serialize(Archive& ar, unsigned /*version*/)
63 {
64  // Note: It's ok to NOT serialize a DAC object if you call the
65  // writeDAC() method in some other way during de-serialization.
66  // This is for example done in MSXPPI/KeyClick.
67  int16_t lastValue = lastWrittenValue;
68  ar.serialize("lastValue", lastValue);
69  if (ar.isLoader()) {
70  writeDAC(lastValue, getHostSampleClock().getTime());
71  }
72 }
74 
75 } // namespace openmsx
T length(const vecN< N, T > &x)
Definition: gl_vec.hh:343
void unregisterSound()
Unregisters this sound device with the Mixer.
Definition: SoundDevice.cc:131
constexpr unsigned DUMMY_INPUT_RATE
A fixed point number, implemented by a 32-bit signed integer.
Definition: FixedPoint.hh:15
DACSound16S(std::string_view name, std::string_view desc, const DeviceConfig &config)
Definition: DACSound16S.cc:11
void setInputRate(unsigned sampleRate)
Definition: SoundDevice.hh:108
void reset(EmuTime::param time)
Definition: DACSound16S.cc:29
void addDelta(TimeIndex time, float delta)
Definition: BlipBuffer.cc:107
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
virtual ~DACSound16S()
Definition: DACSound16S.cc:19
bool mixChannels(float *dataOut, unsigned samples)
Calls generateChannels() and combines the output to a single channel.
Definition: SoundDevice.cc:188
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
const DynamicClock & getHostSampleClock() const
See MSXMixer::getHostSampleClock().
Definition: SoundDevice.cc:339
bool readSamples(float *out, unsigned samples)
Definition: BlipBuffer.cc:160
unsigned getTicksTill(EmuTime::param e) const
Calculate the number of ticks for this clock until the given time.
Definition: DynamicClock.hh:51
void serialize(Archive &ar, unsigned version)
Definition: DACSound16S.cc:62
TclObject t
void writeDAC(int16_t value, EmuTime::param time)
Definition: DACSound16S.cc:34
void registerSound(const DeviceConfig &config)
Registers this sound device with the Mixer.
Definition: SoundDevice.cc:90