1 /* $Id: mixer.cpp 20211 2010-07-24 10:14:39Z alberth $ */
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file mixer.cpp Mixing of sound samples. */
14 #include "core/math_func.hpp"
16 #include "safeguards.h"
21 /* pointer to allocated buffer memory */
24 /* current position in memory */
37 static MixerChannel _channels
[8];
38 static uint32 _play_rate
= 11025;
39 static uint32 _max_size
= UINT_MAX
;
42 * The theoretical maximum volume for a single sound sample. Multiple sound
43 * samples should not exceed this limit as it will sound too loud. It also
44 * stops overflowing when too many sounds are played at the same time, which
45 * causes an even worse sound quality.
47 static const int MAX_VOLUME
= 128 * 128;
50 * Perform the rate conversion between the input and output.
51 * @param b the buffer to read the data from
52 * @param frac_pos the position from the begin of the buffer till the next element
53 * @tparam T the size of the buffer (8 or 16 bits)
54 * @return the converted value.
57 static int RateConversion(T
*b
, int frac_pos
)
59 return ((b
[0] * ((1 << 16) - frac_pos
)) + (b
[1] * frac_pos
)) >> 16;
62 static void mix_int16(MixerChannel
*sc
, int16
*buffer
, uint samples
)
64 if (samples
> sc
->samples_left
) samples
= sc
->samples_left
;
65 sc
->samples_left
-= samples
;
68 const int16
*b
= (const int16
*)sc
->memory
+ sc
->pos
;
69 uint32 frac_pos
= sc
->frac_pos
;
70 uint32 frac_speed
= sc
->frac_speed
;
71 int volume_left
= sc
->volume_left
;
72 int volume_right
= sc
->volume_right
;
74 if (frac_speed
== 0x10000) {
75 /* Special case when frac_speed is 0x10000 */
77 buffer
[0] = Clamp(buffer
[0] + (*b
* volume_left
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
78 buffer
[1] = Clamp(buffer
[1] + (*b
* volume_right
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
81 } while (--samples
> 0);
84 int data
= RateConversion(b
, frac_pos
);
85 buffer
[0] = Clamp(buffer
[0] + (data
* volume_left
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
86 buffer
[1] = Clamp(buffer
[1] + (data
* volume_right
>> 16), -MAX_VOLUME
, MAX_VOLUME
);
88 frac_pos
+= frac_speed
;
91 } while (--samples
> 0);
94 sc
->frac_pos
= frac_pos
;
95 sc
->pos
= b
- (const int16
*)sc
->memory
;
98 static void mix_int8_to_int16(MixerChannel
*sc
, int16
*buffer
, uint samples
)
100 if (samples
> sc
->samples_left
) samples
= sc
->samples_left
;
101 sc
->samples_left
-= samples
;
104 const int8
*b
= sc
->memory
+ sc
->pos
;
105 uint32 frac_pos
= sc
->frac_pos
;
106 uint32 frac_speed
= sc
->frac_speed
;
107 int volume_left
= sc
->volume_left
;
108 int volume_right
= sc
->volume_right
;
110 if (frac_speed
== 0x10000) {
111 /* Special case when frac_speed is 0x10000 */
113 buffer
[0] = Clamp(buffer
[0] + (*b
* volume_left
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
114 buffer
[1] = Clamp(buffer
[1] + (*b
* volume_right
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
117 } while (--samples
> 0);
120 int data
= RateConversion(b
, frac_pos
);
121 buffer
[0] = Clamp(buffer
[0] + (data
* volume_left
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
122 buffer
[1] = Clamp(buffer
[1] + (data
* volume_right
>> 8), -MAX_VOLUME
, MAX_VOLUME
);
124 frac_pos
+= frac_speed
;
127 } while (--samples
> 0);
130 sc
->frac_pos
= frac_pos
;
131 sc
->pos
= b
- sc
->memory
;
134 static void MxCloseChannel(MixerChannel
*mc
)
139 void MxMixSamples(void *buffer
, uint samples
)
143 /* Clear the buffer */
144 memset(buffer
, 0, sizeof(int16
) * 2 * samples
);
146 /* Mix each channel */
147 for (mc
= _channels
; mc
!= endof(_channels
); mc
++) {
150 mix_int16(mc
, (int16
*)buffer
, samples
);
152 mix_int8_to_int16(mc
, (int16
*)buffer
, samples
);
154 if (mc
->samples_left
== 0) MxCloseChannel(mc
);
159 MixerChannel
*MxAllocateChannel()
162 for (mc
= _channels
; mc
!= endof(_channels
); mc
++) {
165 mc
->memory
= nullptr;
172 void MxSetChannelRawSrc(MixerChannel
*mc
, int8
*mem
, size_t size
, uint rate
, bool is16bit
)
178 mc
->frac_speed
= (rate
<< 16) / _play_rate
;
180 if (is16bit
) size
/= 2;
182 /* adjust the magnitude to prevent overflow */
183 while (size
>= _max_size
) {
185 rate
= (rate
>> 1) + 1;
188 mc
->samples_left
= (uint
)size
* _play_rate
/ rate
;
189 mc
->is16bit
= is16bit
;
193 * Set volume and pan parameters for a sound.
194 * @param mc MixerChannel to set
195 * @param volume Volume level for sound, range is 0..16384
196 * @param pan Pan position for sound, range is 0..1
198 void MxSetChannelVolume(MixerChannel
*mc
, uint volume
, float pan
)
200 /* Use sinusoidal pan to maintain overall sound power level regardless
202 mc
->volume_left
= (uint
)(sin((1.0 - pan
) * M_PI
/ 2.0) * volume
);
203 mc
->volume_right
= (uint
)(sin(pan
* M_PI
/ 2.0) * volume
);
207 void MxActivateChannel(MixerChannel
*mc
)
213 bool MxInitialize(uint rate
)
216 _max_size
= UINT_MAX
/ _play_rate
;