~rabbits/uxn-playdate

fed4b6e6bb0448de327eda303778de2fa6052b20 — Bad Diode 11 months ago 8a67f79
Add sample xfading
1 files changed, 23 insertions(+), 22 deletions(-)

M src/audio.c
M src/audio.c => src/audio.c +23 -22
@@ 1,6 1,6 @@
#define SOUND_TIMER (256.0f / 44100.0f * 1000.0f)
#define N_CHANNELS 4
#define ZERO_THRESHOLD 4
#define XFADE_SAMPLES 100

typedef enum EnvStage {
    ENV_ATTACK  = (1 << 0),


@@ 31,7 31,7 @@ typedef struct Sample {
typedef struct AudioChannel {
    Sample sample;
    Sample next_sample;
    bool wait_zero;
    bool xfade;
    float duration;
    float vol_l;
    float vol_r;


@@ 2608,13 2608,8 @@ note_on(AudioChannel *channel, u16 duration, u8 *data, u16 len, u8 vol,
    const float *inc = &tuning[(pitch + 1) - 21][0];
    sample.inc = *(inc + FINE_TUNE);

    // TODO: Check previously played sample instead of the envelope.
    // if (channel->sample.data != NULL && channel->sample.env.vol > 0) {
    //     channel->next_sample = sample;
    //     channel->wait_zero = true;
    // } else {
        channel->sample = sample;
    // }
    channel->next_sample = sample;
    channel->xfade = true;
}

void


@@ 2731,26 2726,32 @@ audio_handler(void *ctx, s16 *left, s16 *right, int len) {
        channel->duration -= SOUND_TIMER;

        // Process all requested samples
        int x = 0;
        if (channel->xfade) {
            float delta = 1.0f / XFADE_SAMPLES;
            for (; x < XFADE_SAMPLES; x++) {
                float alpha = x * delta;
                float beta = 1.0f - alpha;
                s16 next_a = next_a = next_sample(&channel->next_sample);
                s16 next_b = 0;
                if (channel->sample.data != NULL) {
                    next_b = next_sample(&channel->sample);
                }
                s16 next = alpha * next_a + beta * next_b;
                left[x]  += next * channel->vol_l;
                right[x] += next * channel->vol_r;
            }
            channel->sample = channel->next_sample;
            channel->xfade = false;
        }
        Sample *sample = &channel->sample;
        // TODO: Don't loop everything dummy
        sample->loop = sample->len;
        for (int x = 0; x < len; x++) {
        for (; x < len; x++) {
            if (sample->data == NULL) {
                break;
            }

            s16 next = next_sample(sample);

            left[x]  += next * channel->vol_l;
            right[x] += next * channel->vol_r;

            // if (channel->wait_zero) {
            //     if (next < ZERO_THRESHOLD && next > -ZERO_THRESHOLD) {
            //         channel->wait_zero = false;
            //         channel->sample = channel->next_sample;
            //         sample = &channel->sample;
            //     }
            // }
        }
    }
    for (int x = 0; x < len; x++) {