//filter-slfi-random.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-2015 * * This file is part of roard a part of RoarAudio, * a cross-platform sound system for both, home and professional use. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * RoarAudio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include #include #define MAX_CHANNELS 64 struct slfi_channel { ssize_t channel; int32_t time_end; int32_t time_cur; int32_t time_max; uint8_t value_start; uint8_t value_end; }; struct slfi_random { struct slfi_channel channel[MAX_CHANNELS]; size_t channel_len; }; static inline void parse_range(ssize_t * channel, ssize_t * channel_stop, const char * str) { char * delm; char * buf; if ( strstr(str, "-") == NULL ) { *channel = atoi(str); *channel_stop = *channel; return; } buf = roar_mm_strdup(str); if ( buf == NULL ) { ROAR_WARN("Can not allocate memory: %s", roar_errorstring); *channel = 0; *channel_stop = 0; return; } delm = strstr(buf, "-"); *delm = 0; delm++; *channel = atoi(buf); *channel_stop = atoi(delm); if ( *channel_stop < *channel ) *channel_stop = *channel; roar_mm_free(buf); } static int __init(struct roar_slfi_inst * inst, const struct roar_keyval * para, ssize_t paralen) { struct slfi_random * self = roar_mm_malloc(sizeof(struct slfi_random)); const struct roar_keyval * kv; ssize_t i; int32_t time_max = 2000000L; ssize_t channel, channel_stop; if ( self == NULL ) return -1; memset(self, 0, sizeof(*self)); inst->userdata = self; for (i = 0; i < (ssize_t)MAX_CHANNELS; i++) { self->channel[i].channel = -1; self->channel[i].time_end = 0; self->channel[i].time_cur = 0; self->channel[i].value_start = 0; } for (i = 0; i < paralen; i++) { kv = &(para[i]); if ( kv->key == NULL || kv->value == NULL ) continue; if ( !strcmp(kv->key, "time-max") ) { time_max = roar_str2usec(kv->value); if ( time_max < 0 ) time_max = 2000000L; } else if ( !strcmp(kv->key, "channel") ) { parse_range(&channel, &channel_stop, kv->value); for (; channel <= channel_stop; channel++) { if ( self->channel_len == MAX_CHANNELS ) { ROAR_WARN("__init(*): Can not add (list is full) channel: %s", kv->value); continue; } self->channel[self->channel_len].channel = channel; self->channel[self->channel_len].time_max = time_max; self->channel_len++; } } else { ROAR_WARN("__init(*): Unknown parameter: %s", kv->key); } } return 0; } static inline void calc_end(struct slfi_channel * channel) { if ( channel->time_cur <= channel->time_end ) return; channel->time_cur = 0; channel->time_end = (int32_t)1 + (int32_t)roar_random_uint16() * ((channel->time_max-1) / 65536L); channel->value_start = channel->value_end; if ( roar_random_uint16() < 32768 ) return; channel->value_end = roar_random_uint16() & 0xE0; } static inline uint8_t calc_channel(struct slfi_channel * channel) { double trel = (double)channel->time_cur/(double)channel->time_end; double valdiff = (double)(channel->value_end - channel->value_start)*trel; valdiff += (double)channel->value_start; return (uint8_t)(unsigned int)(int)valdiff; } static int __update(struct roar_slfi_inst * inst, uint8_t * universe, ssize_t size_of_universe, int32_t usecspassed, const uint8_t * event, size_t eventlen) { struct slfi_random * self = inst->userdata; struct slfi_channel * channel; size_t i; (void)inst, (void)event, (void)eventlen; for (i = 0; i < self->channel_len; i++) { channel = &(self->channel[i]); if ( channel->channel >= size_of_universe ) { ROAR_WARN("__update(*): Universe too small for filter."); continue; } calc_end(channel); universe[channel->channel] = calc_channel(channel); channel->time_cur += usecspassed; } return 0; } static const struct roar_slfi_filter filter[1] = { { .name = "random", .description = "Random SLFI filter", .flags = ROAR_SLFI_FLAG_ON_UPDATE, .init = __init, .uninit = NULL, .update = __update, .ctl = NULL } }; ROAR_DL_PLUGIN_REG_SLFI(filter); // This is the plugin control block. ROAR_DL_PLUGIN_START(filter_slfi_random) { // Here we set the name and vendor of our plugin. // If you have no Vendor ID you need to use ROAR_DL_PLUGIN_META_PRODUCT_NV(). ROAR_DL_PLUGIN_META_PRODUCT_NIV("filter-slfi-random", ROAR_VID_ROARAUDIO, ROAR_VNAME_ROARAUDIO); // This sets the version of your plugin. ROAR_DL_PLUGIN_META_VERSION(ROAR_VERSION_STRING); // This sets the license of your plugin. // If there is no tag for the license you use you can just // use ROAR_DL_PLUGIN_META_LICENSE(). ROAR_DL_PLUGIN_META_LICENSE_TAG(GPLv3_0); // This sets the author and contact infos. // There are several other macros to do this with other parameters. // See ROAR_DL_PLUGIN_META_CONTACT*() in the header or documentation. ROAR_DL_PLUGIN_META_CONTACT_FLNE("Philipp", "Schafft", "ph3-der-loewe", "lion@lion.leolix.org"); // This sets the description for your plugin. ROAR_DL_PLUGIN_META_DESC("This plugin sets random values. It can be used for fireflies or moodlights"); // Load filters. ROAR_DL_PLUGIN_REG_FNFUNC(ROAR_DL_FN_FILTER); // This is the end of the control block. } ROAR_DL_PLUGIN_END //ll