1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
#include "config.h"
#include <xmms/plugin.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include "echo.h"
static void init(void);
static void clear_buffer(void);
static void cleanup(void);
static int mod_samples(gpointer * d, gint length, AFormat afmt, gint srate, gint nch);
#define MAX_SRATE 50000
#define MAX_CHANNELS 2
#define BYTES_PS 2
#define BUFFER_SAMPLES (MAX_SRATE * MAX_DELAY / 1000)
#define BUFFER_SHORTS (BUFFER_SAMPLES * MAX_CHANNELS)
#define BUFFER_BYTES (BUFFER_SHORTS * BYTES_PS)
EffectPlugin echo_ep =
{
NULL,
NULL,
"Echo Plugin " VERSION,
init,
cleanup,
echo_about,
echo_configure,
mod_samples,
NULL
};
static short *buffer = NULL;
int echo_delay = 500, echo_feedback = 50, echo_volume = 50;
static int w_ofs;
static int old_srate, old_nch;
EffectPlugin *get_eplugin_info(void)
{
return &echo_ep;
}
static void init(void)
{
buffer = g_malloc0(BUFFER_BYTES);
}
static void clear_buffer(void)
{
bzero(buffer, BUFFER_BYTES);
w_ofs = 0; // short[] index
}
static void cleanup(void)
{
if (buffer)
{
free(buffer);
buffer = NULL;
}
}
static void range(int *v)
{
if (*v < -32768)
*v = -32768;
if (*v > 32767)
*v = 32767;
}
static int mod_samples(gpointer * d, gint length, AFormat afmt, gint srate, gint nch)
{
int i, in, out, buf, tmp, r_ofs;
gint16 *data = (gint16 *) * d;
if (!(afmt == FMT_S16_NE || (afmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) || (afmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN)))
return length;
if (nch != old_nch || srate != old_srate)
{
clear_buffer();
old_nch = nch;
old_srate = srate;
}
r_ofs = w_ofs - (srate * echo_delay / 1000) * nch;
if (r_ofs < 0)
r_ofs += BUFFER_SHORTS;
for (i = 0; i < length / BYTES_PS; i++)
{
in = data[i];
buf = buffer[r_ofs];
out = in + buf * echo_volume / 100;
buf = in + buf * echo_feedback / 100;
range(&out);
range(&buf);
buffer[w_ofs] = buf;
data[i] = out;
tmp = data[i];
if (++r_ofs >= BUFFER_SHORTS)
r_ofs -= BUFFER_SHORTS;
if (++w_ofs >= BUFFER_SHORTS)
w_ofs -= BUFFER_SHORTS;
}
return length;
}
|