5 * Copyright (C) 2002-2005 Monty and Xiph.Org
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)
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.
26 #include "multicompand.h"
35 typedef struct multicompand_feedback
{
36 feedback_generic parent_class
;
41 } multicompand_feedback
;
44 sig_atomic_t static_u
[multicomp_freqs_max
];
45 sig_atomic_t under_ratio
;
47 sig_atomic_t static_o
[multicomp_freqs_max
];
48 sig_atomic_t over_ratio
;
50 sig_atomic_t base_ratio
;
54 feedback_generic_pool feedpool
;
57 iir_filter over_attack
[MAX_INPUT_CHANNELS
];
58 iir_filter over_decay
[MAX_INPUT_CHANNELS
];
60 iir_filter under_attack
[MAX_INPUT_CHANNELS
];
61 iir_filter under_decay
[MAX_INPUT_CHANNELS
];
63 iir_filter base_attack
[MAX_INPUT_CHANNELS
];
64 iir_filter base_decay
[MAX_INPUT_CHANNELS
];
66 iir_state over_iir
[multicomp_freqs_max
][MAX_INPUT_CHANNELS
];
67 int over_delay
[MAX_INPUT_CHANNELS
];
69 iir_state under_iir
[multicomp_freqs_max
][MAX_INPUT_CHANNELS
];
70 int under_delay
[MAX_INPUT_CHANNELS
];
72 iir_state base_iir
[multicomp_freqs_max
][MAX_INPUT_CHANNELS
];
73 int base_delay
[MAX_INPUT_CHANNELS
];
75 peak_state over_peak
[multicomp_freqs_max
][MAX_INPUT_CHANNELS
];
76 peak_state under_peak
[multicomp_freqs_max
][MAX_INPUT_CHANNELS
];
77 peak_state base_peak
[multicomp_freqs_max
][MAX_INPUT_CHANNELS
];
88 multicompand_settings multi_master_set
;
89 multicompand_settings
*multi_channel_set
;
91 static multicompand_state master_state
;
92 static multicompand_state channel_state
;
94 static subband_window sw
[multicomp_banks
];
96 static feedback_generic
*new_multicompand_feedback(void){
97 multicompand_feedback
*ret
=calloc(1,sizeof(*ret
));
98 return (feedback_generic
*)ret
;
101 /* total, peak, rms are pulled in array[freqs][input_ch] order */
103 static int pull_multicompand_feedback(multicompand_state
*ms
,float **peak
,float **rms
,int *b
){
104 multicompand_feedback
*f
=(multicompand_feedback
*)feedback_pull(&ms
->feedpool
);
110 feedback_old(&ms
->feedpool
,(feedback_generic
*)f
);
114 for(i
=0;i
<f
->freq_bands
;i
++)
115 memcpy(peak
[i
],f
->peak
[i
],sizeof(**peak
)*ms
->ch
);
117 for(i
=0;i
<f
->freq_bands
;i
++)
118 memcpy(rms
[i
],f
->rms
[i
],sizeof(**rms
)*ms
->ch
);
119 if(b
)*b
=f
->freq_bands
;
120 feedback_old(&ms
->feedpool
,(feedback_generic
*)f
);
125 int pull_multicompand_feedback_master(float **peak
,float **rms
,int *b
){
126 return pull_multicompand_feedback(&master_state
,peak
,rms
,b
);
129 int pull_multicompand_feedback_channel(float **peak
,float **rms
,int *b
){
130 return pull_multicompand_feedback(&channel_state
,peak
,rms
,b
);
133 static void reset_filters_onech(multicompand_state
*ms
,int ch
){
135 /* delays are only used to softstart individual filters that went
136 inactive at unity; the key is that we know they're starting from
137 mult of zero, which is not necessarily true at a reset */
138 ms
->base_delay
[ch
]=0;
139 ms
->over_delay
[ch
]=0;
140 ms
->under_delay
[ch
]=0;
141 for(i
=0;i
<multicomp_freqs_max
;i
++){
142 memset(&ms
->over_peak
[i
][ch
],0,sizeof(peak_state
));
143 memset(&ms
->under_peak
[i
][ch
],0,sizeof(peak_state
));
144 memset(&ms
->base_peak
[i
][ch
],0,sizeof(peak_state
));
145 memset(&ms
->over_iir
[i
][ch
],0,sizeof(iir_state
));
146 memset(&ms
->under_iir
[i
][ch
],0,sizeof(iir_state
));
147 memset(&ms
->base_iir
[i
][ch
],0,sizeof(iir_state
));
151 static void reset_filters(multicompand_state
*ms
){
153 for(j
=0;j
<ms
->ch
;j
++)
154 reset_filters_onech(ms
,j
);
157 void multicompand_reset(){
159 subband_reset(&master_state
.ss
);
160 subband_reset(&channel_state
.ss
);
161 while(pull_multicompand_feedback_master(NULL
,NULL
,NULL
));
162 while(pull_multicompand_feedback_channel(NULL
,NULL
,NULL
));
163 reset_filters(&master_state
);
164 reset_filters(&channel_state
);
166 master_state
.initstate
=0;
167 channel_state
.initstate
=0;
170 static int multicompand_load_helper(multicompand_state
*ms
,int ch
){
172 int qblocksize
=input_size
/8;
173 memset(ms
,0,sizeof(*ms
));
176 subband_load(&ms
->ss
,multicomp_freqs_max
,qblocksize
,ch
);
178 ms
->peak
=calloc(multicomp_freqs_max
,sizeof(*ms
->peak
));
179 ms
->rms
=calloc(multicomp_freqs_max
,sizeof(*ms
->rms
));
180 for(i
=0;i
<multicomp_freqs_max
;i
++)ms
->peak
[i
]=malloc(ms
->ch
*sizeof(**ms
->peak
));
181 for(i
=0;i
<multicomp_freqs_max
;i
++)ms
->rms
[i
]=malloc(ms
->ch
*sizeof(**ms
->rms
));
183 ms
->prevset
=malloc(ch
*sizeof(*ms
->prevset
));
184 ms
->currset
=malloc(ch
*sizeof(*ms
->currset
));
191 int multicompand_load(int outch
){
193 multi_channel_set
=calloc(input_ch
,sizeof(*multi_channel_set
));
194 multicompand_load_helper(&master_state
,outch
);
195 multicompand_load_helper(&channel_state
,input_ch
);
197 for(i
=0;i
<multicomp_banks
;i
++)
198 subband_load_freqs(&master_state
.ss
,&sw
[i
],multicomp_freq_list
[i
],
204 static void filter_set1(multicompand_state
*ms
,
208 float corner_freq
= 500./msec
;
210 alpha
=corner_freq
/input_rate
;
211 filter
->g
=mkbessel(alpha
,1,filter
->c
);
213 filter
->Hz
=alpha
*input_rate
;
217 static void filter_set2(multicompand_state
*ms
,
221 float corner_freq
= 500./msec
;
223 /* make sure the chosen frequency doesn't require a lookahead
224 greater than what's available */
225 if(step_freq(input_size
*2-ms
->ss
.qblocksize
*3)*1.01>corner_freq
)
226 corner_freq
=step_freq(input_size
*2-ms
->ss
.qblocksize
*3);
228 alpha
=corner_freq
/input_rate
;
229 filter
->g
=mkbessel(alpha
,2,filter
->c
);
231 filter
->Hz
=alpha
*input_rate
;
235 static void filterbank_set1(multicompand_state
*ms
,
239 for(i
=0;i
<ms
->ch
;i
++)
240 filter_set1(ms
,msec
,filter
+i
);
244 static void filterbank_set2(multicompand_state
*ms
,
248 for(i
=0;i
<ms
->ch
;i
++)
249 filter_set2(ms
,msec
,filter
+i
);
253 static int find_maxbands(subband_state
*ss
,int channel
){
254 int maxbands
=ss
->wC
[channel
]->freq_bands
;
255 if(maxbands
<ss
->w0
[channel
]->freq_bands
)maxbands
=ss
->w0
[channel
]->freq_bands
;
256 if(maxbands
<ss
->w1
[channel
]->freq_bands
)maxbands
=ss
->w1
[channel
]->freq_bands
;
260 static int multicompand_work_perchannel(multicompand_state
*ms
,
265 atten_cache
*prevset
,
266 atten_cache
*currset
,
267 multicompand_settings
*c
){
268 subband_state
*ss
=&ms
->ss
;
269 int active
=(ss
->effect_active1
[channel
] ||
270 ss
->effect_active0
[channel
] ||
271 ss
->effect_activeC
[channel
]);
275 subband_window
*w
=ss
->w1
[channel
];
276 subband_window
*wP
=ss
->wP
[channel
];
277 float adj
[input_size
];
279 int o_active
=0,u_active
=0,b_active
=0;
288 for(i
=0;i
<multicomp_freqs_max
;i
++){
289 currset
->static_u
[i
]=c
->bc
[bank
].static_u
[i
];
290 currset
->static_o
[i
]=c
->bc
[bank
].static_o
[i
];
293 currset
->under_ratio
=c
->under_ratio
;
294 currset
->over_ratio
=c
->over_ratio
;
295 currset
->base_ratio
=c
->base_ratio
;
297 /* don't slew from an unknown value */
298 if(!ss
->effect_activeP
[channel
] || !ms
->initstate
)
299 memcpy(prevset
,currset
,sizeof(*currset
));
301 /* don't run filters that will be applied at unity */
302 if(prevset
->under_ratio
==1000 && currset
->under_ratio
==1000){
303 ms
->under_delay
[channel
]=2;
304 for(i
=0;i
<multicomp_freqs_max
;i
++){
305 memset(&ms
->under_peak
[i
][channel
],0,sizeof(peak_state
));
306 memset(&ms
->under_iir
[i
][channel
],0,sizeof(iir_state
));
309 if(ms
->under_delay
[channel
]-->0)currset
->under_ratio
=1000;
310 if(ms
->under_delay
[channel
]<0)ms
->under_delay
[channel
]=0;
314 if(prevset
->over_ratio
==1000 && currset
->over_ratio
==1000){
315 ms
->over_delay
[channel
]=2;
316 for(i
=0;i
<multicomp_freqs_max
;i
++){
317 memset(&ms
->over_peak
[i
][channel
],0,sizeof(peak_state
));
318 memset(&ms
->over_iir
[i
][channel
],0,sizeof(iir_state
));
321 if(ms
->over_delay
[channel
]-->0)currset
->over_ratio
=1000;
322 if(ms
->over_delay
[channel
]<0)ms
->over_delay
[channel
]=0;
326 if(prevset
->base_ratio
==1000 && currset
->base_ratio
==1000){
327 ms
->base_delay
[channel
]=2;
328 for(i
=0;i
<multicomp_freqs_max
;i
++){
329 memset(&ms
->base_peak
[i
][channel
],0,sizeof(peak_state
));
330 memset(&ms
->base_iir
[i
][channel
],0,sizeof(iir_state
));
333 if(ms
->base_delay
[channel
]-->0)currset
->base_ratio
=1000;
334 if(ms
->base_delay
[channel
]<0)ms
->base_delay
[channel
]=0;
338 } else if (ss
->effect_activeP
[channel
]){
339 /* this lapping channel just became inactive */
340 reset_filters_onech(ms
,channel
);
343 /* one thing is worth a note here; 'maxbands' can be
344 'overrange' for the current bank. This is intentional; we
345 may need to run the additional (allocated and valid)
346 filters before or after their bands are active. The only
347 garbage data here is the xxxx_u, xxxx_o and xxxx_b
348 settings. There are allocated, but unset; if overrange,
349 they're ignored in the compand worker */
351 for(i
=0;i
<maxbands
;i
++){
353 float *x
=ss
->lap
[i
][channel
];
355 if(u_active
|| o_active
|| b_active
)
356 memset(adj
,0,sizeof(*adj
)*input_size
);
359 bi_compand(x
,0,(i
>=w
->freq_bands
?0:adj
),
360 //prevset->static_u[i],
361 currset
->static_u
[i
],
362 1.f
-1000.f
/prevset
->under_ratio
,
363 1.f
-1000.f
/currset
->under_ratio
,
364 c
->under_lookahead
/1000.f
,
367 &ms
->under_attack
[channel
],
368 &ms
->under_decay
[channel
],
369 &ms
->under_iir
[i
][channel
],
370 &ms
->under_peak
[i
][channel
],
371 ss
->effect_active1
[channel
] &&
376 bi_compand(x
,0,(i
>=w
->freq_bands
?0:adj
),
377 //prevset->static_o[i],
378 currset
->static_o
[i
],
379 1.f
-1000.f
/prevset
->over_ratio
,
380 1.f
-1000.f
/currset
->over_ratio
,
381 c
->over_lookahead
/1000.f
,
384 &ms
->over_attack
[channel
],
385 &ms
->over_decay
[channel
],
386 &ms
->over_iir
[i
][channel
],
387 &ms
->over_peak
[i
][channel
],
388 ss
->effect_active1
[channel
] &&
392 if(ss
->visible1
[channel
]){
395 if(!mute_channel_muted(ss
->mutemask1
,channel
)){
396 /* determine rms and peak for feedback */
401 for(k
=0;k
<input_size
;k
++){
409 if(u_active
|| o_active
|| b_active
){
410 peakfeed
[i
][channel
]=todB(max
)*.5+adj
[maxpos
];
411 rmsfeed
[i
][channel
]=todB(rms
/input_size
)*.5+adj
[maxpos
];
413 peakfeed
[i
][channel
]=todB(max
)*.5;
414 rmsfeed
[i
][channel
]=todB(rms
/input_size
)*.5;
420 full_compand(x
,0,(i
>=w
->freq_bands
?0:adj
),
421 1.f
-1000.f
/prevset
->base_ratio
,
422 1.f
-1000.f
/currset
->base_ratio
,
424 &ms
->base_attack
[channel
],
425 &ms
->base_decay
[channel
],
426 &ms
->base_iir
[i
][channel
],
427 &ms
->base_peak
[i
][channel
],
428 ss
->effect_active1
[channel
] &&
431 if(u_active
|| o_active
|| b_active
){
432 if(ss
->effect_active1
[channel
]){
433 for(k
=0;k
<input_size
;k
++)
434 x
[k
]*=fromdB_a(adj
[k
]);
439 for(;i
<wP
->freq_bands
;i
++){
440 memset(&ms
->over_peak
[i
][channel
],0,sizeof(peak_state
));
441 memset(&ms
->under_peak
[i
][channel
],0,sizeof(peak_state
));
442 memset(&ms
->base_peak
[i
][channel
],0,sizeof(peak_state
));
443 memset(&ms
->over_iir
[i
][channel
],0,sizeof(iir_state
));
444 memset(&ms
->under_iir
[i
][channel
],0,sizeof(iir_state
));
445 memset(&ms
->base_iir
[i
][channel
],0,sizeof(iir_state
));
450 static void push_feedback(multicompand_state
*ms
,int bypass
,int maxmaxbands
){
454 multicompand_feedback
*ff
=
455 (multicompand_feedback
*)
456 feedback_new(&ms
->feedpool
,new_multicompand_feedback
);
458 feedback_push(&ms
->feedpool
,(feedback_generic
*)ff
);
460 multicompand_feedback
*ff
=
461 (multicompand_feedback
*)
462 feedback_new(&ms
->feedpool
,new_multicompand_feedback
);
465 ff
->peak
=malloc(multicomp_freqs_max
*sizeof(*ff
->peak
));
466 ff
->rms
=malloc(multicomp_freqs_max
*sizeof(*ff
->rms
));
468 for(i
=0;i
<multicomp_freqs_max
;i
++)
469 ff
->rms
[i
]=malloc(ms
->ch
*sizeof(**ff
->rms
));
470 for(i
=0;i
<multicomp_freqs_max
;i
++)
471 ff
->peak
[i
]=malloc(ms
->ch
*sizeof(**ff
->peak
));
474 for(i
=0;i
<maxmaxbands
;i
++){
475 memcpy(ff
->peak
[i
],ms
->peak
[i
],ms
->ch
*sizeof(**ms
->peak
));
476 memcpy(ff
->rms
[i
],ms
->rms
[i
],ms
->ch
*sizeof(**ms
->rms
));
479 ff
->freq_bands
=maxmaxbands
;
480 feedback_push(&ms
->feedpool
,(feedback_generic
*)ff
);
484 static void multicompand_work_master(void *vs
){
485 multicompand_state
*ms
=(multicompand_state
*)vs
;
486 int i
,j
,bypass_visible
=1;
489 for(i
=0;i
<multicomp_freqs_max
;i
++){
490 for(j
=0;j
<ms
->ch
;j
++){
491 ms
->peak
[i
][j
]=-150.;
496 for(i
=0;i
<ms
->ch
;i
++){
497 int maxbands
=find_maxbands(&ms
->ss
,i
);
498 if(maxbands
>maxmaxbands
)maxmaxbands
=maxbands
;
499 if(multicompand_work_perchannel(ms
, ms
->peak
, ms
->rms
, maxbands
, i
,
500 &ms
->prevset
[i
], &ms
->currset
[i
], &multi_master_set
))
504 atten_cache
*temp
=ms
->prevset
;
505 ms
->prevset
=ms
->currset
;
510 push_feedback(ms
,bypass_visible
,maxmaxbands
);
513 static void multicompand_work_channel(void *vs
){
514 multicompand_state
*ms
=(multicompand_state
*)vs
;
515 int i
,j
,bypass_visible
=1;
518 for(i
=0;i
<multicomp_freqs_max
;i
++){
519 for(j
=0;j
<ms
->ch
;j
++){
520 ms
->peak
[i
][j
]=-150.;
525 for(i
=0;i
<ms
->ch
;i
++){
526 int maxbands
=find_maxbands(&ms
->ss
,i
);
527 if(maxbands
>maxmaxbands
)maxmaxbands
=maxbands
;
528 if(multicompand_work_perchannel(ms
, ms
->peak
, ms
->rms
, maxbands
, i
,
529 &ms
->prevset
[i
], &ms
->currset
[i
], multi_channel_set
+i
))
533 atten_cache
*temp
=ms
->prevset
;
534 ms
->prevset
=ms
->currset
;
539 push_feedback(ms
,bypass_visible
,maxmaxbands
);
542 time_linkage
*multicompand_read_master(time_linkage
*in
){
543 multicompand_state
*ms
=&master_state
;
546 subband_window
*w
[ms
->ch
];
547 int i
,ab
=multi_master_set
.active_bank
;
549 for(i
=0;i
<ms
->ch
;i
++){
550 visible
[i
]=multi_master_set
.panel_visible
;
551 active
[i
]=multi_master_set
.panel_active
;
555 /* do any filters need updated from UI changes? */
557 float o_attackms
=multi_master_set
.over_attack
*.1;
558 float o_decayms
=multi_master_set
.over_decay
*.1;
559 float u_attackms
=multi_master_set
.under_attack
*.1;
560 float u_decayms
=multi_master_set
.under_decay
*.1;
561 float b_attackms
=multi_master_set
.base_attack
*.1;
562 float b_decayms
=multi_master_set
.base_decay
*.1;
564 if(o_attackms
!=ms
->over_attack
[0].ms
)
565 filterbank_set2(ms
,o_attackms
,ms
->over_attack
);
566 if(o_decayms
!=ms
->over_decay
[0].ms
)
567 filterbank_set1(ms
,o_decayms
,ms
->over_decay
);
568 if(u_attackms
!=ms
->under_attack
[0].ms
)
569 filterbank_set2(ms
,u_attackms
,ms
->under_attack
);
570 if(u_decayms
!=ms
->under_decay
[0].ms
)
571 filterbank_set1(ms
,u_decayms
,ms
->under_decay
);
572 if(b_attackms
!=ms
->base_attack
[0].ms
)
573 filterbank_set2(ms
,b_attackms
,ms
->base_attack
);
574 if(b_decayms
!=ms
->base_decay
[0].ms
)
575 filterbank_set1(ms
,b_decayms
,ms
->base_decay
);
578 return subband_read(in
, &master_state
.ss
, w
, visible
,active
,
579 multicompand_work_master
,&master_state
);
582 time_linkage
*multicompand_read_channel(time_linkage
*in
){
583 multicompand_state
*ms
=&channel_state
;
586 subband_window
*w
[ms
->ch
];
589 for(i
=0;i
<ms
->ch
;i
++){
591 /* do any filters need updated from UI changes? */
592 float o_attackms
=multi_channel_set
[i
].over_attack
*.1;
593 float o_decayms
=multi_channel_set
[i
].over_decay
*.1;
594 float u_attackms
=multi_channel_set
[i
].under_attack
*.1;
595 float u_decayms
=multi_channel_set
[i
].under_decay
*.1;
596 float b_attackms
=multi_channel_set
[i
].base_attack
*.1;
597 float b_decayms
=multi_channel_set
[i
].base_decay
*.1;
599 if(o_attackms
!=ms
->over_attack
[i
].ms
)
600 filter_set2(ms
,o_attackms
,ms
->over_attack
+i
);
601 if(o_decayms
!=ms
->over_decay
[i
].ms
)
602 filter_set1(ms
,o_decayms
,ms
->over_decay
+i
);
603 if(u_attackms
!=ms
->under_attack
[i
].ms
)
604 filter_set2(ms
,u_attackms
,ms
->under_attack
+i
);
605 if(u_decayms
!=ms
->under_decay
[i
].ms
)
606 filter_set1(ms
,u_decayms
,ms
->under_decay
+i
);
607 if(b_attackms
!=ms
->base_attack
[i
].ms
)
608 filter_set2(ms
,b_attackms
,ms
->base_attack
+i
);
609 if(b_decayms
!=ms
->base_decay
[i
].ms
)
610 filter_set1(ms
,b_decayms
,ms
->base_decay
+i
);
612 w
[i
]=&sw
[multi_channel_set
[i
].active_bank
];
613 visible
[i
]=multi_channel_set
[i
].panel_visible
;
614 active
[i
]=multi_channel_set
[i
].panel_active
;
617 return subband_read(in
, &channel_state
.ss
, w
, visible
, active
,
618 multicompand_work_channel
,&channel_state
);