Bits and Bytes - richardjwild/arctracker GitHub Wiki

Following on from the previous effort, I wasn't very happy with the code in the pianola_roll function, specifically this part:

printf(
        "%s %c%c%X%X | ",
        notes[event.note],
        alphanum[event.sample],
        alphanum[event.effects[0].code + 1],
        (event.effects[0].data >> 4) & 0xf,
        event.effects[0].data & 0xf);

so I refactored it to this:

channel_event_t event = line[track];
effect_t first_effect = event.effects[0];
printf(
        "%s %c%c%X%X | ",
        notes[event.note],
        alphanum[event.sample],
        alphanum[first_effect.code + 1],
        high_nybble(first_effect.data),
        low_nybble(first_effect.data));

which involved extracting two functions:

static inline
int low_nybble(const __uint8_t octet)
{
    return octet & 0xf;
}

static inline
int high_nybble(const __uint8_t octet)
{
    return (octet >> 4) & 0xf;
}

But I had already defined macros that did a similar job in other modules. This had clearly become a function in its own right, so I created a new header file called bits.h to give a home for all this stuff. I converted the low_nybble and high_nybble functions to macros and put all of them in there:

#define MASK_AND_SHIFT_RIGHT(value, mask, shift) \
(((unsigned int) (value) >> (unsigned int) (shift)) & (unsigned int) (mask))

#define MASK_5_SHIFT_RIGHT(value, shift) \
(__uint8_t) MASK_AND_SHIFT_RIGHT(value, 0x1f, shift)

#define MASK_6_SHIFT_RIGHT(value, shift) \
(__uint8_t) MASK_AND_SHIFT_RIGHT(value, 0x3f, shift)

#define MASK_8_SHIFT_RIGHT(value, shift) \
(__uint8_t) MASK_AND_SHIFT_RIGHT(value, 0xff, shift)

#define HIGH_NYBBLE(value) \
(__uint8_t) MASK_AND_SHIFT_RIGHT(value, 0xf, 4)

#define LOW_NYBBLE(value) \
(__uint8_t) MASK_AND_SHIFT_RIGHT(value, 0xf, 0)

That was a very simple job, but worth doing.

Previous: Console | Next: Separating the Formats II