1 /*
2  *  SPDX-License-Identifier: GPL-2.0-or-later
3  *
4  *  Copyright (C) 2020-2021  The DOSBox Staging Team
5  *  Copyright (C) 2002-2021  The DOSBox Team
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License along
18  *  with this program; if not, write to the Free Software Foundation, Inc.,
19  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #ifndef DOSBOX_MIXER_H
23 #define DOSBOX_MIXER_H
24 
25 #include "dosbox.h"
26 
27 #include <atomic>
28 #include <functional>
29 #include <memory>
30 
31 #include "envelope.h"
32 
33 typedef void (*MIXER_MixHandler)(Bit8u *sampdate, Bit32u len);
34 
35 // The mixer callback can accept a static function or a member function
36 // using a std::bind. The callback typically requests enough frames to
37 // fill one millisecond with of audio. For an audio channel running at
38 // 48000 Hz, that's 48 frames.
39 using MIXER_Handler = std::function<void(uint16_t frames)>;
40 
41 enum BlahModes {
42 	MIXER_8MONO,MIXER_8STEREO,
43 	MIXER_16MONO,MIXER_16STEREO
44 };
45 
46 enum MixerModes {
47 	M_8M,M_8S,
48 	M_16M,M_16S
49 };
50 
51 // A simple stereo audio frame
52 struct AudioFrame {
53 	float left = 0;
54 	float right = 0;
55 };
56 
57 #define MIXER_BUFSIZE (16 * 1024)
58 #define MIXER_BUFMASK (MIXER_BUFSIZE - 1)
59 extern Bit8u MixTemp[MIXER_BUFSIZE];
60 
61 #define MAX_AUDIO ((1<<(16-1))-1)
62 #define MIN_AUDIO -(1<<(16-1))
63 
64 // Get a DOS-formatted silent-sample when there's a chance it will
65 // be processed using AddSamples_nonnative()
66 template <typename T>
Mixer_GetSilentDOSSample()67 constexpr T Mixer_GetSilentDOSSample()
68 {
69 	// All signed samples are silent at true zero
70 	if (std::is_signed<T>::value)
71 		return static_cast<T>(0);
72 
73 	// unsigned 8-bit samples: silence is always 128
74 	constexpr bool is_multibyte = sizeof(T) > 1;
75 	if (!is_multibyte)
76 		return static_cast<T>(128);
77 
78 	// unsigned 16-bit samples: silence is always 32768 (little-endian)
79 	if (sizeof(T) == 2u)
80 #if defined(WORDS_BIGENDIAN)
81 		return static_cast<T>(0x0080); // 32768 (little-endian)
82 #else
83 		return static_cast<T>(0x8000); // 32768
84 #endif
85 	static_assert(sizeof(T) <= 2, "DOS only produced 8 and 16-bit samples");
86 }
87 
88 class MixerChannel {
89 public:
90 	MixerChannel(MIXER_Handler _handler, const char *name);
91 	int GetSampleRate() const;
92 	bool IsInterpolated() const;
93 	using apply_level_callback_f = std::function<void(const AudioFrame &level)>;
94 	void RegisterLevelCallBack(apply_level_callback_f cb);
95 	void SetVolume(float _left, float _right);
96 	void SetScale(float f);
97 	void SetScale(float _left, float _right);
98 	void MapChannels(Bit8u _left, Bit8u _right);
99 	void UpdateVolume();
100 	void SetFreq(int _freq);
101 	void SetPeakAmplitude(int peak);
102 	void Mix(int _needed);
103 	void AddSilence(); // Fill up until needed
104 
105 	template <class Type, bool stereo, bool signeddata, bool nativeorder>
106 	void AddSamples(uint16_t len, const Type *data);
107 
108 	void AddSamples_m8(uint16_t len, const Bit8u *data);
109 	void AddSamples_s8(uint16_t len, const Bit8u *data);
110 	void AddSamples_m8s(uint16_t len, const Bit8s *data);
111 	void AddSamples_s8s(uint16_t len, const Bit8s *data);
112 	void AddSamples_m16(uint16_t len, const Bit16s *data);
113 	void AddSamples_s16(uint16_t len, const Bit16s *data);
114 	void AddSamples_m16u(uint16_t len, const Bit16u *data);
115 	void AddSamples_s16u(uint16_t len, const Bit16u *data);
116 	void AddSamples_m32(uint16_t len, const Bit32s *data);
117 	void AddSamples_s32(uint16_t len, const Bit32s *data);
118 	void AddSamples_m16_nonnative(uint16_t len, const Bit16s *data);
119 	void AddSamples_s16_nonnative(uint16_t len, const Bit16s *data);
120 	void AddSamples_m16u_nonnative(uint16_t len, const Bit16u *data);
121 	void AddSamples_s16u_nonnative(uint16_t len, const Bit16u *data);
122 	void AddSamples_m32_nonnative(uint16_t len, const Bit32s *data);
123 	void AddSamples_s32_nonnative(uint16_t len, const Bit32s *data);
124 
125 	void AddStretched(uint16_t len, Bit16s *data); // Stretch block up into needed data
126 
127 	void FillUp();
128 	void Enable(bool should_enable);
129 	void FlushSamples();
130 
131 	float volmain[2] = {1.0f, 1.0f};
132 	std::atomic<int> done = 0; // Timing on how many samples have been done by the mixer
133 	bool is_enabled = false;
134 
135 private:
136 	// prevent default construction, copying, and assignment
137 	MixerChannel() = delete;
138 	MixerChannel(const MixerChannel &) = delete;
139 	MixerChannel &operator=(const MixerChannel &) = delete;
140 
141 	Envelope envelope;
142 	MIXER_Handler handler = nullptr;
143 	int freq_add = 0u;           // This gets added the frequency counter each mixer step
144 	int freq_counter = 0u;       // When this flows over a new sample needs to be read from the device
145 	int needed = 0u;             // Timing on how many samples were needed by the mixer
146 	int prev_sample[2] = {0, 0}; // Previous and next samples
147 	int next_sample[2] = {0, 0};
148 	// Simple way to lower the impact of DC offset. if MIXER_UPRAMP_STEPS is
149 	// >0. Still work in progress and thus disabled for now.
150 	int offset[2] = {0, 0};
151 	int sample_rate = 0u;
152 	int volmul[2] = {1, 1};
153 	float scale[2] = {1.0f, 1.0f};
154 
155 	// Defines the peak sample amplitude we can expect in this channel.
156 	// Default to signed 16bit max, however channel's that know their own
157 	// peak, like the PCSpeaker, should update it with: SetPeakAmplitude()
158 	int peak_amplitude = MAX_AUDIO;
159 
160 	uint8_t channel_map[2] = {0, 1}; // Output channel mapping
161 
162 	// The RegisterLevelCallBack() assigns this callback that can be used by
163 	// the channel's source to manage the stream's level prior to mixing,
164 	// in-place of scaling by volmain[]
165 	apply_level_callback_f apply_level = nullptr;
166 
167 	bool interpolate = false;
168 	bool last_samples_were_stereo = false;
169 	bool last_samples_were_silence = true;
170 };
171 using mixer_channel_t = std::shared_ptr<MixerChannel>;
172 
173 mixer_channel_t MIXER_AddChannel(MIXER_Handler handler, const int freq, const char *name);
174 mixer_channel_t MIXER_FindChannel(const char *name);
175 
176 /* PC Speakers functions, tightly related to the timer functions */
177 void PCSPEAKER_SetCounter(int cntr, int mode);
178 void PCSPEAKER_SetType(int mode);
179 
180 #endif
181