ref: c6bc9714dd9e3ba1e022327f607ea09c40440d3d
dir: /src/core/rendsig.c/
/* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . .
* | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \
* / . \
* rendsig.c - Wrappers to render samples from / / \ \
* the signals in a DUH. | < / \_
* | \/ /\ /
* By entheh. \_ / > /
* | \ / /
* | ' /
* \__/
*/
#include <stdlib.h>
#include "dumb.h"
#include "internal/dumb.h"
struct DUH_SIGRENDERER {
DUH_SIGTYPE_DESC *desc;
sigrenderer_t *sigrenderer;
int n_channels;
long pos;
int subpos;
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback;
void *callback_data;
};
DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels,
long pos) {
DUH_SIGRENDERER *sigrenderer;
DUH_SIGNAL *signal;
DUH_START_SIGRENDERER proc;
if (!duh)
return NULL;
if ((unsigned int)sig >= (unsigned int)duh->n_signals)
return NULL;
signal = duh->signal[sig];
if (!signal)
return NULL;
sigrenderer = malloc(sizeof(*sigrenderer));
if (!sigrenderer)
return NULL;
sigrenderer->desc = signal->desc;
proc = sigrenderer->desc->start_sigrenderer;
if (proc) {
duh->signal[sig] = NULL;
sigrenderer->sigrenderer =
(*proc)(duh, signal->sigdata, n_channels, pos);
duh->signal[sig] = signal;
if (!sigrenderer->sigrenderer) {
free(sigrenderer);
return NULL;
}
} else
sigrenderer->sigrenderer = NULL;
sigrenderer->n_channels = n_channels;
sigrenderer->pos = pos;
sigrenderer->subpos = 0;
sigrenderer->callback = NULL;
return sigrenderer;
}
void duh_sigrenderer_set_sample_analyser_callback(
DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data) {
if (sigrenderer) {
sigrenderer->callback = callback;
sigrenderer->callback_data = data;
}
}
int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer) {
return sigrenderer ? sigrenderer->n_channels : 0;
}
long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer) {
DUH_SIGRENDERER_GET_POSITION proc;
if (!sigrenderer)
return -1;
proc = sigrenderer->desc->sigrenderer_get_position;
if (proc)
return (*proc)(sigrenderer->sigrenderer);
else
return sigrenderer->pos;
}
void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer,
unsigned char id, long value) {
DUH_SIGRENDERER_SET_SIGPARAM proc;
if (!sigrenderer)
return;
proc = sigrenderer->desc->sigrenderer_set_sigparam;
if (proc)
(*proc)(sigrenderer->sigrenderer, id, value);
else
TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take "
"parameters.\n",
(int)id, value, (int)(sigrenderer->desc->type >> 24),
(int)(sigrenderer->desc->type >> 16),
(int)(sigrenderer->desc->type >> 8),
(int)(sigrenderer->desc->type));
}
long duh_sigrenderer_generate_samples(DUH_SIGRENDERER *sigrenderer,
float volume, float delta, long size,
sample_t **samples) {
long rendered;
LONG_LONG t;
if (!sigrenderer)
return 0;
rendered = (*sigrenderer->desc->sigrenderer_generate_samples)(
sigrenderer->sigrenderer, volume, delta, size, samples);
if (rendered) {
if (sigrenderer->callback)
(*sigrenderer->callback)(sigrenderer->callback_data,
(const sample_t *const *)samples,
sigrenderer->n_channels, rendered);
t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered;
sigrenderer->pos += (long)(t >> 16);
sigrenderer->subpos = (int)t & 65535;
}
return rendered;
}
void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer,
float volume, sample_t *samples) {
if (sigrenderer)
(*sigrenderer->desc->sigrenderer_get_current_sample)(
sigrenderer->sigrenderer, volume, samples);
}
void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer) {
if (sigrenderer) {
if (sigrenderer->desc->end_sigrenderer)
if (sigrenderer->sigrenderer)
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
free(sigrenderer);
}
}
DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer,
DUH_SIGTYPE_DESC *desc,
int n_channels, long pos) {
DUH_SIGRENDERER *sigrenderer;
if (desc->start_sigrenderer && !vsigrenderer)
return NULL;
sigrenderer = malloc(sizeof(*sigrenderer));
if (!sigrenderer) {
if (desc->end_sigrenderer)
if (vsigrenderer)
(*desc->end_sigrenderer)(vsigrenderer);
return NULL;
}
sigrenderer->desc = desc;
sigrenderer->sigrenderer = vsigrenderer;
sigrenderer->n_channels = n_channels;
sigrenderer->pos = pos;
sigrenderer->subpos = 0;
sigrenderer->callback = NULL;
return sigrenderer;
}
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer,
long type) {
if (sigrenderer && sigrenderer->desc->type == type)
return sigrenderer->sigrenderer;
return NULL;
}
#if 0
// This function is disabled because we don't know whether we want to destroy
// the sigrenderer if the type doesn't match. We don't even know if we need
// the function at all. Who would want to keep an IT_SIGRENDERER (for
// instance) without keeping the DUH_SIGRENDERER?
sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
{
if (sigrenderer && sigrenderer->desc->type == type) {
if (sigrenderer) {
if (sigrenderer->desc->end_sigrenderer)
if (sigrenderer->sigrenderer)
(*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
free(sigrenderer);
}
return sigrenderer->sigrenderer;
}
return NULL;
}
#endif