Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / postfish / follower.c
blob36fcb268e8bee4abdd4f95bb82d5ee0256b34cc1
1 /*
3 * postfish
4 *
5 * Copyright (C) 2002-2005 Monty
7 * Postfish is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
12 * Postfish is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Postfish; see the file COPYING. If not, write to the
19 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "postfish.h"
25 #include "follower.h"
27 static void _analysis(char *base,int seq, float *data, int n,int dB,
28 off_t offset){
30 FILE *f;
31 char buf[80];
32 sprintf(buf,"%s_%d.m",base,seq);
34 f=fopen(buf,"a");
35 if(f){
36 int i;
37 for(i=0;i<n;i++)
38 if(dB)
39 fprintf(f,"%d %f\n",(int)(i+offset),todB(data[i]));
40 else
41 fprintf(f,"%d %f\n",(int)(i+offset),(data[i]));
44 fclose(f);
47 off_t offset=0;
48 int offch;
50 /* Common follower code */
52 static void prepare_peak(float *peak, float *x, int n, int ahead,
53 int hold, peak_state *ps){
54 int ii,jj;
55 int loc=ps->loc;
56 float val=ps->val;
58 /* Although we have two input_size blocks of zeroes after a
59 reset, we may still need to look ahead explicitly after a
60 reset if the lookahead is exceptionally long */
62 if(loc==0 && val==0){
63 for(ii=0;ii<ahead;ii++)
64 if((x[ii]*x[ii])>val){
65 val=(x[ii]*x[ii]);
66 loc=ii+hold;
70 if(val>peak[0])peak[0]=val;
72 for(ii=1;ii<n;ii++){
73 if((x[ii+ahead]*x[ii+ahead])>val){
74 val=(x[ii+ahead]*x[ii+ahead]);
75 loc=ii+ahead+hold;
77 if(ii>=loc){
78 /* backfill */
79 val=0;
80 for(jj=ii+ahead-1;jj>=ii;jj--){
81 if((x[jj]*x[jj])>val)val=(x[jj]*x[jj]);
82 if(jj<n && val>peak[jj])peak[jj]=val;
84 val=(x[ii+ahead]*x[ii+ahead]);
85 loc=ii+ahead+hold;
87 if(val>peak[ii])peak[ii]=val;
90 ps->loc=loc-input_size;
91 ps->val=val;
94 static void fill_work(float **A, float **B, int ch, float *work,
95 int ahead, int hold, int mode, peak_state *ps){
96 int i,j,k;
98 if(mode){
99 /* peak mode */
101 memset(work,0,sizeof(*work)*input_size);
103 if(B){
104 float bigcache[input_size*2];
105 memcpy(bigcache,A[0],sizeof(*bigcache)*input_size);
106 memcpy(bigcache+input_size,B[0],sizeof(*bigcache)*input_size);
107 for(j=1;j<ch;j++){
108 float *AA = A[j];
109 float *BB = B[j];
110 float *bb = bigcache+input_size;
111 for(i=0;i<input_size;i++)
112 if(bigcache[i]*bigcache[i]<AA[i]*AA[i])
113 bigcache[i]=AA[i];
114 for(i=0;i<input_size;i++)
115 if(bb[i]*bb[i]<BB[i]*BB[i])
116 bb[i]=BB[i];
118 prepare_peak(work, bigcache, input_size, ahead, hold, ps);
119 }else{
120 if(ch>1){
121 float bigcache[input_size];
122 memcpy(bigcache,A[0],sizeof(*bigcache)*input_size);
123 for(j=1;j<ch;j++){
124 float *AA = A[j];
125 for(i=0;i<input_size;i++)
126 if(bigcache[i]*bigcache[i]<AA[i]*AA[i])
127 bigcache[i]=AA[i];
129 prepare_peak(work, bigcache, input_size, ahead, hold, ps);
130 }else{
131 prepare_peak(work, A[0], input_size, ahead, hold, ps);
134 }else{
135 /* rms mode */
136 float *cachea=A[0]+ahead;
138 if(B){
139 float *cacheb=B[0];
140 float *worka=work+input_size-ahead;
142 for(k=0;k<input_size-ahead;k++)
143 work[k]=cachea[k]*cachea[k];
144 for(k=0;k<ahead;k++)
145 worka[k]=cacheb[k]*cacheb[k];
147 for(j=1;j<ch;j++){
148 cachea = A[j]+ahead;
149 cacheb = B[j];
150 for(k=0;k<input_size-ahead;k++)
151 work[k]+=cachea[k]*cachea[k];
152 for(k=0;k<ahead;k++)
153 worka[k]+=cacheb[k]*cacheb[k];
155 if(ch>0){
156 float inv = 1./ch;
157 for(k=0;k<input_size;k++)
158 work[k]*=inv;
161 }else{
163 for(k=0;k<input_size;k++)
164 work[k]=cachea[k]*cachea[k];
165 for(j=1;j<ch;j++){
166 cachea = A[j];
167 for(k=0;k<input_size;k++)
168 work[k]+=cachea[k]*cachea[k];
170 if(ch>0){
171 float inv = 1./ch;
172 for(k=0;k<input_size;k++)
173 work[k]*=inv;
181 void bi_compand(float **A,float **B,
182 int ch,
183 float *adj,
184 float corner,
185 float multiplier,
186 float currmultiplier,
187 float lookahead,
188 int mode,int softknee,
189 iir_filter *attack, iir_filter *decay,
190 iir_state *iir, peak_state *ps,
191 int active,
192 int over){
194 float work[input_size];
195 float kneelevel=fromdB(corner*2);
196 int hold,ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
198 if(ahead>input_size)ahead=input_size;
199 hold=ahead*(1.-lookahead);
200 ahead*=lookahead;
202 fill_work(A,B,ch,work,ahead,hold,mode,ps);
204 multiplier*=.5;
205 currmultiplier*=.5;
207 if(!active || !adj)adj=work;
209 if(over){
210 if(multiplier!=currmultiplier){
211 if(softknee){
212 compute_iir_over_soft_del(work, input_size, iir, attack, decay,
213 kneelevel, multiplier, currmultiplier, adj);
214 }else{
215 compute_iir_over_hard_del(work, input_size, iir, attack, decay,
216 kneelevel, multiplier, currmultiplier, adj);
218 }else{
219 if(softknee){
220 compute_iir_over_soft(work, input_size, iir, attack, decay,
221 kneelevel, multiplier, adj);
222 }else{
223 compute_iir_over_hard(work, input_size, iir, attack, decay,
224 kneelevel, multiplier, adj);
227 }else{
228 if(multiplier!=currmultiplier){
229 if(softknee){
230 compute_iir_under_soft_del(work, input_size, iir, attack, decay,
231 kneelevel, multiplier, currmultiplier, adj);
232 }else{
233 compute_iir_under_hard_del(work, input_size, iir, attack, decay,
234 kneelevel, multiplier, currmultiplier, adj);
236 }else{
237 if(softknee){
238 compute_iir_under_soft(work, input_size, iir, attack, decay,
239 kneelevel, multiplier, adj);
240 }else{
241 compute_iir_under_hard(work, input_size, iir, attack, decay,
242 kneelevel, multiplier, adj);
249 void full_compand(float **A,float **B,int ch,float *adj,
250 float multiplier,float currmultiplier,
251 int mode,
252 iir_filter *attack, iir_filter *decay,
253 iir_state *iir, peak_state *ps,
254 int active){
256 int k;
257 float work[input_size];
258 int ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
260 fill_work(A,B,ch,work,ahead,0,mode,ps);
262 multiplier*=.5;
263 currmultiplier*=.5;
265 compute_iir_symmetric_limited(work, input_size, iir, attack, decay);
267 if(active){
268 if(multiplier!=currmultiplier){
269 float multiplier_add=(currmultiplier-multiplier)/input_size;
271 for(k=0;k<input_size;k++){
272 adj[k]-=(todB_a2(work[k])+adj[k])*multiplier;
273 multiplier+=multiplier_add;
275 }else{
276 for(k=0;k<input_size;k++)
277 adj[k]-=(todB_a2(work[k])+adj[k])*multiplier;