2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file mixer.cpp Mixing of sound samples. */
13 #include "core/math_func.hpp"
14 #include "framerate_type.h"
15 #include "settings_type.h"
17 #include "safeguards.h"
23 /* pointer to allocated buffer memory */
26 /* current position in memory */
39 static MixerChannel _channels
[8];
40 static uint32 _play_rate
= 11025;
41 static uint32 _max_size
= UINT_MAX
;
42 static MxStreamCallback _music_stream
= nullptr;
43 static std::mutex _music_stream_mutex
;
46 * The theoretical maximum volume for a single sound sample. Multiple sound
47 * samples should not exceed this limit as it will sound too loud. It also
48 * stops overflowing when too many sounds are played at the same time, which
49 * causes an even worse sound quality.
51 static const int MAX_VOLUME
= 32767;
54 * Perform the rate conversion between the input and output.
55 * @param b the buffer to read the data from
56 * @param frac_pos the position from the begin of the buffer till the next element
57 * @tparam T the size of the buffer (8 or 16 bits)
58 * @return the converted value.
61 static int RateConversion(T
*b
, int frac_pos
)
63 return ((b
[0] * ((1 << 16) - frac_pos
)) + (b
[1] * frac_pos
)) >> 16;
66 static void mix_int16(MixerChannel
*sc
, int16
*buffer
, uint samples
, uint8 effect_vol
)
68 if (samples
> sc
->samples_left
) samples
= sc
->samples_left
;
69 sc
->samples_left
-= samples
;
72 const int16
*b
= (const int16
*)sc
->memory
+ sc
->pos
;
73 uint32 frac_pos
= sc
->frac_pos
;
74 uint32 frac_speed
= sc
->frac_speed
;
75 int volume_left
= sc
->volume_left
* effect_vol
/ 255;
76 int volume_right
= sc
->volume_right
* effect_vol
/ 255;
78 if (frac_speed
== 0x10000) {
79 /* Special case when frac_speed is 0x10000 */
81 buffer
[0] = Clamp(buffer
[0] + (*b
* volume_left
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
82 buffer
[1] = Clamp(buffer
[1] + (*b
* volume_right
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
85 } while (--samples
> 0);
88 int data
= RateConversion(b
, frac_pos
);
89 buffer
[0] = Clamp(buffer
[0] + (data
* volume_left
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
90 buffer
[1] = Clamp(buffer
[1] + (data
* volume_right
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
92 frac_pos
+= frac_speed
;
95 } while (--samples
> 0);
98 sc
->frac_pos
= frac_pos
;
99 sc
->pos
= b
- (const int16
*)sc
->memory
;
102 static void mix_int8_to_int16(MixerChannel
*sc
, int16
*buffer
, uint samples
, uint8 effect_vol
)
104 if (samples
> sc
->samples_left
) samples
= sc
->samples_left
;
105 sc
->samples_left
-= samples
;
108 const int8
*b
= sc
->memory
+ sc
->pos
;
109 uint32 frac_pos
= sc
->frac_pos
;
110 uint32 frac_speed
= sc
->frac_speed
;
111 int volume_left
= sc
->volume_left
* effect_vol
/ 255;
112 int volume_right
= sc
->volume_right
* effect_vol
/ 255;
114 if (frac_speed
== 0x10000) {
115 /* Special case when frac_speed is 0x10000 */
117 buffer
[0] = Clamp(buffer
[0] + (*b
* volume_left
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
118 buffer
[1] = Clamp(buffer
[1] + (*b
* volume_right
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
121 } while (--samples
> 0);
124 int data
= RateConversion(b
, frac_pos
);
125 buffer
[0] = Clamp(buffer
[0] + (data
* volume_left
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
126 buffer
[1] = Clamp(buffer
[1] + (data
* volume_right
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
128 frac_pos
+= frac_speed
;
131 } while (--samples
> 0);
134 sc
->frac_pos
= frac_pos
;
135 sc
->pos
= b
- sc
->memory
;
138 static void MxCloseChannel(MixerChannel
*mc
)
143 void MxMixSamples(void *buffer
, uint samples
)
145 PerformanceMeasurer
framerate(PFE_SOUND
);
146 static uint last_samples
= 0;
147 if (samples
!= last_samples
) {
148 framerate
.SetExpectedRate((double)_play_rate
/ samples
);
149 last_samples
= samples
;
154 /* Clear the buffer */
155 memset(buffer
, 0, sizeof(int16
) * 2 * samples
);
158 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
159 /* Fetch music if a sampled stream is available */
160 if (_music_stream
) _music_stream((int16
*)buffer
, samples
);
163 /* Apply simple x^3 scaling to master effect volume. This increases the
164 * perceived difference in loudness to better match expectations. effect_vol
165 * is expected to be in the range 0-127 hence the division by 127 * 127 to
166 * get back into range. */
167 uint8 effect_vol
= (_settings_client
.music
.effect_vol
*
168 _settings_client
.music
.effect_vol
*
169 _settings_client
.music
.effect_vol
) / (127 * 127);
171 /* Mix each channel */
172 for (mc
= _channels
; mc
!= endof(_channels
); mc
++) {
175 mix_int16(mc
, (int16
*)buffer
, samples
, effect_vol
);
177 mix_int8_to_int16(mc
, (int16
*)buffer
, samples
, effect_vol
);
179 if (mc
->samples_left
== 0) MxCloseChannel(mc
);
184 MixerChannel
*MxAllocateChannel()
187 for (mc
= _channels
; mc
!= endof(_channels
); mc
++) {
190 mc
->memory
= nullptr;
197 void MxSetChannelRawSrc(MixerChannel
*mc
, int8
*mem
, size_t size
, uint rate
, bool is16bit
)
203 mc
->frac_speed
= (rate
<< 16) / _play_rate
;
205 if (is16bit
) size
/= 2;
207 /* adjust the magnitude to prevent overflow */
208 while (size
>= _max_size
) {
210 rate
= (rate
>> 1) + 1;
213 mc
->samples_left
= (uint
)size
* _play_rate
/ rate
;
214 mc
->is16bit
= is16bit
;
218 * Set volume and pan parameters for a sound.
219 * @param mc MixerChannel to set
220 * @param volume Volume level for sound, range is 0..16384
221 * @param pan Pan position for sound, range is 0..1
223 void MxSetChannelVolume(MixerChannel
*mc
, uint volume
, float pan
)
225 /* Use sinusoidal pan to maintain overall sound power level regardless
227 mc
->volume_left
= (uint
)(sin((1.0 - pan
) * M_PI
/ 2.0) * volume
);
228 mc
->volume_right
= (uint
)(sin(pan
* M_PI
/ 2.0) * volume
);
232 void MxActivateChannel(MixerChannel
*mc
)
238 * Set source of PCM music
239 * @param music_callback Function that will be called to fill sample buffers with music data.
240 * @return Sample rate of mixer, which the buffers supplied to the callback must be rendered at.
242 uint32
MxSetMusicSource(MxStreamCallback music_callback
)
244 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
245 _music_stream
= music_callback
;
250 bool MxInitialize(uint rate
)
252 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
254 _max_size
= UINT_MAX
/ _play_rate
;
255 _music_stream
= nullptr; /* rate may have changed, any music source is now invalid */