#include #include #include #include #include #include "gifenc/gifenc.h" #define NOTE 440 #define AUDIO_FRAME_RATE 44100 #define LENGTH (AUDIO_FRAME_RATE / NOTE) #define WIDTH LENGTH * 4 #define HEIGHT 128 #define RED 0 #define GREEN 0 #define BLUE 255 static struct sinewave { float f, s, c; } init_sinewave(float frequency, float phase, float amplitude) { struct sinewave r; r.f = 2.f * sinf((float)M_PI * frequency / (float)AUDIO_FRAME_RATE); r.s = amplitude * sinf(phase); r.c = amplitude * cosf(phase); return r; } static float pump_sinewave(struct sinewave *wave) { wave->s -= wave->f * wave->c; wave->c += wave->f * wave->s; return wave->s; } static struct sqrtwave { struct sinewave w; union { float f; uint32_t u; } v; } init_sqrtwave(float frequency, float phase, float amplitude) { struct sqrtwave r; union { float f; uint32_t u; } v, a; r.w = 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; } static float pump_sqrtwave(struct sqrtwave *wave) { union { float f; uint32_t u; } v; pump_sinewave(&wave->w); v.f = wave->w.s; wave->v.u = (wave->v.u & 0x7fffffff) | (v.u & 0x80000000); return wave->v.f; } static struct sawtwave { float v, a, i; } init_sawtwave(float frequency, float phase, float amplitude) { struct sawtwave r; r.v = sinf(phase) * amplitude; r.a = amplitude; r.i = 2.f * frequency / AUDIO_FRAME_RATE * amplitude; return r; } static float pump_sawtwave(struct sawtwave *wave) { wave->v += wave->i; if (wave->v > wave->a) wave->v -= wave->a * 2.f; return wave->v; } static int absi(int v) { return v > 0 ? v : -v; } static void plot_line(uint8_t *frame, int x, int xt, int y, int yt) { int dx = xt - x; int dy = yt - y; int step = absi(dx) >= absi(dy) ? absi(dx) : absi(dy); dx /= step; dy /= step; int xc = x; int yc = y; int i = 1; while (i <= step) { frame[xc + yc * WIDTH] = 1; xc += dx; yc += dy; i++; } } static void generate_wave(char const *filepath, void *generator, float (*pumper)(void *)) { float wave[LENGTH]; for (int i = 0; i < LENGTH; ++i) { wave[i] = pumper(generator); } uint8_t palette[6] = { [3] = RED, [4] = GREEN, [5] = BLUE }; ge_GIF *g = ge_new_gif(filepath, WIDTH, HEIGHT, palette, 1, 0, 0); assert(g); for (int f = 0; f < LENGTH; ++f) { memset(g->frame, 0, WIDTH * HEIGHT); for (int i = 0; i < WIDTH; ++i) { int l0 = (int)((wave[(f + i) % LENGTH] + 1.0f) * 127.5f) / 2; int l1 = (int)((wave[(f + i + 1) % LENGTH] + 1.0f) * 127.5f) / 2; if (i == WIDTH - 1) g->frame[i + l0 * WIDTH] = 1; else plot_line(g->frame, i, i + 1, l0, l1); } ge_add_frame(g, 1); } ge_close_gif(g); } int main(void) { struct sinewave sine = init_sinewave((float)NOTE, 0.0f, 1.0f); generate_wave(".dynamic/sine.gif", &sine, pump_sinewave); struct sqrtwave sqrt = init_sqrtwave((float)NOTE, 0.0f, 1.0f); generate_wave(".dynamic/sqrt.gif", &sqrt, pump_sqrtwave); struct sawtwave sawt = init_sawtwave((float)NOTE, 0.0f, 1.0f); generate_wave(".dynamic/sawt.gif", &sawt, pump_sawtwave); return 0; }