92 lines
2.4 KiB
C
92 lines
2.4 KiB
C
/*
|
|
Dinky fixed point oscillators.
|
|
https://git.poto.cafe/veclavtalica/stfu/src/branch/master/Source/oscillators.c
|
|
*/
|
|
|
|
#ifndef COM_SND_OSCS_H
|
|
#define COM_SND_OSCS_H
|
|
|
|
#include "../cfg.h"
|
|
#include "../fix.h"
|
|
#include "../std.h"
|
|
#include <stdint.h>
|
|
|
|
/* Intended to be executed offline with values then embedded in the binary. */
|
|
struct com_snd_swave {
|
|
uint16_t f, s, c;
|
|
};
|
|
|
|
static struct com_snd_swave
|
|
com_snd_swave_init(com_fix_t frequency, uint16_t phase, uint16_t amplitude) {
|
|
com_std_assert(frequency > 0);
|
|
struct com_snd_swave r;
|
|
r.f = 2.f * sinf((float)M_PI * frequency / STFU_AUDIO_FRAME_RATE);
|
|
r.s = amplitude * sinf(phase);
|
|
r.c = amplitude * cosf(phase);
|
|
return r;
|
|
}
|
|
|
|
static inline int16_t com_snd_swave_pump(struct com_snd_swave *wave) {
|
|
int16_t const f = com_fix_sin(com_fix_mul(
|
|
wave->phase, com_fix_div(com_fix_mul(wave->frequency, COM_FIX_PI2),
|
|
COM_CFG_SNDFRMRATE)));
|
|
wave->phase += 1;
|
|
return f;
|
|
}
|
|
|
|
/* Implemented over sinewave */
|
|
// struct com_snd_oscs_sqrtwave {
|
|
// struct com_snd_swave w;
|
|
// union {
|
|
// float f;
|
|
// uint32_t u;
|
|
// } v;
|
|
// } com_snd_oscs_init_sqrtwave(float frequency, float phase, float amplitude) {
|
|
// struct com_snd_oscs_sqrtwave r;
|
|
// union {
|
|
// float f;
|
|
// uint32_t u;
|
|
// } v, a;
|
|
// r.w = com_snd_oscs_init_sinewave(frequency, phase, 1.f);
|
|
// v.f = r.w.s;
|
|
// a.f = amplitude;
|
|
// r.v.u = (a.u & 0x7fffffff) | (v.u & 0x80000000);
|
|
// return r;
|
|
// }
|
|
|
|
// /* Use floating point bit representation to infer sign, all other bits are
|
|
// set
|
|
// * to amplitude */
|
|
// struct com_snd_oscs_sqrtwave
|
|
// com_snd_oscs_pump_sqrtwave(struct com_snd_oscs_sqrtwave wave) {
|
|
// union {
|
|
// float f;
|
|
// uint32_t u;
|
|
// } v;
|
|
// com_snd_oscs_pump_sinewave(wave.w);
|
|
// v.f = wave.w.s;
|
|
// wave.v.u = (wave.v.u & 0x7fffffff) | (v.u & 0x80000000);
|
|
// return wave;
|
|
// }
|
|
|
|
// struct com_snd_oscs_sawtooth {
|
|
// float v, a, i;
|
|
// } com_snd_oscs_init_sawtooth(float frequency, float phase, float amplitude) {
|
|
// struct com_snd_oscs_sawtooth r;
|
|
// r.v = sinf(phase) * amplitude;
|
|
// r.a = amplitude;
|
|
// r.i = 2.f * frequency / STFU_AUDIO_FRAME_RATE * amplitude;
|
|
// return r;
|
|
// }
|
|
|
|
// /* Simple amplitude overflow check with truncation */
|
|
// struct com_snd_oscs_sawtooth
|
|
// com_snd_oscs_pump_sawtooth(struct com_snd_oscs_sawtooth wave) {
|
|
// wave.v += wave.i;
|
|
// if (wave.v > wave.a)
|
|
// wave.v -= wave.a * 2.f;
|
|
// return wave;
|
|
// }
|
|
|
|
#endif
|