This specifically is for APU volumes, but in the end, this is general 6502 and math, so that's why I'm posting it here instead of the music forum.

Basically, I want to be able to scale volumes linearly.

For example, at scale 0 (full scale, i.e. identity), we have:

[code]0123456789ABCDEF[/acode]

At scale "F" (silent), we have:

[code]000000000000000[/code]

At scale "E", I would like:

[code]011111111111111[/code]

so at scale 7, I want:

[code]0112233445566778[/code]

The method I currently have mapped out for this task is through integration (to keep the table small). First, if the volume is 0, we just leave it at 0. Second, if scale is 0, we leave the volume untouched. That means, I have a table with 15 entries, each entry having 15 bits (plus an extra bit for padding), so that's a 30 byte LUT.

So if I have volume V, and I want to scale V to scale 7, I look at entry 7 at my LUT, which is:

[code]010101010101010x - x being the padding[/code]

Now I need to do my integration, and I'll do it like this:

[code]Copy LUT entry to scratch memory

OUT = V

Do {

ASL copy of LUT entry

If (Carry)

Subtract 1 from OUT

Loop (V-1) Times

OUT = Volume[/code]

This gives me the result I want, but in the worst case scenario, this code will be running 3 times (squares + noise) per frame, and that loop will have up to 14 iterations. Yes, I do realize there are ways to optimize the pseudo code for 6502, but I want to know if there's a more efficient way to scale my volumes.

I realize I can just simply subtract the scaler from the input volume, but that's not linear, and the channel volumes will be out of proportion with each other nearly all the time.

Is there a better way to do this, or am I being too confusing?

Basically, I want to be able to scale volumes linearly.

For example, at scale 0 (full scale, i.e. identity), we have:

[code]0123456789ABCDEF[/acode]

At scale "F" (silent), we have:

[code]000000000000000[/code]

At scale "E", I would like:

[code]011111111111111[/code]

so at scale 7, I want:

[code]0112233445566778[/code]

The method I currently have mapped out for this task is through integration (to keep the table small). First, if the volume is 0, we just leave it at 0. Second, if scale is 0, we leave the volume untouched. That means, I have a table with 15 entries, each entry having 15 bits (plus an extra bit for padding), so that's a 30 byte LUT.

So if I have volume V, and I want to scale V to scale 7, I look at entry 7 at my LUT, which is:

[code]010101010101010x - x being the padding[/code]

Now I need to do my integration, and I'll do it like this:

[code]Copy LUT entry to scratch memory

OUT = V

Do {

ASL copy of LUT entry

If (Carry)

Subtract 1 from OUT

Loop (V-1) Times

OUT = Volume[/code]

This gives me the result I want, but in the worst case scenario, this code will be running 3 times (squares + noise) per frame, and that loop will have up to 14 iterations. Yes, I do realize there are ways to optimize the pseudo code for 6502, but I want to know if there's a more efficient way to scale my volumes.

I realize I can just simply subtract the scaler from the input volume, but that's not linear, and the channel volumes will be out of proportion with each other nearly all the time.

Is there a better way to do this, or am I being too confusing?