From 4d87b2e85f13ee9597d9646db9c388cbf6269f2b Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Mon, 31 Jul 2023 04:08:04 -0700 Subject: modules/signals: experimental signals module Playing with libs/sig in 2D, this isn't really an interesting module by itself in terms of visual output. But it might have utility as a diagnostic thing if libs/sig becomes a more used thing. At the very least, for now, it's useful for observing affects of and iterating on libs/sig development. So I'm merging this, just gated behind TIL_MODULE_EXPERIMENTAL so it's not in rtv rotation or presented as something in the usual modules list. --- src/Makefile.am | 2 +- src/modules/Makefile.am | 2 +- src/modules/signals/Makefile.am | 3 + src/modules/signals/signals.c | 199 ++++++++++++++++++++++++++++++++++++++++ src/til.c | 2 + 5 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 src/modules/signals/Makefile.am create mode 100644 src/modules/signals/signals.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 5da7150..094f295 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,7 +3,7 @@ SUBDIRS = libs modules noinst_LTLIBRARIES = libtil.la libtil_la_SOURCES = til.c til.h til_args.c til_args.h til_fb.c til_fb.h til_jenkins.c til_jenkins.h til_limits.h til_module_context.c til_module_context.h til_settings.h til_settings.c til_setup.c til_setup.h til_str.c til_str.h til_stream.c til_stream.h til_tap.h til_threads.c til_threads.h til_util.c til_util.h libtil_la_CPPFLAGS = -I@top_srcdir@/src -libtil_la_LIBADD = modules/blinds/libblinds.la modules/checkers/libcheckers.la modules/compose/libcompose.la modules/drizzle/libdrizzle.la modules/flui2d/libflui2d.la modules/julia/libjulia.la modules/meta2d/libmeta2d.la modules/mixer/libmixer.la modules/moire/libmoire.la modules/montage/libmontage.la modules/pixbounce/libpixbounce.la modules/plasma/libplasma.la modules/plato/libplato.la modules/ray/libray.la modules/rkt/librkt.la modules/roto/libroto.la modules/rtv/librtv.la modules/shapes/libshapes.la modules/snow/libsnow.la modules/sparkler/libsparkler.la modules/spiro/libspiro.la modules/stars/libstars.la modules/strobe/libstrobe.la modules/submit/libsubmit.la modules/swab/libswab.la modules/swarm/libswarm.la modules/voronoi/libvoronoi.la libs/grid/libgrid.la libs/puddle/libpuddle.la libs/ray/libray.la libs/rocket/librocket.la libs/sig/libsig.la libs/txt/libtxt.la libs/ascii/libascii.la libs/din/libdin.la +libtil_la_LIBADD = modules/blinds/libblinds.la modules/checkers/libcheckers.la modules/compose/libcompose.la modules/drizzle/libdrizzle.la modules/flui2d/libflui2d.la modules/julia/libjulia.la modules/meta2d/libmeta2d.la modules/mixer/libmixer.la modules/moire/libmoire.la modules/montage/libmontage.la modules/pixbounce/libpixbounce.la modules/plasma/libplasma.la modules/plato/libplato.la modules/ray/libray.la modules/rkt/librkt.la modules/roto/libroto.la modules/rtv/librtv.la modules/shapes/libshapes.la modules/signals/libsignals.la modules/snow/libsnow.la modules/sparkler/libsparkler.la modules/spiro/libspiro.la modules/stars/libstars.la modules/strobe/libstrobe.la modules/submit/libsubmit.la modules/swab/libswab.la modules/swarm/libswarm.la modules/voronoi/libvoronoi.la libs/grid/libgrid.la libs/puddle/libpuddle.la libs/ray/libray.la libs/rocket/librocket.la libs/sig/libsig.la libs/txt/libtxt.la libs/ascii/libascii.la libs/din/libdin.la bin_PROGRAMS = rototiller rototiller_SOURCES = fps.c fps.h main.c mem_fb.c setup.h setup.c til.h til_fb.c til_fb.h til_settings.c til_settings.h til_threads.c til_threads.h til_util.c til_util.h diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index d34e0c7..c8778c3 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -1 +1 @@ -SUBDIRS = blinds checkers compose drizzle flui2d julia meta2d mixer moire montage pixbounce plasma plato ray rkt roto rtv shapes snow sparkler spiro stars strobe submit swab swarm voronoi +SUBDIRS = blinds checkers compose drizzle flui2d julia meta2d mixer moire montage pixbounce plasma plato ray rkt roto rtv shapes signals snow sparkler spiro stars strobe submit swab swarm voronoi diff --git a/src/modules/signals/Makefile.am b/src/modules/signals/Makefile.am new file mode 100644 index 0000000..0bfe4df --- /dev/null +++ b/src/modules/signals/Makefile.am @@ -0,0 +1,3 @@ +noinst_LTLIBRARIES = libsignals.la +libsignals_la_SOURCES = signals.c +libsignals_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs diff --git a/src/modules/signals/signals.c b/src/modules/signals/signals.c new file mode 100644 index 0000000..c56c6f8 --- /dev/null +++ b/src/modules/signals/signals.c @@ -0,0 +1,199 @@ +#include +#include + +#include "til.h" +#include "til_fb.h" +#include "til_module_context.h" + +#include "sig/sig.h" + +/* Copyright (C) 2020-2022 - Vito Caputo */ + +/* 2D waveform drawings to exercise libs/sig and explore its ergonomics */ + +/* TODO: a tileable mode would be neat, where the start and end + * heights always match up for the lines... + * + * TODO: a connected-lines version would be neat as well + * + * TODO: exposing taps for influencing the signals could be fun + * too, as well as making N_SIGNALS a runtime setting. + */ + +#define N_SIGNALS 11 + +typedef struct signals_context_t { + til_module_context_t til_module_context; + sig_sig_t *signals[N_SIGNALS]; +} signals_context_t; + + +static til_module_context_t * signals_create_context(const til_module_t *module, til_stream_t *stream, unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup) +{ + signals_context_t *ctxt; + + ctxt = til_module_context_new(module, sizeof(signals_context_t), stream, seed, ticks, n_cpus, setup); + if (!ctxt) + return NULL; + + ctxt->signals[0] = sig_new_sin(sig_new_const(.5f)); /* oscillate @ .5hz */ + if (!ctxt->signals[0]) + goto err; + + ctxt->signals[1] = sig_new_sin( /* oscillate */ + sig_new_scale( /* at a scaled frequency */ + sig_new_sin(sig_new_const(.1f)),/* from another oscillator @ .1hz */ + sig_new_const(.2f), /* from .2 */ + sig_new_const(7.f) /* to 7 */ + ) + ); + if (!ctxt->signals[1]) + goto err; + + ctxt->signals[2] = sig_new_lerp( /* interpolate */ + sig_new_sin(sig_new_const(.33f)), /* a .33hz oscillator */ + sig_new_sin(sig_new_const(.15f)), /* and a .15hz oscillator */ + sig_new_sin(sig_new_const(2.f)) /* weighted by a 2hz oscillator */ + ); + if (!ctxt->signals[2]) + goto err; + + ctxt->signals[3] = sig_new_pow( /* raise */ + sig_new_sin(sig_new_const(4.f)), /* a 4hz oscillator */ + sig_new_sin(sig_new_const(.33f)) /* to the power of a .33f hz oscillator */ + ); + if (!ctxt->signals[3]) + goto err; + + ctxt->signals[4] = sig_new_mult( /* multiply */ + sig_new_sin(sig_new_const(4.f)), /* a 4hz oscillator */ + sig_new_sin(sig_new_const(1.f)) /* by a 1hz oscillator */ + ); + if (!ctxt->signals[4]) + goto err; + + ctxt->signals[5] = sig_new_lerp( /* interpolate */ + sig_ref(ctxt->signals[3]), /* signals[3] */ + sig_ref(ctxt->signals[4]), /* signals[4] */ + sig_ref(ctxt->signals[2]) /* weighted by signals[2] */ + ); + if (!ctxt->signals[5]) + goto err; + + ctxt->signals[6] = sig_new_lerp( /* interpolate */ + sig_new_inv(sig_ref(ctxt->signals[5])), /* invert of signals[5] */ + sig_new_pow(sig_ref(ctxt->signals[5]), /* with raised signals[5] */ + sig_ref(ctxt->signals[3])), /* to power of signals[3] */ + sig_ref(ctxt->signals[2]) /* weighted by signals[2] */ + ); + if (!ctxt->signals[6]) + goto err; + + ctxt->signals[7] = sig_new_mult( /* multiply */ + sig_ref(ctxt->signals[6]), /* signals[6] */ + sig_ref(ctxt->signals[5]) /* signals[5] */ + ); + if (!ctxt->signals[7]) + goto err; + + ctxt->signals[8] = sig_new_mult( /* multiply */ + sig_ref(ctxt->signals[1]), /* signals[1] */ + sig_ref(ctxt->signals[7]) /* signals[7] */ + ); + if (!ctxt->signals[8]) + goto err; + + ctxt->signals[9] = sig_new_pow( /* raise */ + sig_ref(ctxt->signals[3]), /* signals[3] */ + sig_new_scale( /* to power of scaled */ + sig_ref(ctxt->signals[7]), /* signals[7] */ + sig_new_const(.1f), /* into range .1f .. */ + sig_new_const(20.f) /* to 20.f */ + ) + ); + if (!ctxt->signals[9]) + goto err; + + ctxt->signals[10] = sig_new_lerp( /* interpolate */ + sig_ref(ctxt->signals[9]), /* signals[9] */ + sig_new_rand(), /* random noise */ + sig_new_lerp( /* weighted by interpolating */ + sig_new_inv( /* inverted ... */ + sig_ref(ctxt->signals[5])),/* signals[5] */ + sig_ref(ctxt->signals[3]), /* and signals[3] */ + sig_ref(ctxt->signals[1]) /* weighted by signals[1] */ + ) + ); + if (!ctxt->signals[10]) + goto err; + + return &ctxt->til_module_context; + +err: + for (unsigned i = 0; i < N_SIGNALS; i++) + sig_free(ctxt->signals[i]); + + free(ctxt); + + return NULL; +} + + +static void signals_destroy_context(til_module_context_t *context) +{ + signals_context_t *ctxt = (signals_context_t *)context; + + for (unsigned i = 0; i < N_SIGNALS; i++) + sig_free(ctxt->signals[i]); + + free(ctxt); +} + + +static int signals_fragmenter(til_module_context_t *context, const til_fb_fragment_t *fragment, unsigned number, til_fb_fragment_t *res_fragment) +{ + return til_fb_fragment_slice_single(fragment, N_SIGNALS, number, res_fragment); +} + + +static void signals_prepare_frame(til_module_context_t *context, til_stream_t *stream, unsigned ticks, til_fb_fragment_t **fragment_ptr, til_frame_plan_t *res_frame_plan) +{ + *res_frame_plan = (til_frame_plan_t){ .fragmenter = signals_fragmenter }; +} + + +static void signals_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr) +{ + signals_context_t *ctxt = (signals_context_t *)context; + til_fb_fragment_t *fragment = *fragment_ptr; + + til_fb_fragment_clear(fragment); + + if (fragment->number >= N_SIGNALS) + return; + + ticks >>= 2; /* move a bit slower */ + + for (unsigned x = 0, y; x < fragment->width; x++) { + float size = fragment->height - 1; + + /* This needs to compute an offset into fragment->height, + * from a 0-1 range, hence size is height - 1 to not overflow. + */ + y = size - sig_output(ctxt->signals[fragment->number], ticks + x) * size; + + til_fb_fragment_put_pixel_checked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, fragment->x + x, fragment->y + y, 0xffffffff); + } +} + + +til_module_t signals_module = { + .create_context = signals_create_context, + .destroy_context = signals_destroy_context, + .prepare_frame = signals_prepare_frame, + .render_fragment = signals_render_fragment, + .name = "signals", + .description = "2D Waveforms (threaded)", + .author = "Vito Caputo ", + .flags = TIL_MODULE_OVERLAYABLE | TIL_MODULE_EXPERIMENTAL, +}; diff --git a/src/til.c b/src/til.c index 0aa8efd..fa6d402 100644 --- a/src/til.c +++ b/src/til.c @@ -46,6 +46,7 @@ extern til_module_t rkt_module; extern til_module_t roto_module; extern til_module_t rtv_module; extern til_module_t shapes_module; +extern til_module_t signals_module; extern til_module_t snow_module; extern til_module_t sparkler_module; extern til_module_t spiro_module; @@ -75,6 +76,7 @@ static const til_module_t *modules[] = { &roto_module, &rtv_module, &shapes_module, + &signals_module, &snow_module, &sparkler_module, &spiro_module, -- cgit v1.2.3