2
* Copyright (C) 2003-2009 The Music Player Daemon Project
3
* http://www.musicpd.org
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
* Imported from AudioCompress by J. Shagam <fluffy@beesbuzz.biz>
33
#include <X11/Xutil.h>
35
static Display *display;
37
static Visual *visual;
39
static GC blackGC, whiteGC, blueGC, yellowGC, dkyellowGC, redGC;
43
static int gainCurrent, gainTarget;
58
void CompressCfg(int show_mon, int anticlip, int target, int gainmax,
59
int gainsmooth, unsigned buckets)
61
static unsigned lastsize;
63
prefs.show_mon = show_mon;
64
prefs.anticlip = anticlip;
65
prefs.target = target;
66
prefs.gainmax = gainmax;
67
prefs.gainsmooth = gainsmooth;
68
prefs.buckets = buckets;
70
/* Allocate the peak structure */
71
peaks = g_realloc(peaks, sizeof(int)*prefs.buckets);
73
if (prefs.buckets > lastsize)
74
memset(peaks + lastsize, 0, sizeof(int)*(prefs.buckets
76
lastsize = prefs.buckets;
79
/* Configure the monitor window if needed */
80
if (show_mon && !mon_init)
82
display = XOpenDisplay(getenv("DISPLAY"));
84
/* We really shouldn't try to init X if there's no X */
88
"X not detected; disabling monitor window\n");
89
show_mon = prefs.show_mon = 0;
93
if (show_mon && !mon_init)
98
gainCurrent = gainTarget = (1 << GAINSHIFT);
102
screen = DefaultScreen(display);
103
visual = DefaultVisual(display, screen);
104
window = XCreateSimpleWindow(display,
105
RootWindow(display, screen),
106
0, 0, prefs.buckets, 128 + 8, 0,
107
BlackPixel(display, screen),
108
WhitePixel(display, screen));
109
XStoreName(display, window, "AudioCompress monitor");
111
gcv.foreground = BlackPixel(display, screen);
112
blackGC = XCreateGC(display, window, GCForeground, &gcv);
113
gcv.foreground = WhitePixel(display, screen);
114
whiteGC = XCreateGC(display, window, GCForeground, &gcv);
118
XAllocColor(display, DefaultColormap(display, screen), &col);
119
gcv.foreground = col.pixel;
120
blueGC = XCreateGC(display, window, GCForeground, &gcv);
124
XAllocColor(display, DefaultColormap(display, screen), &col);
125
gcv.foreground = col.pixel;
126
yellowGC = XCreateGC(display, window, GCForeground, &gcv);
130
XAllocColor(display, DefaultColormap(display, screen), &col);
131
gcv.foreground = col.pixel;
132
dkyellowGC = XCreateGC(display, window, GCForeground, &gcv);
136
XAllocColor(display, DefaultColormap(display, screen), &col);
137
gcv.foreground = col.pixel;
138
redGC = XCreateGC(display, window, GCForeground, &gcv);
145
XMapWindow(display, window);
147
XUnmapWindow(display, window);
148
XResizeWindow(display, window, prefs.buckets, 128 + 8);
154
void CompressFree(void)
159
XFreeGC(display, blackGC);
160
XFreeGC(display, whiteGC);
161
XFreeGC(display, blueGC);
162
XFreeGC(display, yellowGC);
163
XFreeGC(display, dkyellowGC);
164
XFreeGC(display, redGC);
165
XDestroyWindow(display, window);
166
XCloseDisplay(display);
173
void CompressDo(void *data, unsigned int length)
175
int16_t *audio = (int16_t *)data, *ap;
190
for (i = 0; i < prefs.buckets; i++)
193
pn = (pn + 1)%prefs.buckets;
196
fprintf(stderr, "modifyNative16(0x%08x, %d)\n",(unsigned int)data,
200
/* Determine peak's value and position */
205
fprintf(stderr, "finding peak(b=%d)\n", pn);
209
for (i = 0; i < length/2; i++)
216
} else if (-val > peak)
225
/* Only draw if needed, of course */
229
/* current amplitude */
230
XDrawLine(display, window, whiteGC,
234
(peaks[pn]*gainCurrent >> (GAINSHIFT + 8)));
237
XDrawLine(display, window, yellowGC,
239
127 - (peaks[pn]*gainCurrent
244
XDrawLine(display, window, blackGC,
245
pn, 127 - (peaks[pn] >> 8), pn, 127);
249
XDrawLine(display, window, redGC,
250
(pn + prefs.buckets - 1)%prefs.buckets,
251
126 - clipped/(length*512),
252
(pn + prefs.buckets - 1)%prefs.buckets,
257
/* XDrawPoint(display, window, redGC, */
258
/* pn, 127 - TARGET/256); */
259
/* amplification edge */
260
XDrawLine(display, window, dkyellowGC,
262
127 - (peaks[pn]*gainCurrent
266
(peaks[(pn + prefs.buckets
267
- 1)%prefs.buckets]*gainCurrent
268
>> (GAINSHIFT + 8)));
272
for (i = 0; i < prefs.buckets; i++)
281
/* Determine target gain */
282
gn = (1 << GAINSHIFT)*prefs.target/peak;
284
if (gn <(1 << GAINSHIFT))
287
gainTarget = (gainTarget *((1 << prefs.gainsmooth) - 1) + gn)
290
/* Give it an extra insignifigant nudge to counteract possible
296
else if (gn > gainTarget)
299
if (gainTarget > prefs.gainmax << GAINSHIFT)
300
gainTarget = prefs.gainmax << GAINSHIFT;
309
XDrawPoint(display, window, redGC,
311
127 - (peak*gainCurrent
312
>> (GAINSHIFT + 8)));
315
XFillRectangle(display, window, whiteGC, 0, 128,
317
x = (gainTarget - (1 << GAINSHIFT))*prefs.buckets
318
/ ((prefs.gainmax - 1) << GAINSHIFT);
319
XDrawLine(display, window, redGC, x,
322
x = (gn - (1 << GAINSHIFT))*prefs.buckets
323
/ ((prefs.gainmax - 1) << GAINSHIFT);
325
XDrawLine(display, window, blackGC,
330
XDrawLine(display, window, blueGC,
331
0, 127 - (peak >> 8), prefs.buckets,
334
XDrawLine(display, window, whiteGC,
335
0, 127 - (peak >> 8), prefs.buckets,
340
/* See if a peak is going to clip */
341
gn = (1 << GAINSHIFT)*32768/peak;
352
/* We're ramping up, so draw it out over the whole frame */
356
/* Determine gain rate necessary to make target */
360
gr = ((gainTarget - gainCurrent) << 16)/(int)pos;
363
gf = gainCurrent << 16;
366
fprintf(stderr, "\rgain = %2.2f%+.2e ",
367
gainCurrent*1.0/(1 << GAINSHIFT),
368
(gainTarget - gainCurrent)*1.0/(1 << GAINSHIFT));
372
for (i = 0; i < length/2; i++)
376
/* Interpolate the gain */
377
gainCurrent = gf >> 16;
381
gf = gainTarget << 16;
384
sample = (*ap)*gainCurrent >> GAINSHIFT;
390
clipped += -32768 - sample;
392
} else if (sample > 32767)
397
clipped += sample - 32767;
403
fprintf(stderr, "clip %d b%-3d ", clip, pn);
407
fprintf(stderr, "\ndone\n");