1 /*(LGPL)
2 ---------------------------------------------------------------------------
3 a_limiter.h - Simple limiter
4 ---------------------------------------------------------------------------
5 * Copyright (C) 2001, 2002, David Olofson
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <stdlib.h>
23 #include "a_limiter.h"
24 #include "a_types.h"
25
lim_open(limiter_t * lim,int samplerate)26 int lim_open(limiter_t *lim, int samplerate)
27 {
28 lim->samplerate = samplerate;
29 lim_control(lim, LIM_THRESHOLD, 32768);
30 lim_control(lim, LIM_RELEASE, 300000);
31 lim->peak = (unsigned)(32768<<8);
32 lim->attenuation = 0;
33 return 0;
34 }
35
lim_close(limiter_t * lim)36 void lim_close(limiter_t *lim)
37 {
38 /* Nothing to destruct */
39 }
40
lim_control(limiter_t * lim,int param,int value)41 void lim_control(limiter_t *lim, int param, int value)
42 {
43 switch(param)
44 {
45 case LIM_THRESHOLD:
46 lim->threshold = (unsigned)(value << 8);
47 if(lim->threshold < 256)
48 lim->threshold = 256;
49 break;
50 case LIM_RELEASE:
51 if(lim->samplerate < 1)
52 lim->samplerate = 44100;
53 lim->release = (value << 8) / lim->samplerate;
54 break;
55 }
56 }
57
lims_process(limiter_t * lim,int * in,int * out,unsigned frames)58 void lims_process(limiter_t *lim, int *in, int *out, unsigned frames)
59 {
60 unsigned i;
61 frames <<= 1;
62 for(i = 0; i < frames; i += 2)
63 {
64 int gain;
65 int lp = abs(in[i]) << 8;
66 int rp = abs(in[i+1]) << 8;
67 unsigned maxp = (unsigned)(lp > rp ? lp : rp);
68 if(maxp > lim->peak)
69 {
70 lim->peak = maxp;
71 gain = (32767<<16) / ((lim->peak+255)>>8);
72 }
73 else
74 {
75 gain = (32767<<16) / ((lim->peak+255)>>8);
76 lim->peak -= lim->release;
77 if(lim->peak < lim->threshold)
78 lim->peak = lim->threshold;
79 }
80 #ifdef A_USE_INT64
81 out[i] = (Sint64)in[i] * (Sint64)gain >> 16;
82 out[i+1] = (Sint64)in[i+1] * (Sint64)gain >> 16;
83 #else
84 if(gain < 8192)
85 {
86 out[i] = in[i] * gain >> 16;
87 out[i+1] = in[i+1] * gain >> 16;
88 }
89 else
90 {
91 out[i] = in[i] * (gain>>4) >> 12;
92 out[i+1] = in[i+1] * (gain>>4) >> 12;
93 }
94 #endif
95 }
96 lim->attenuation = (lim->peak - lim->threshold) >> 8;
97 }
98
limss_process(limiter_t * lim,int * in,int * out,unsigned frames)99 void limss_process(limiter_t *lim, int *in, int *out, unsigned frames)
100 {
101 unsigned i;
102 frames <<= 1;
103 for(i = 0; i < frames; i += 2)
104 {
105 int gain;
106 int lp = abs(in[i]);
107 int rp = abs(in[i+1]);
108 unsigned maxp = (unsigned)(lp > rp ? lp : rp);
109 unsigned p = maxp << 8;
110 p += (maxp - abs(lp - rp)) << 7;
111 if(p > lim->peak)
112 {
113 lim->peak = p;
114 gain = (32767<<16) / ((lim->peak+255)>>8);
115 }
116 else
117 {
118 gain = (32767<<16) / ((lim->peak+255)>>8);
119 lim->peak -= lim->release;
120 if(lim->peak < lim->threshold)
121 lim->peak = lim->threshold;
122 }
123 #ifdef A_USE_INT64
124 out[i] = (Sint64)in[i] * (Sint64)gain >> 16;
125 out[i+1] = (Sint64)in[i+1] * (Sint64)gain >> 16;
126 #else
127 if(gain < 8192)
128 {
129 out[i] = in[i] * gain >> 16;
130 out[i+1] = in[i+1] * gain >> 16;
131 }
132 else
133 {
134 out[i] = in[i] * (gain>>4) >> 12;
135 out[i+1] = in[i+1] * (gain>>4) >> 12;
136 }
137 #endif
138 }
139 lim->attenuation = (lim->peak - lim->threshold) >> 8;
140 }
141