| 122 | } |
| 123 | |
| 124 | void MxMixSamples(void *buffer, uint samples) |
| 125 | { |
| 126 | PerformanceMeasurer framerate(PFE_SOUND); |
| 127 | static uint last_samples = 0; |
| 128 | if (samples != last_samples) { |
| 129 | framerate.SetExpectedRate((double)_play_rate / samples); |
| 130 | last_samples = samples; |
| 131 | } |
| 132 | |
| 133 | /* Clear the buffer */ |
| 134 | std::fill_n(static_cast<int16_t *>(buffer), 2 * samples, 0); |
| 135 | |
| 136 | { |
| 137 | std::lock_guard<std::mutex> lock{ _music_stream_mutex }; |
| 138 | /* Fetch music if a sampled stream is available */ |
| 139 | if (_music_stream) _music_stream((int16_t*)buffer, samples); |
| 140 | } |
| 141 | |
| 142 | /* Check if any channels should be stopped. */ |
| 143 | MixerChannelMask stop = _stop_channels.load(std::memory_order_acquire); |
| 144 | for (uint8_t idx : SetBitIterator(stop)) { |
| 145 | MxCloseChannel(idx); |
| 146 | } |
| 147 | |
| 148 | /* Apply simple x^3 scaling to master effect volume. This increases the |
| 149 | * perceived difference in loudness to better match expectations. effect_vol |
| 150 | * is expected to be in the range 0-127 hence the division by 127 * 127 to |
| 151 | * get back into range. */ |
| 152 | uint8_t effect_vol_setting = _effect_vol.load(std::memory_order_relaxed); |
| 153 | uint8_t effect_vol = (effect_vol_setting * |
| 154 | effect_vol_setting * |
| 155 | effect_vol_setting) / (127 * 127); |
| 156 | |
| 157 | /* Mix each channel */ |
| 158 | MixerChannelMask active = _active_channels.load(std::memory_order_acquire); |
| 159 | for (uint8_t idx : SetBitIterator(active)) { |
| 160 | MixerChannel *mc = &_channels[idx]; |
| 161 | if (mc->is16bit) { |
| 162 | mix_int16<int16_t>(mc, (int16_t*)buffer, samples, effect_vol); |
| 163 | } else { |
| 164 | mix_int16<int8_t>(mc, (int16_t*)buffer, samples, effect_vol); |
| 165 | } |
| 166 | if (mc->samples_left == 0) MxCloseChannel(idx); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | MixerChannel *MxAllocateChannel() |
| 171 | { |
no test coverage detected