openMSX
MSXMixer.hh
Go to the documentation of this file.
1 #ifndef MSXMIXER_HH
2 #define MSXMIXER_HH
3 
4 #include "Schedulable.hh"
5 #include "Observer.hh"
6 #include "InfoTopic.hh"
7 #include "EmuTime.hh"
8 #include "DynamicClock.hh"
9 #include "dynarray.hh"
10 #include <vector>
11 #include <memory>
12 
13 namespace openmsx {
14 
15 class SoundDevice;
16 class Mixer;
17 class MSXMotherBoard;
18 class MSXCommandController;
19 class GlobalSettings;
20 class SpeedManager;
21 class ThrottleManager;
22 class IntegerSetting;
23 class StringSetting;
24 class BooleanSetting;
25 class Setting;
26 class AviRecorder;
27 
28 class MSXMixer final : private Schedulable, private Observer<Setting>
29  , private Observer<SpeedManager>
30  , private Observer<ThrottleManager>
31 {
32 public:
33  // See SoundDevice::getAmplificationFactor()
34  // and MSXMixer::updateVolumeParams()
35  static constexpr int AMP_BITS = 9;
36 
37 public:
38  MSXMixer(const MSXMixer&) = delete;
39  MSXMixer& operator=(const MSXMixer&) = delete;
40 
41  MSXMixer(Mixer& mixer, MSXMotherBoard& motherBoard,
42  GlobalSettings& globalSettings);
43  ~MSXMixer();
44 
53  void registerSound(SoundDevice& device, float volume,
54  int balance, unsigned numChannels);
55 
59  void unregisterSound(SoundDevice& device);
60 
65  void updateStream(EmuTime::param time);
66 
70  void updateSoftwareVolume(SoundDevice& device);
71 
78  [[nodiscard]] double getEffectiveSpeed() const;
79 
83  void setSynchronousMode(bool synchronous);
84  [[nodiscard]] bool isSynchronousMode() const { return synchronousCounter != 0; }
85 
91  void mute();
92  void unmute();
93 
94  // Called by Mixer or SoundDriver
95 
99  void setMixerParams(unsigned fragmentSize, unsigned sampleRate);
100 
110  [[nodiscard]] const DynamicClock& getHostSampleClock() const { return prevTime; }
111 
112  // Called by AviRecorder
113  [[nodiscard]] bool needStereoRecording() const;
114  void setRecorder(AviRecorder* recorder);
115 
116  // Returns the nominal host sample rate (not adjusted for speed setting)
117  [[nodiscard]] unsigned getSampleRate() const { return hostSampleRate; }
118 
119  [[nodiscard]] SoundDevice* findDevice(std::string_view name) const;
120 
121  void reInit();
122 
123 private:
124  struct SoundDeviceInfo {
125  SoundDeviceInfo(unsigned numChannels);
126 
127  SoundDevice* device = nullptr;
128  std::unique_ptr<IntegerSetting> volumeSetting;
129  std::unique_ptr<IntegerSetting> balanceSetting;
131  std::unique_ptr<StringSetting> record;
132  std::unique_ptr<BooleanSetting> mute;
133  };
134  dynarray<ChannelSettings> channelSettings;
135  float defaultVolume = 0.f;
136  float left1 = 0.f, right1 = 0.f, left2 = 0.f, right2 = 0.f;
137  };
138 
139  void updateVolumeParams(SoundDeviceInfo& info);
140  void updateMasterVolume();
141  void reschedule();
142  void reschedule2();
143  void generate(float* output, EmuTime::param time, unsigned samples);
144 
145  // Schedulable
146  void executeUntil(EmuTime::param time) override;
147 
148  // Observer<Setting>
149  void update(const Setting& setting) noexcept override;
150  // Observer<SpeedManager>
151  void update(const SpeedManager& speedManager) noexcept override;
152  // Observer<ThrottleManager>
153  void update(const ThrottleManager& throttleManager) noexcept override;
154 
155  void changeRecordSetting(const Setting& setting);
156  void changeMuteSetting(const Setting& setting);
157 
158 private:
159  unsigned fragmentSize;
160  unsigned hostSampleRate; // requested freq by sound driver,
161  // not compensated for speed
162 
163  std::vector<SoundDeviceInfo> infos;
164 
165  Mixer& mixer;
166  MSXMotherBoard& motherBoard;
167  MSXCommandController& commandController;
168 
169  IntegerSetting& masterVolume;
170  SpeedManager& speedManager;
171  ThrottleManager& throttleManager;
172 
173  DynamicClock prevTime;
174 
175  struct SoundDeviceInfoTopic final : InfoTopic {
176  explicit SoundDeviceInfoTopic(InfoCommand& machineInfoCommand);
177  void execute(span<const TclObject> tokens,
178  TclObject& result) const override;
179  [[nodiscard]] std::string help(span<const TclObject> tokens) const override;
180  void tabCompletion(std::vector<std::string>& tokens) const override;
181  } soundDeviceInfo;
182 
183  AviRecorder* recorder;
184  unsigned synchronousCounter;
185 
186  unsigned muteCount;
187  float tl0, tr0; // internal DC-filter state
188 };
189 
190 } // namespace openmsx
191 
192 #endif
BaseSetting * setting
Definition: Interpreter.cc:27
Represents a clock with a variable frequency.
Definition: DynamicClock.hh:16
This class contains settings that are used by several other class (including some singletons).
A Setting with an integer value.
void mute()
TODO This methods (un)mute the sound.
Definition: MSXMixer.cc:548
void setRecorder(AviRecorder *recorder)
Definition: MSXMixer.cc:596
void registerSound(SoundDevice &device, float volume, int balance, unsigned numChannels)
Use this method to register a given sounddevice.
Definition: MSXMixer.cc:85
void setSynchronousMode(bool synchronous)
If we're recording, we want to emulate sound at 100% emutime speed.
Definition: MSXMixer.cc:139
MSXMixer(const MSXMixer &)=delete
void updateSoftwareVolume(SoundDevice &device)
Used by SoundDevice::setSoftwareVolume()
Definition: MSXMixer.cc:724
unsigned getSampleRate() const
Definition: MSXMixer.hh:117
double getEffectiveSpeed() const
Returns the ratio of emutime-speed per realtime-speed.
Definition: MSXMixer.cc:156
SoundDevice * findDevice(std::string_view name) const
Definition: MSXMixer.cc:748
bool needStereoRecording() const
Definition: MSXMixer.cc:540
MSXMixer & operator=(const MSXMixer &)=delete
void updateStream(EmuTime::param time)
Use this method to force an 'early' call to all updateBuffer() methods.
Definition: MSXMixer.cc:161
static constexpr int AMP_BITS
Definition: MSXMixer.hh:35
const DynamicClock & getHostSampleClock() const
Clock that ticks at the exact moment(s) in time that a host sample should be generated.
Definition: MSXMixer.hh:110
bool isSynchronousMode() const
Definition: MSXMixer.hh:84
void setMixerParams(unsigned fragmentSize, unsigned sampleRate)
Set new fragment size and sample frequency.
Definition: MSXMixer.cc:582
void unregisterSound(SoundDevice &device)
Every sounddevice must unregister before it is destructed.
Definition: MSXMixer.cc:126
Generic Gang-of-Four Observer class, templatized edition.
Definition: Observer.hh:10
Every class that wants to get scheduled at some point must inherit from this class.
Definition: Schedulable.hh:34
Manages the desired ratio between emutime and real time.
Definition: SpeedManager.hh:18
Manages the throttle state of openMSX.
Definition: span.hh:126
This file implemented 3 utility functions:
Definition: Autofire.cc:9
std::unique_ptr< StringSetting > record
Definition: MSXMixer.hh:131
std::unique_ptr< BooleanSetting > mute
Definition: MSXMixer.hh:132