Mercurial > repos > simple16
diff src/audio.c @ 24:4c9dbfa30a66
Implemented audio
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 31 Mar 2016 00:07:37 -0700 |
parents | |
children | 23bea9b9569f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/audio.c Thu Mar 31 00:07:37 2016 -0700 @@ -0,0 +1,69 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include "audio.h" +#include "system.h" + +#define BUFFER_INC_RES 1000000000UL + +audio *alloc_audio(uint32_t master_clock, uint32_t clock_div, int sample_rate, int buffer_size) +{ + size_t alloc_size = sizeof(audio) + buffer_size * sizeof(int16_t) * 2; + audio *context = malloc(alloc_size); + memset(context, 0, alloc_size); + context->writebuffer = context->buffer; + context->playbuffer = context->buffer + buffer_size; + + context->buffer_size = buffer_size; + context->clock_inc = clock_div; + context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)sample_rate) / (uint64_t)master_clock) * clock_div; + for (int i = 0; i < NUM_CHANNELS; i++) + { + context->value[i] = context->volume[i] << 5; + } +} + +void audio_run(audio *context, uint32_t target) +{ + while (context->cycles < target) + { + for (int i = 0; i < 4; i++) + { + if (context->timer_cur[i]) { + context->timer_cur[i]--; + if (!context->timer_cur[i]) { + context->value[i] = context->value[i] ? 0 : (context->volume[i] << 5); + } + } else { + context->timer_cur[i] = context->timer_load[i]; + } + } + context->buffer_fraction += context->buffer_inc; + if (context->buffer_fraction >= BUFFER_INC_RES) { + context->buffer_fraction -= BUFFER_INC_RES; + context->writebuffer[context->buffer_pos++] = + context->value[0] + context->value[1] + context->value[2] + context->value[3]; + if (context->buffer_pos == context->buffer_size) { + int16_t *tmp = context->playbuffer; + context->playbuffer = context->writebuffer; + context->writebuffer = tmp; + system_present_audio(context->playbuffer); + context->buffer_pos = 0; + } + } + context->cycles += context->clock_inc; + } +} + +void audio_write_freq(audio *context, int channel, uint16_t value) +{ + context->timer_cur[channel] = context->timer_load[channel] = value; +} + +void audio_write_vol(audio *context, int pair, uint16_t value) +{ + int channel = pair * 2; + context->value[channel] = context->volume[channel] = value >> 8; + channel++; + context->value[channel] = context->volume[channel] = value; +}