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 MixerChannel _channels
[8];
39 static uint32_t _play_rate
= 11025;
40 static uint32_t _max_size
= UINT_MAX
;
41 static MxStreamCallback _music_stream
= nullptr;
42 static std::mutex _music_stream_mutex
;
43 static std::atomic
<uint8_t> _effect_vol
;
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;
67 static void mix_int16(MixerChannel
*sc
, int16_t *buffer
, uint samples
, uint8_t effect_vol
)
69 /* Shift required to get sample value into range for the data type. */
70 const uint SHIFT
= sizeof(T
) * CHAR_BIT
;
72 if (samples
> sc
->samples_left
) samples
= sc
->samples_left
;
73 sc
->samples_left
-= samples
;
76 const T
*b
= (const T
*)sc
->memory
+ sc
->pos
;
77 uint32_t frac_pos
= sc
->frac_pos
;
78 uint32_t frac_speed
= sc
->frac_speed
;
79 int volume_left
= sc
->volume_left
* effect_vol
/ 255;
80 int volume_right
= sc
->volume_right
* effect_vol
/ 255;
82 if (frac_speed
== 0x10000) {
83 /* Special case when frac_speed is 0x10000 */
85 buffer
[0] = Clamp(buffer
[0] + (*b
* volume_left
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
86 buffer
[1] = Clamp(buffer
[1] + (*b
* volume_right
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
89 } while (--samples
> 0);
92 int data
= RateConversion(b
, frac_pos
);
93 buffer
[0] = Clamp(buffer
[0] + (data
* volume_left
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
94 buffer
[1] = Clamp(buffer
[1] + (data
* volume_right
>> SHIFT
), -MAX_VOLUME
, MAX_VOLUME
);
96 frac_pos
+= frac_speed
;
99 } while (--samples
> 0);
102 sc
->frac_pos
= frac_pos
;
103 sc
->pos
= b
- (const T
*)sc
->memory
;
106 static void MxCloseChannel(uint8_t channel_index
)
108 _active_channels
.fetch_and(~(1 << channel_index
), std::memory_order_release
);
111 void MxMixSamples(void *buffer
, uint samples
)
113 PerformanceMeasurer
framerate(PFE_SOUND
);
114 static uint last_samples
= 0;
115 if (samples
!= last_samples
) {
116 framerate
.SetExpectedRate((double)_play_rate
/ samples
);
117 last_samples
= samples
;
120 /* Clear the buffer */
121 memset(buffer
, 0, sizeof(int16_t) * 2 * samples
);
124 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
125 /* Fetch music if a sampled stream is available */
126 if (_music_stream
) _music_stream((int16_t*)buffer
, samples
);
129 /* Apply simple x^3 scaling to master effect volume. This increases the
130 * perceived difference in loudness to better match expectations. effect_vol
131 * is expected to be in the range 0-127 hence the division by 127 * 127 to
132 * get back into range. */
133 uint8_t effect_vol_setting
= _effect_vol
.load(std::memory_order_relaxed
);
134 uint8_t effect_vol
= (effect_vol_setting
*
136 effect_vol_setting
) / (127 * 127);
138 /* Mix each channel */
139 uint8_t active
= _active_channels
.load(std::memory_order_acquire
);
140 for (uint8_t idx
: SetBitIterator(active
)) {
141 MixerChannel
*mc
= &_channels
[idx
];
143 mix_int16
<int16_t>(mc
, (int16_t*)buffer
, samples
, effect_vol
);
145 mix_int16
<int8_t>(mc
, (int16_t*)buffer
, samples
, effect_vol
);
147 if (mc
->samples_left
== 0) MxCloseChannel(idx
);
151 MixerChannel
*MxAllocateChannel()
153 uint8_t currently_active
= _active_channels
.load(std::memory_order_acquire
);
154 uint8_t available
= ~currently_active
;
155 if (available
== 0) return nullptr;
157 uint8_t channel_index
= FindFirstBit(available
);
159 MixerChannel
*mc
= &_channels
[channel_index
];
161 mc
->memory
= nullptr;
165 void MxSetChannelRawSrc(MixerChannel
*mc
, int8_t *mem
, size_t size
, uint rate
, bool is16bit
)
171 mc
->frac_speed
= (rate
<< 16) / _play_rate
;
173 if (is16bit
) size
/= 2;
175 /* adjust the magnitude to prevent overflow */
176 while (size
>= _max_size
) {
178 rate
= (rate
>> 1) + 1;
181 mc
->samples_left
= (uint
)size
* _play_rate
/ rate
;
182 mc
->is16bit
= is16bit
;
186 * Set volume and pan parameters for a sound.
187 * @param mc MixerChannel to set
188 * @param volume Volume level for sound, range is 0..16384
189 * @param pan Pan position for sound, range is 0..1
191 void MxSetChannelVolume(MixerChannel
*mc
, uint volume
, float pan
)
193 /* Use sinusoidal pan to maintain overall sound power level regardless
195 mc
->volume_left
= (uint
)(sin((1.0 - pan
) * M_PI
/ 2.0) * volume
);
196 mc
->volume_right
= (uint
)(sin(pan
* M_PI
/ 2.0) * volume
);
200 void MxActivateChannel(MixerChannel
*mc
)
202 uint8_t channel_index
= mc
- _channels
;
203 _active_channels
.fetch_or((1 << channel_index
), std::memory_order_release
);
207 * Set source of PCM music
208 * @param music_callback Function that will be called to fill sample buffers with music data.
209 * @return Sample rate of mixer, which the buffers supplied to the callback must be rendered at.
211 uint32_t MxSetMusicSource(MxStreamCallback music_callback
)
213 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
214 _music_stream
= music_callback
;
219 bool MxInitialize(uint rate
)
221 std::lock_guard
<std::mutex
> lock
{ _music_stream_mutex
};
223 _max_size
= UINT_MAX
/ _play_rate
;
224 _music_stream
= nullptr; /* rate may have changed, any music source is now invalid */
228 void SetEffectVolume(uint8_t volume
)
230 _effect_vol
.store(volume
, std::memory_order_relaxed
);