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"
16 #include "settings_type.h"
18 #include "safeguards.h"
21 /* pointer to allocated buffer memory */
24 /* current position in memory */
28 uint32_t samples_left
;
37 static std::atomic
<uint8_t> _active_channels
;
38 static std::atomic
<uint8_t> _stop_channels
;
39 static MixerChannel _channels
[8];
40 static uint32_t _play_rate
= 11025;
41 static uint32_t _max_size
= UINT_MAX
;
42 static MxStreamCallback _music_stream
= nullptr;
43 static std::mutex _music_stream_mutex
;
44 static std::atomic
<uint8_t> _effect_vol
;
47 * The theoretical maximum volume for a single sound sample. Multiple sound
48 * samples should not exceed this limit as it will sound too loud. It also
49 * stops overflowing when too many sounds are played at the same time, which
50 * causes an even worse sound quality.
52 static const int MAX_VOLUME
= 32767;
55 * Perform the rate conversion between the input and output.
56 * @param b the buffer to read the data from
57 * @param frac_pos the position from the begin of the buffer till the next element
58 * @tparam T the size of the buffer (8 or 16 bits)
59 * @return the converted value.
62 static int RateConversion(T
*b
, int frac_pos
)
64 return ((b
[0] * ((1 << 16) - frac_pos
)) + (b
[1] * frac_pos
)) >> 16;
68 static void mix_int16(MixerChannel
*sc
, int16_t *buffer
, uint samples
, uint8_t effect_vol
)
70 /* Shift required to get sample value into range for the data type. */
71 const uint SHIFT
= sizeof(T
) * CHAR_BIT
;
73 if (samples
> sc
->samples_left
) samples
= sc
->samples_left
;
74 sc
->samples_left
-= samples
;
77 const T
*b
= (const T
*)sc
->memory
+ sc
->pos
;
78 uint32_t frac_pos
= sc
->frac_pos
;
79 uint32_t frac_speed
= sc
->frac_speed
;
80 int volume_left
= sc
->volume_left
* effect_vol
/ 255;
81 int volume_right
= sc
->volume_right
* effect_vol
/ 255;
83 if (frac_speed
== 0x10000) {
84 /* Special case when frac_speed is 0x10000 */
86 buffer
[0] = Clamp(buffer
[0] + (*b
* volume_left
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
87 buffer
[1] = Clamp(buffer
[1] + (*b
* volume_right
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
90 } while (--samples
> 0);
93 int data
= RateConversion(b
, frac_pos
);
94 buffer
[0] = Clamp(buffer
[0] + (data
* volume_left
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
95 buffer
[1] = Clamp(buffer
[1] + (data
* volume_right
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
97 frac_pos
+= frac_speed
;
100 } while (--samples
> 0);
103 sc
->frac_pos
= frac_pos
;
104 sc
->pos
= b
- (const T
*)sc
->memory
;
107 static void MxCloseChannel(uint8_t channel_index
)
109 _active_channels
.fetch_and(~(1 << channel_index
), std::memory_order_release
);
113 * Close all mixer channels.
114 * This signals to the mixer that each channel should be closed even if it has not played all remaining samples.
115 * This is safe (and designed) to be called from the main thread.
117 void MxCloseAllChannels()
119 _stop_channels
.fetch_or(~0, std::memory_order_release
);
122 void MxMixSamples(void *buffer
, uint samples
)
124 PerformanceMeasurer
framerate(PFE_SOUND
);
125 static uint last_samples
= 0;
126 if (samples
!= last_samples
) {
127 framerate
.SetExpectedRate((double)_play_rate
/ samples
);
128 last_samples
= samples
;
131 /* Clear the buffer */
132 memset(buffer
, 0, sizeof(int16_t) * 2 * samples
);
135 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
136 /* Fetch music if a sampled stream is available */
137 if (_music_stream
) _music_stream((int16_t*)buffer
, samples
);
140 /* Check if any channels should be stopped. */
141 uint8_t stop
= _stop_channels
.load(std::memory_order_acquire
);
142 for (uint8_t idx
: SetBitIterator(stop
)) {
146 /* Apply simple x^3 scaling to master effect volume. This increases the
147 * perceived difference in loudness to better match expectations. effect_vol
148 * is expected to be in the range 0-127 hence the division by 127 * 127 to
149 * get back into range. */
150 uint8_t effect_vol_setting
= _effect_vol
.load(std::memory_order_relaxed
);
151 uint8_t effect_vol
= (effect_vol_setting
*
153 effect_vol_setting
) / (127 * 127);
155 /* Mix each channel */
156 uint8_t active
= _active_channels
.load(std::memory_order_acquire
);
157 for (uint8_t idx
: SetBitIterator(active
)) {
158 MixerChannel
*mc
= &_channels
[idx
];
160 mix_int16
<int16_t>(mc
, (int16_t*)buffer
, samples
, effect_vol
);
162 mix_int16
<int8_t>(mc
, (int16_t*)buffer
, samples
, effect_vol
);
164 if (mc
->samples_left
== 0) MxCloseChannel(idx
);
168 MixerChannel
*MxAllocateChannel()
170 uint8_t currently_active
= _active_channels
.load(std::memory_order_acquire
);
171 uint8_t available
= ~currently_active
;
172 if (available
== 0) return nullptr;
174 uint8_t channel_index
= FindFirstBit(available
);
176 MixerChannel
*mc
= &_channels
[channel_index
];
178 mc
->memory
= nullptr;
182 void MxSetChannelRawSrc(MixerChannel
*mc
, int8_t *mem
, size_t size
, uint rate
, bool is16bit
)
188 mc
->frac_speed
= (rate
<< 16) / _play_rate
;
190 if (is16bit
) size
/= 2;
192 /* adjust the magnitude to prevent overflow */
193 while (size
>= _max_size
) {
195 rate
= (rate
>> 1) + 1;
198 mc
->samples_left
= (uint
)size
* _play_rate
/ rate
;
199 mc
->is16bit
= is16bit
;
203 * Set volume and pan parameters for a sound.
204 * @param mc MixerChannel to set
205 * @param volume Volume level for sound, range is 0..16384
206 * @param pan Pan position for sound, range is 0..1
208 void MxSetChannelVolume(MixerChannel
*mc
, uint volume
, float pan
)
210 /* Use sinusoidal pan to maintain overall sound power level regardless
212 mc
->volume_left
= (uint
)(sin((1.0 - pan
) * M_PI
/ 2.0) * volume
);
213 mc
->volume_right
= (uint
)(sin(pan
* M_PI
/ 2.0) * volume
);
217 void MxActivateChannel(MixerChannel
*mc
)
219 uint8_t channel_index
= mc
- _channels
;
220 _stop_channels
.fetch_and(~(1 << channel_index
), std::memory_order_release
);
221 _active_channels
.fetch_or((1 << channel_index
), std::memory_order_release
);
225 * Set source of PCM music
226 * @param music_callback Function that will be called to fill sample buffers with music data.
227 * @return Sample rate of mixer, which the buffers supplied to the callback must be rendered at.
229 uint32_t MxSetMusicSource(MxStreamCallback music_callback
)
231 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
232 _music_stream
= music_callback
;
237 bool MxInitialize(uint rate
)
239 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
241 _max_size
= UINT_MAX
/ _play_rate
;
242 _music_stream
= nullptr; /* rate may have changed, any music source is now invalid */
246 void SetEffectVolume(uint8_t volume
)
248 _effect_vol
.store(volume
, std::memory_order_relaxed
);