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