aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-28 17:17:01 +0200
committerBad Diode <bd@badd10de.dev>2021-05-28 17:17:01 +0200
commit6dce0bf202267616fc63c3b818fc9439def925a5 (patch)
tree432fea18e1352d4e97de0b7e87c24364addfb549 /src
parentbc7f470714032c9e97798a5e532517c3d01adeef (diff)
downloaduxngba-6dce0bf202267616fc63c3b818fc9439def925a5.tar.gz
uxngba-6dce0bf202267616fc63c3b818fc9439def925a5.zip
Vectorize downsample for audio mixdown
This results in 3K cycles less per sound_mix call
Diffstat (limited to 'src')
-rw-r--r--src/uxn/devices/apu.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/src/uxn/devices/apu.c b/src/uxn/devices/apu.c
index d968840..0b502f8 100644
--- a/src/uxn/devices/apu.c
+++ b/src/uxn/devices/apu.c
@@ -183,7 +183,7 @@ void sound_mix() {
183 u32 fill = 0; 183 u32 fill = 0;
184 dma_fill(mix_buffer, fill, sizeof(mix_buffer), 3); 184 dma_fill(mix_buffer, fill, sizeof(mix_buffer), 3);
185 185
186 // Mix channels into the temporary buffer. 186 // Mix channels into the temporary buffer.
187 for (size_t j = 0; j < POLYPHONY; ++j) { 187 for (size_t j = 0; j < POLYPHONY; ++j) {
188 AudioChannel *ch = &channels[j]; 188 AudioChannel *ch = &channels[j];
189 // Check if channel is active. 189 // Check if channel is active.
@@ -203,7 +203,7 @@ void sound_mix() {
203 // stopping. 203 // stopping.
204 for(size_t i = 0; i < AUDIO_BUF_LEN; i++) { 204 for(size_t i = 0; i < AUDIO_BUF_LEN; i++) {
205 // Remember we are using fixed point values. 205 // Remember we are using fixed point values.
206 mix_buffer[i] += (0x80 + (u8)ch->data[ch->pos >> 12]) * vol; 206 mix_buffer[i] += (0x80 ^ ch->data[ch->pos >> 12]) * vol;
207 ch->pos += ch->inc; 207 ch->pos += ch->inc;
208 208
209 if (ch->pos >= ch->length) { 209 if (ch->pos >= ch->length) {
@@ -223,16 +223,20 @@ void sound_mix() {
223 // Sample still have room to go, no need to check for looping or 223 // Sample still have room to go, no need to check for looping or
224 // end of sample. 224 // end of sample.
225 for(size_t i = 0; i < AUDIO_BUF_LEN; i++) { 225 for(size_t i = 0; i < AUDIO_BUF_LEN; i++) {
226 mix_buffer[i] += (0x80 + (u8)ch->data[ch->pos>>12]) * ch->vol; 226 mix_buffer[i] += (0x80 ^ ch->data[ch->pos>>12]) * vol;
227 ch->pos += ch->inc; 227 ch->pos += ch->inc;
228 } 228 }
229 } 229 }
230 } 230 }
231 231
232 // Downsample and copy to the playing buffer. 232 // Downsample and copy to the playing buffer (Vectorized).
233 for (size_t i = 0; i < AUDIO_BUF_LEN; ++i) { 233 u64 *mix = mix_buffer;
234 // >> 6 to divide off the volume, >> 2 to divide by 4 channels to 234 u32 *buf = audio.current_buffer;
235 // prevent overflow. 235 for (size_t i = 0, k = 0; i < AUDIO_BUF_LEN; i += 4, k++) {
236 audio.current_buffer[i] = mix_buffer[i] >> 8; 236 u64 x = mix[k];
237 buf[k] = (x >> 8) & 0xFF
238 | (x >> 16) & 0xFF00
239 | (x >> 24) & 0xFF0000
240 | (x >> 32) & 0xFF000000;
237 } 241 }
238} 242}