diff options
Diffstat (limited to 'plugins/dumb/dumb-kode54/src/sigtypes/sample.c')
-rw-r--r-- | plugins/dumb/dumb-kode54/src/sigtypes/sample.c | 680 |
1 files changed, 340 insertions, 340 deletions
diff --git a/plugins/dumb/dumb-kode54/src/sigtypes/sample.c b/plugins/dumb/dumb-kode54/src/sigtypes/sample.c index 4695de91..d810958e 100644 --- a/plugins/dumb/dumb-kode54/src/sigtypes/sample.c +++ b/plugins/dumb/dumb-kode54/src/sigtypes/sample.c @@ -1,340 +1,340 @@ -/* _______ ____ __ ___ ___
- * \ _ \ \ / \ / \ \ / / ' ' '
- * | | \ \ | | || | \/ | . .
- * | | | | | | || ||\ /| |
- * | | | | | | || || \/ | | ' ' '
- * | | | | | | || || | | . .
- * | |_/ / \ \__// || | |
- * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
- * / \
- * / . \
- * sample.c - The sample (SAMP) signal type. / / \ \
- * | < / \_
- * By entheh. | \/ /\ /
- * \_ / > /
- * This only supports monaural samples. For | \ / /
- * multiple channels, use multiple samples and | ' /
- * a combining signal (COMB). \__/
- */
-
-/* NOTE: filters need not be credited yet, as they will be moved elsewhere. */
-/** WARNING don't forget to move these filters somewhere */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "dumb.h"
-
-
-/** WARNING move these things somewhere useful, for DUH writing - this applies to other signal types too */
-#define SIGTYPE_SAMPLE DUMB_ID('S','A','M','P')
-
-
-
-#define SAMPFLAG_16BIT 1 /* sample in file is 16 bit, rather than 8 bit */
-#define SAMPFLAG_LOOP 2 /* loop indefinitely */
-#define SAMPFLAG_XLOOP 4 /* loop x times; only relevant if LOOP not set */
-#define SAMPFLAG_PINGPONG 8 /* loop back and forth, if LOOP or XLOOP set */
-
-
-/* SAMPPARAM_N_LOOPS: add 'value' iterations to the loop. 'value' is assumed
- * to be positive.
- */
-#define SAMPPARAM_N_LOOPS 0
-
-
-
-typedef struct SAMPLE_SIGDATA
-{
- long size;
- int flags;
- long loop_start;
- long loop_end;
- sample_t *samples;
-}
-SAMPLE_SIGDATA;
-
-
-
-typedef struct SAMPLE_SIGRENDERER
-{
- SAMPLE_SIGDATA *sigdata;
- int n_channels;
- DUMB_RESAMPLER r;
- int n_loops;
-}
-SAMPLE_SIGRENDERER;
-
-
-
-static sigdata_t *sample_load_sigdata(DUH *duh, DUMBFILE *file)
-{
- SAMPLE_SIGDATA *sigdata;
- long size;
- long n;
- int flags;
-
- (void)duh;
-
- size = dumbfile_igetl(file);
-
- if (dumbfile_error(file) || size <= 0)
- return NULL;
-
- flags = dumbfile_getc(file);
- if (flags < 0)
- return NULL;
-
- sigdata = malloc(sizeof(*sigdata));
- if (!sigdata)
- return NULL;
-
- sigdata->samples = malloc(size * sizeof(sample_t));
- if (!sigdata->samples) {
- free(sigdata);
- return NULL;
- }
-
- sigdata->size = size;
- sigdata->flags = flags;
-
- if (sigdata->flags & (SAMPFLAG_LOOP | SAMPFLAG_XLOOP)) {
- sigdata->loop_start = dumbfile_igetl(file);
-
- if (dumbfile_error(file) || (unsigned long)sigdata->loop_start >= (unsigned long)size) {
- free(sigdata->samples);
- free(sigdata);
- return NULL;
- }
-
- if (sigdata->flags & SAMPFLAG_LOOP)
- sigdata->loop_end = size;
- else {
- sigdata->loop_end = dumbfile_igetl(file);
-
- if (dumbfile_error(file) || sigdata->loop_end <= sigdata->loop_start || sigdata->loop_end > size) {
- free(sigdata->samples);
- free(sigdata);
- return NULL;
- }
- }
- } else {
- sigdata->loop_start = 0;
- sigdata->loop_end = size;
- }
-
- if (sigdata->flags & SAMPFLAG_16BIT) {
- for (n = 0; n < size; n++) {
- int m = dumbfile_igetw(file);
- if (m < 0) {
- free(sigdata->samples);
- free(sigdata);
- return NULL;
- }
- sigdata->samples[n] = (int)(signed short)m << 8;
- }
- } else {
- for (n = 0; n < size; n++) {
- int m = dumbfile_getc(file);
- if (m < 0) {
- free(sigdata->samples);
- free(sigdata);
- return NULL;
- }
- sigdata->samples[n] = (int)(signed char)m << 16;
- }
- }
-
- return sigdata;
-}
-
-
-
-static void sample_pickup(DUMB_RESAMPLER *r, void *data)
-{
- SAMPLE_SIGRENDERER *sigrenderer = data;
-
- if (!(sigrenderer->sigdata->flags & (SAMPFLAG_LOOP | SAMPFLAG_XLOOP))) {
- r->dir = 0;
- return;
- }
-
- if (!(sigrenderer->sigdata->flags & SAMPFLAG_LOOP) && sigrenderer->n_loops == 0) {
- r->dir = 0;
- return;
- }
-
- if (sigrenderer->sigdata->flags & SAMPFLAG_PINGPONG) {
- if (r->dir < 0) {
- r->pos = (r->start << 1) - 1 - r->pos;
- r->subpos ^= 65535;
- r->dir = 1;
- } else {
- r->pos = (r->end << 1) - 1 - r->pos;
- r->subpos ^= 65535;
- r->dir = -1;
- }
- } else
- r->pos -= r->end - r->start;
-
- if (!(sigrenderer->sigdata->flags & SAMPFLAG_LOOP)) {
- if (sigrenderer->n_loops > 0) {
- sigrenderer->n_loops--;
- if (sigrenderer->n_loops == 0) {
- r->start = 0;
- r->end = sigrenderer->sigdata->size;
- }
- }
- }
-}
-
-
-
-static sigrenderer_t *sample_start_sigrenderer(DUH *duh, sigdata_t *data, int n_channels, long pos)
-{
- SAMPLE_SIGDATA *sigdata = data;
- SAMPLE_SIGRENDERER *sigrenderer;
-
- (void)duh;
-
- sigrenderer = malloc(sizeof(*sigrenderer));
- if (!sigrenderer) return NULL;
-
- sigrenderer->sigdata = data;
- sigrenderer->n_channels = n_channels;
- dumb_reset_resampler(&sigrenderer->r, sigdata->samples, pos, 0, sigdata->size);
- sigrenderer->r.pickup = &sample_pickup;
- sigrenderer->r.pickup_data = sigrenderer;
- sigrenderer->n_loops = 0;
-
- return sigrenderer;
-}
-
-
-
-#if 0
-/* The name says it all ;-) */
-static void sample_cheap_low_pass_filter(sample *src, long size, float max_freq) {
-
- long i;
- float fact = max_freq / 44100.0f;
-
- for (i = 0; i < size-1; i++) {
- float d = src[i+1] - src[i];
- if (d > fact)
- src[i+1] += fact - d;
- else if (d < -fact)
- src[i+1] += -d - fact;
- }
-
- return;
-}
-
-
-
-/* Dithering with noise shaping filter. Set shape = 0 for no shaping. */
-static void sample_dither_filter(float *src, long size, float shape) {
- float r1 = 0, r2 = 0;
- float s1 = 0, s2 = 0; /* Feedback buffer */
- float o = 0.5f / 255;
- float tmp;
- int i;
-
- for (i = 0; i < size; i++) {
- r2 = r1;
- r1 = rand() / (float)RAND_MAX;
-
- tmp = src[i] + shape * (s1 + s1 - s2);
- src[i] = tmp + o * (r1 - r2);
- src[i] = MID(-1.0f, src[i], 1.0f);
-
- s2 = s1;
- s1 = tmp - src[i];
- }
- return;
-}
-#endif
-
-
-
-static void sample_sigrenderer_set_sigparam(sigrenderer_t *data, unsigned char id, long value)
-{
- SAMPLE_SIGRENDERER *sigrenderer = data;
-
- if (id == SAMPPARAM_N_LOOPS) {
- if ((sigrenderer->sigdata->flags & (SAMPFLAG_LOOP | SAMPFLAG_XLOOP)) == SAMPFLAG_XLOOP) {
- sigrenderer->n_loops += value;
- sigrenderer->r.start = sigrenderer->n_loops ? sigrenderer->sigdata->loop_start : 0;
- sigrenderer->r.end = sigrenderer->n_loops ? sigrenderer->sigdata->loop_end : sigrenderer->sigdata->size;
- }
- }
-}
-
-
-
-static long sample_sigrenderer_get_samples(
- sigrenderer_t *data,
- float volume, float delta,
- long size, sample_t **samples
-)
-{
- SAMPLE_SIGRENDERER *sigrenderer = data;
-
- DUMB_RESAMPLER initial_r = sigrenderer->r;
-
- long s = dumb_resample(&sigrenderer->r, samples[0], size, volume, delta);
-
- int n;
- for (n = 1; n < sigrenderer->n_channels; n++) {
- sigrenderer->r = initial_r;
- dumb_resample(&sigrenderer->r, samples[n], size, volume, delta);
- }
-
- return s;
-}
-
-
-
-static void sample_sigrenderer_get_current_sample(sigrenderer_t *data, float volume, sample_t *samples)
-{
- SAMPLE_SIGRENDERER *sigrenderer = data;
- int n;
- for (n = 0; n < sigrenderer->n_channels; n++)
- samples[n] = dumb_resample_get_current_sample(&sigrenderer->r, volume);
-}
-
-
-
-static void sample_end_sigrenderer(sigrenderer_t *sigrenderer)
-{
- free(sigrenderer);
-}
-
-
-
-static void sample_unload_sigdata(sigdata_t *data)
-{
- SAMPLE_SIGDATA *sigdata = data;
- free(sigdata->samples);
- free(data);
-}
-
-
-
-static DUH_SIGTYPE_DESC sigtype_sample = {
- SIGTYPE_SAMPLE,
- &sample_load_sigdata,
- &sample_start_sigrenderer,
- &sample_sigrenderer_set_sigparam,
- &sample_sigrenderer_get_samples,
- &sample_sigrenderer_get_current_sample,
- &sample_end_sigrenderer,
- &sample_unload_sigdata
-};
-
-
-
-void dumb_register_sigtype_sample(void)
-{
- dumb_register_sigtype(&sigtype_sample);
-}
+/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + * / \ + * / . \ + * sample.c - The sample (SAMP) signal type. / / \ \ + * | < / \_ + * By entheh. | \/ /\ / + * \_ / > / + * This only supports monaural samples. For | \ / / + * multiple channels, use multiple samples and | ' / + * a combining signal (COMB). \__/ + */ + +/* NOTE: filters need not be credited yet, as they will be moved elsewhere. */ +/** WARNING don't forget to move these filters somewhere */ + +#include <stdlib.h> +#include <string.h> + +#include "dumb.h" + + +/** WARNING move these things somewhere useful, for DUH writing - this applies to other signal types too */ +#define SIGTYPE_SAMPLE DUMB_ID('S','A','M','P') + + + +#define SAMPFLAG_16BIT 1 /* sample in file is 16 bit, rather than 8 bit */ +#define SAMPFLAG_LOOP 2 /* loop indefinitely */ +#define SAMPFLAG_XLOOP 4 /* loop x times; only relevant if LOOP not set */ +#define SAMPFLAG_PINGPONG 8 /* loop back and forth, if LOOP or XLOOP set */ + + +/* SAMPPARAM_N_LOOPS: add 'value' iterations to the loop. 'value' is assumed + * to be positive. + */ +#define SAMPPARAM_N_LOOPS 0 + + + +typedef struct SAMPLE_SIGDATA +{ + long size; + int flags; + long loop_start; + long loop_end; + sample_t *samples; +} +SAMPLE_SIGDATA; + + + +typedef struct SAMPLE_SIGRENDERER +{ + SAMPLE_SIGDATA *sigdata; + int n_channels; + DUMB_RESAMPLER r; + int n_loops; +} +SAMPLE_SIGRENDERER; + + + +static sigdata_t *sample_load_sigdata(DUH *duh, DUMBFILE *file) +{ + SAMPLE_SIGDATA *sigdata; + long size; + long n; + int flags; + + (void)duh; + + size = dumbfile_igetl(file); + + if (dumbfile_error(file) || size <= 0) + return NULL; + + flags = dumbfile_getc(file); + if (flags < 0) + return NULL; + + sigdata = malloc(sizeof(*sigdata)); + if (!sigdata) + return NULL; + + sigdata->samples = malloc(size * sizeof(sample_t)); + if (!sigdata->samples) { + free(sigdata); + return NULL; + } + + sigdata->size = size; + sigdata->flags = flags; + + if (sigdata->flags & (SAMPFLAG_LOOP | SAMPFLAG_XLOOP)) { + sigdata->loop_start = dumbfile_igetl(file); + + if (dumbfile_error(file) || (unsigned long)sigdata->loop_start >= (unsigned long)size) { + free(sigdata->samples); + free(sigdata); + return NULL; + } + + if (sigdata->flags & SAMPFLAG_LOOP) + sigdata->loop_end = size; + else { + sigdata->loop_end = dumbfile_igetl(file); + + if (dumbfile_error(file) || sigdata->loop_end <= sigdata->loop_start || sigdata->loop_end > size) { + free(sigdata->samples); + free(sigdata); + return NULL; + } + } + } else { + sigdata->loop_start = 0; + sigdata->loop_end = size; + } + + if (sigdata->flags & SAMPFLAG_16BIT) { + for (n = 0; n < size; n++) { + int m = dumbfile_igetw(file); + if (m < 0) { + free(sigdata->samples); + free(sigdata); + return NULL; + } + sigdata->samples[n] = (int)(signed short)m << 8; + } + } else { + for (n = 0; n < size; n++) { + int m = dumbfile_getc(file); + if (m < 0) { + free(sigdata->samples); + free(sigdata); + return NULL; + } + sigdata->samples[n] = (int)(signed char)m << 16; + } + } + + return sigdata; +} + + + +static void sample_pickup(DUMB_RESAMPLER *r, void *data) +{ + SAMPLE_SIGRENDERER *sigrenderer = data; + + if (!(sigrenderer->sigdata->flags & (SAMPFLAG_LOOP | SAMPFLAG_XLOOP))) { + r->dir = 0; + return; + } + + if (!(sigrenderer->sigdata->flags & SAMPFLAG_LOOP) && sigrenderer->n_loops == 0) { + r->dir = 0; + return; + } + + if (sigrenderer->sigdata->flags & SAMPFLAG_PINGPONG) { + if (r->dir < 0) { + r->pos = (r->start << 1) - 1 - r->pos; + r->subpos ^= 65535; + r->dir = 1; + } else { + r->pos = (r->end << 1) - 1 - r->pos; + r->subpos ^= 65535; + r->dir = -1; + } + } else + r->pos -= r->end - r->start; + + if (!(sigrenderer->sigdata->flags & SAMPFLAG_LOOP)) { + if (sigrenderer->n_loops > 0) { + sigrenderer->n_loops--; + if (sigrenderer->n_loops == 0) { + r->start = 0; + r->end = sigrenderer->sigdata->size; + } + } + } +} + + + +static sigrenderer_t *sample_start_sigrenderer(DUH *duh, sigdata_t *data, int n_channels, long pos) +{ + SAMPLE_SIGDATA *sigdata = data; + SAMPLE_SIGRENDERER *sigrenderer; + + (void)duh; + + sigrenderer = malloc(sizeof(*sigrenderer)); + if (!sigrenderer) return NULL; + + sigrenderer->sigdata = data; + sigrenderer->n_channels = n_channels; + dumb_reset_resampler(&sigrenderer->r, sigdata->samples, pos, 0, sigdata->size); + sigrenderer->r.pickup = &sample_pickup; + sigrenderer->r.pickup_data = sigrenderer; + sigrenderer->n_loops = 0; + + return sigrenderer; +} + + + +#if 0 +/* The name says it all ;-) */ +static void sample_cheap_low_pass_filter(sample *src, long size, float max_freq) { + + long i; + float fact = max_freq / 44100.0f; + + for (i = 0; i < size-1; i++) { + float d = src[i+1] - src[i]; + if (d > fact) + src[i+1] += fact - d; + else if (d < -fact) + src[i+1] += -d - fact; + } + + return; +} + + + +/* Dithering with noise shaping filter. Set shape = 0 for no shaping. */ +static void sample_dither_filter(float *src, long size, float shape) { + float r1 = 0, r2 = 0; + float s1 = 0, s2 = 0; /* Feedback buffer */ + float o = 0.5f / 255; + float tmp; + int i; + + for (i = 0; i < size; i++) { + r2 = r1; + r1 = rand() / (float)RAND_MAX; + + tmp = src[i] + shape * (s1 + s1 - s2); + src[i] = tmp + o * (r1 - r2); + src[i] = MID(-1.0f, src[i], 1.0f); + + s2 = s1; + s1 = tmp - src[i]; + } + return; +} +#endif + + + +static void sample_sigrenderer_set_sigparam(sigrenderer_t *data, unsigned char id, long value) +{ + SAMPLE_SIGRENDERER *sigrenderer = data; + + if (id == SAMPPARAM_N_LOOPS) { + if ((sigrenderer->sigdata->flags & (SAMPFLAG_LOOP | SAMPFLAG_XLOOP)) == SAMPFLAG_XLOOP) { + sigrenderer->n_loops += value; + sigrenderer->r.start = sigrenderer->n_loops ? sigrenderer->sigdata->loop_start : 0; + sigrenderer->r.end = sigrenderer->n_loops ? sigrenderer->sigdata->loop_end : sigrenderer->sigdata->size; + } + } +} + + + +static long sample_sigrenderer_get_samples( + sigrenderer_t *data, + float volume, float delta, + long size, sample_t **samples +) +{ + SAMPLE_SIGRENDERER *sigrenderer = data; + + DUMB_RESAMPLER initial_r = sigrenderer->r; + + long s = dumb_resample(&sigrenderer->r, samples[0], size, volume, delta); + + int n; + for (n = 1; n < sigrenderer->n_channels; n++) { + sigrenderer->r = initial_r; + dumb_resample(&sigrenderer->r, samples[n], size, volume, delta); + } + + return s; +} + + + +static void sample_sigrenderer_get_current_sample(sigrenderer_t *data, float volume, sample_t *samples) +{ + SAMPLE_SIGRENDERER *sigrenderer = data; + int n; + for (n = 0; n < sigrenderer->n_channels; n++) + samples[n] = dumb_resample_get_current_sample(&sigrenderer->r, volume); +} + + + +static void sample_end_sigrenderer(sigrenderer_t *sigrenderer) +{ + free(sigrenderer); +} + + + +static void sample_unload_sigdata(sigdata_t *data) +{ + SAMPLE_SIGDATA *sigdata = data; + free(sigdata->samples); + free(data); +} + + + +static DUH_SIGTYPE_DESC sigtype_sample = { + SIGTYPE_SAMPLE, + &sample_load_sigdata, + &sample_start_sigrenderer, + &sample_sigrenderer_set_sigparam, + &sample_sigrenderer_get_samples, + &sample_sigrenderer_get_current_sample, + &sample_end_sigrenderer, + &sample_unload_sigdata +}; + + + +void dumb_register_sigtype_sample(void) +{ + dumb_register_sigtype(&sigtype_sample); +} |