Recognizes if input is ogg or not.
[xiph.git] / postfish / follower.c
blob479db5fab538eb4dc094c6808213b782ae068830
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, float *work,
95 int ahead, int hold, int mode, peak_state *ps){
96 int 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,sizeof(*work)*input_size);
106 memcpy(bigcache+input_size,B,sizeof(*work)*input_size);
108 prepare_peak(work, bigcache, input_size, ahead, hold, ps);
109 }else{
110 prepare_peak(work, A, input_size, ahead, hold, ps);
112 }else{
113 /* rms mode */
114 float *cachea=A+ahead;
116 if(B){
117 float *worka=work+input_size-ahead;
119 for(k=0;k<input_size-ahead;k++)
120 work[k]=cachea[k]*cachea[k];
122 for(k=0;k<ahead;k++)
123 worka[k]=B[k]*B[k];
124 }else{
126 for(k=0;k<input_size;k++)
127 work[k]=cachea[k]*cachea[k];
134 void bi_compand(float *A,float *B,float *adj,
135 float corner,
136 float multiplier,
137 float currmultiplier,
138 float lookahead,
139 int mode,int softknee,
140 iir_filter *attack, iir_filter *decay,
141 iir_state *iir, peak_state *ps,
142 int active,
143 int over){
145 float work[input_size];
146 float kneelevel=fromdB(corner*2);
147 int hold,ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
149 if(ahead>input_size)ahead=input_size;
150 hold=ahead*(1.-lookahead);
151 ahead*=lookahead;
153 fill_work(A,B,work,ahead,hold,mode,ps);
155 multiplier*=.5;
156 currmultiplier*=.5;
158 if(!active || !adj)adj=work;
160 if(over){
161 if(multiplier!=currmultiplier){
162 if(softknee){
163 compute_iir_over_soft_del(work, input_size, iir, attack, decay,
164 kneelevel, multiplier, currmultiplier, adj);
165 }else{
166 compute_iir_over_hard_del(work, input_size, iir, attack, decay,
167 kneelevel, multiplier, currmultiplier, adj);
169 }else{
170 if(softknee){
171 compute_iir_over_soft(work, input_size, iir, attack, decay,
172 kneelevel, multiplier, adj);
173 }else{
174 compute_iir_over_hard(work, input_size, iir, attack, decay,
175 kneelevel, multiplier, adj);
178 }else{
179 if(multiplier!=currmultiplier){
180 if(softknee){
181 compute_iir_under_soft_del(work, input_size, iir, attack, decay,
182 kneelevel, multiplier, currmultiplier, adj);
183 }else{
184 compute_iir_under_hard_del(work, input_size, iir, attack, decay,
185 kneelevel, multiplier, currmultiplier, adj);
187 }else{
188 if(softknee){
189 compute_iir_under_soft(work, input_size, iir, attack, decay,
190 kneelevel, multiplier, adj);
191 }else{
192 compute_iir_under_hard(work, input_size, iir, attack, decay,
193 kneelevel, multiplier, adj);
200 void full_compand(float *A,float *B,float *adj,
201 float multiplier,float currmultiplier,
202 int mode,
203 iir_filter *attack, iir_filter *decay,
204 iir_state *iir, peak_state *ps,
205 int active){
207 int k;
208 float work[input_size];
209 int ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
211 fill_work(A,B,work,ahead,0,mode,ps);
213 multiplier*=.5;
214 currmultiplier*=.5;
216 compute_iir_symmetric_limited(work, input_size, iir, attack, decay);
218 if(active){
219 if(multiplier!=currmultiplier){
220 float multiplier_add=(currmultiplier-multiplier)/input_size;
222 for(k=0;k<input_size;k++){
223 adj[k]-=(todB_a2(work[k])+adj[k])*multiplier;
224 multiplier+=multiplier_add;
226 }else{
227 for(k=0;k<input_size;k++)
228 adj[k]-=(todB_a2(work[k])+adj[k])*multiplier;