gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > Interleaved samples or bad code?

#161202 - Ruben - Wed Jul 30, 2008 1:33 pm

Code:
@ assuming that...
@ r3: left volume | (right volume << 16)
@ r4: ROM offset
@ r5: 22.10 offset from "ROM offset" (r4)
@ r9: mixed samples (16 bits left, 16 bits right)

add      r12, r4, r5, lsr #shift
ldrsb    r12, [r12, #0x10]
mul      r12, r3, r12
add      r9, r9, r12, asr #0x07   

That's the mixing step. After doing a small calculation (16 channels * 127 max volume * (+127 highest sample) > 65535), I *assume* that it would overflow if all 16 channels were active and mixed 127. So I used that division/shift before adding thing and this is in my mix-down/clipping loop:

Code:
.LClipLoop:
   ldrsh    ip, [r0], #0x02
   bic      ip, ip, #0xFF00
   mov      ip, ip, asr #0x02
   strb     ip, [r1], #0x01
   
   ldrsh    ip, [r0], #0x02
   mov      ip, ip, asr #0x02
   strb     ip, [r3], #0x01
   subs     r2, r2, #0x01
   bcs      .LClipLoop

So... I thought that all I would have to do is clear some bits of the left channel (which would be an overflow, I think) but I just get static. Any ideas why? Am I missing something TOTALLY obvious?

#161204 - Ruben - Wed Jul 30, 2008 1:47 pm

FOLLOWUP:
On further inspection, the right channel is perfectly fine but it's the left that has the static.

#161207 - eKid - Wed Jul 30, 2008 3:49 pm

Your problem is probably here:
Code:
add      r9, r9, r12, asr #0x07

The top value (right output) gets shifted fine (with sign extension), but the bottom value (left output) gets the bottom bits shifted out of the top value.

example:
Code:
samp = -20 [0FFFFFFECh]
vol = 127,127 [07F007F]
samp * vol = 0F613F614h (note also the 1 sample error you'll get with negative numbers)
value >> 7 = 0FFEC27ECh = 0FFEC, 27ECh = -20, 10220 :\

#161230 - Ruben - Thu Jul 31, 2008 2:11 am

Hmm... anyone have any idea what to do then? My mixer runs at 1.7% CPU per channel @ 18157Hz (any panning) which is... slow IMO.

#161232 - eKid - Thu Jul 31, 2008 4:12 am

Use unsigned samples :P

#161234 - Ruben - Thu Jul 31, 2008 4:19 am

LOL!!! Unsigned samples get rid of this problem?

#161235 - eKid - Thu Jul 31, 2008 4:28 am

Something like this:
Code:
signed sample data [-128..127]
  -20, -10, 0, 10, 20, etc
unsigned sample data [+128, or ^0x80]
  108, 118, 128, 138, 148

during calculations:
  add up volume of each channel (used to convert unsigned to signed during the mixdown)

mixing loop:

  read unsigned sample [can use ldrb which can shift the position register]
  multiply by volume [left and right]
  clear bits that will be shifted into low word [clear 0x1F0000 for 32 channels]
  add shifted value to mix [lsr#5 for 32 channels]

mixdown:

  read sample
  subtract volume total * x (x equals amount to match the mixing bit depth)
  shift sample to 8-bit
  clamp sample to -128 to 127
  write sample to output

#161678 - Ruben - Sun Aug 10, 2008 4:53 am

Hmm... well, OK... but that still doesn't answer my question! :P Is my hypothesis (WOOT! Learned a new word at school!) correct and causing an overflow, or am I just going nuts, lol?