/* 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 /* 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