15

Oktalyzer was a Tracker style program for Amiga, that allowed composing and playing music with 8 channels instead of the "hardware-natural" 4.

So far I learned it achieved that by splitting the 4 8-bit channels into 8 4-bit ones. But I still don't understand how it was done from 'mathematics' point of view - it doesn't seem like you can split a DAC index into two halves and have two waveforms of comparable volume overlaid.

One would range 0-16 in 1-bit increments and the other 0-256 in 16-bit increments, resulting in one being 16 times more quiet than the other. Or you could take every other bit, achieving 16-bit increments on both, but one would still be half as loud as the other, not having access to the most significant bit. How was it done in reality?

  • 1
    +1 for reminding me of trackers. – Todd Wilcox May 9 '16 at 21:05
16

According to the very same link you provided:

To perform this feat, Oktalyzer loaded eight channels in memory, mixed them in real time down to four channels, and sent the result to the Amiga sound chip. This was a processor-intensive task which degraded sound quality, but was more than made up for with doubled channels. Oktalyzer could also be run in 4-channel mode to suit more processor-heavy programs.

which makes more sense to me that splitting each channel into two 4-bit channels.

So the process is quite straightforward. During the time between two VBlank interrupts (these occurs normally each 20 ms), the CPU has to take two sample buffers, mix them and write the result to a channel buffer that will be used to feed Paula.

This is quite processor intensive, as for each sample in a 20 ms buffer, the CPU has to calculate what sample to fetch (depending upon the playing frequency), check if it reached the end of sample so it will start at repetition begin. With both samples gathered, each one has to be scaled according to its volume setting, then the CPU has to add them and possibly, apply some compression to avoid clipping while keeping the original dynamic range (adding both sample and then dividing into 2 would result in too quiet sound)

I've just digged into the source code of an early release of Oktalyzer and found this macro: (comments of my own)

GetSample:  macro
        move.b  (a0,d0.w),d4  ;get sample from buffer addressed by a0
        add.b   (a1,d1.w),d4  ;add sample from buffer addressed by a1
        eor.b   d5,d4         ;d5=-128. Fast way to add -128 to result
        move.b  d4,(a5)+      ;store result into output buffer
        swap    d0
        swap    d1
        add.l   d2,d0        ;calculate offset for next sample, buffer a0
        add.l   d3,d1        ;ditto for buffer a1
        swap    d0
        swap    d1
        endm

Which pretty does much of what I've explained (minus the volume scaling operation).

From this source code, I guess that initial buffers pointed by a0 and a1 already contain scaled samples, as there is no code in the macro to check for clipping. I also assume that these original samples are 7 bits unsigned samples. Adding them won't produce clipping, but we will end up with a 8-bit unsiged sample, which is not suitable for Paula, which expects 8-bit signed samples. To get that, we have to substract 128 from the sample value, that's to say, add -128. Adding -128 to a 8-bit number is just toggling its MSb, so d5 is preloaded with -128 and then it is XORed with the calculated sample.

  • I wonder why the code xors the results with 128 rather than simply subtracting 64 from the samples in RAM? – supercat May 9 '16 at 23:26
  • XOR with 128 is a fast way to convert from 2-complement to unsigned binary. It's the equivalent of adding 128 to the result. – mcleod_ideafix May 9 '16 at 23:59
  • Yeah, but I subtracting 64 from the audio source data would have the same effect, wouldn't it? – supercat May 10 '16 at 14:25
  • 1
    eor.b and add.b with a register actually have the exact same cycle timing on a 68000 CPU. – tofro Apr 14 '17 at 7:43
  • I'm still not understanding how different pitches are compensated for, i.e. how does it work when sample A w/ requested pitch PA is mixed with sample B at pitch PB? This is much more complex than simply multiplying according to their volume, isn't it? – DrMickeyLauer Feb 25 '19 at 9:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.