File: echo.c

package info (click to toggle)
xmms 1.0.1-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 4,180 kB
  • ctags: 3,923
  • sloc: ansic: 38,352; sh: 8,294; asm: 398; makefile: 387
file content (111 lines) | stat: -rw-r--r-- 2,116 bytes parent folder | download
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;
}