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)
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.
30 extern int input_size
;
31 extern int input_rate
;
33 mix_settings
*mix_set
;
35 sig_atomic_t atten_visible
;
36 sig_atomic_t *mixpanel_active
;
37 sig_atomic_t *mixpanel_visible
;
42 feedback_generic_pool feedpool
;
61 /* this should be moved somewhere obvious/generic */
65 typedef struct limit_feedback
{
66 feedback_generic parent_class
;
72 static feedback_generic
*new_mix_feedback(void){
73 mix_feedback
*ret
=calloc(1,sizeof(*ret
));
74 return (feedback_generic
*)ret
;
77 /* peak, rms are pulled in array[mixblock][input_ch] order */
78 int pull_mix_feedback(float **peak
,float **rms
){
79 mix_feedback
*f
=(mix_feedback
*)feedback_pull(&ms
.feedpool
);
85 feedback_old(&ms
.feedpool
,(feedback_generic
*)f
);
89 for(i
=0;i
<MIX_BLOCKS
+5;i
++)
90 memcpy(peak
[i
],f
->peak
[i
],sizeof(**peak
)*input_ch
);
92 for(i
=0;i
<MIX_BLOCKS
+5;i
++)
93 memcpy(rms
[i
],f
->rms
[i
],sizeof(**rms
)*input_ch
);
94 feedback_old(&ms
.feedpool
,(feedback_generic
*)f
);
99 /* called only by initial setup */
100 int mix_load(int outch
){
103 mix_set
=calloc(input_ch
,sizeof(*mix_set
));
104 mixpanel_active
=calloc(input_ch
,sizeof(*mixpanel_active
));
105 mixpanel_visible
=calloc(input_ch
,sizeof(*mixpanel_visible
));
107 memset(&ms
,0,sizeof(ms
));
108 ms
.prev
=calloc(input_ch
,sizeof(*ms
.prev
));
109 ms
.curr
=calloc(input_ch
,sizeof(*ms
.curr
));
111 ms
.cacheP
=malloc(input_ch
*sizeof(*ms
.cacheP
));
112 ms
.cachePP
=malloc(input_ch
*sizeof(*ms
.cachePP
));
113 ms
.cachePA
=malloc(input_ch
*sizeof(*ms
.cachePA
));
114 ms
.cachePPA
=malloc(input_ch
*sizeof(*ms
.cachePPA
));
115 ms
.cachePB
=malloc(input_ch
*sizeof(*ms
.cachePB
));
116 ms
.cachePPB
=malloc(input_ch
*sizeof(*ms
.cachePPB
));
117 for(i
=0;i
<input_ch
;i
++)
118 ms
.cacheP
[i
]=malloc(input_size
*sizeof(**ms
.cacheP
));
119 for(i
=0;i
<input_ch
;i
++)
120 ms
.cachePP
[i
]=malloc(input_size
*sizeof(**ms
.cachePP
));
121 for(i
=0;i
<input_ch
;i
++)
122 ms
.cachePA
[i
]=malloc(input_size
*sizeof(**ms
.cachePA
));
123 for(i
=0;i
<input_ch
;i
++)
124 ms
.cachePPA
[i
]=malloc(input_size
*sizeof(**ms
.cachePPA
));
125 for(i
=0;i
<input_ch
;i
++)
126 ms
.cachePB
[i
]=malloc(input_size
*sizeof(**ms
.cachePB
));
127 for(i
=0;i
<input_ch
;i
++)
128 ms
.cachePPB
[i
]=malloc(input_size
*sizeof(**ms
.cachePPB
));
130 ms
.out
.channels
=outch
;
131 ms
.out
.data
=malloc(outch
*sizeof(*ms
.out
.data
));
133 ms
.out
.data
[i
]=malloc(input_size
*sizeof(**ms
.out
.data
));
135 window
=window_get(1,input_size
);
140 /* called only in playback thread */
142 while(pull_mix_feedback(NULL
,NULL
));
147 static void mixwork(float *data
,float *cacheP
,float *cachePP
,
149 float att
,int del
,int inv
,
150 float attP
,float delP
,int invP
){
154 if(-del
>input_size
*2)del
= -input_size
*2;
155 if(-delP
>input_size
*2)delP
= -input_size
*2;
160 if(att
==attP
&& del
==delP
){
162 /* straight copy from cache with attenuation */
164 while(i
<input_size
&& offset
<input_size
)
165 out
[offset
++]+=cachePP
[i
++]*att
;
169 while(i
<input_size
&& offset
<input_size
)
170 out
[offset
++]+=cacheP
[i
++]*att
;
173 while(offset
<input_size
)
174 out
[offset
++]+=data
[i
++]*att
;
177 /* lapped dual copy from cache */
179 /* current settings */
181 while(i
<input_size
&& offset
<input_size
){
182 out
[offset
]+=cachePP
[i
++]*att
*window
[offset
];
188 while(i
<input_size
&& offset
<input_size
){
189 out
[offset
]+=cacheP
[i
++]*att
*window
[offset
];
194 while(offset
<input_size
){
195 out
[offset
]+=data
[i
++]*att
*window
[offset
];
199 /* ...lapped transition from old settings */
202 while(i
<input_size
&& offset
<input_size
){
203 out
[offset
]+=cachePP
[i
++]*attP
*window
[input_size
-offset
-1];
209 while(i
<input_size
&& offset
<input_size
){
210 out
[offset
]+=cacheP
[i
++]*attP
*window
[input_size
-offset
-1];
215 while(offset
<input_size
){
216 out
[offset
]+=data
[i
++]*attP
*window
[input_size
-offset
-1];
222 /* smooth active/inactive transitions while adding */
223 static void mixadd(float *in
,float *out
,int active
,int activeP
){
225 if(!active
&& !activeP
)return;
226 if(active
&& activeP
){
227 for(i
=0;i
<input_size
;i
++)
231 /* mutes no longer need be transitioned */
234 /* called only by playback thread */
235 time_linkage
*mix_read(time_linkage
*in
,
236 time_linkage
*inA
, // reverb channel
237 time_linkage
*inB
){ // reverb channel
239 int i
,j
,k
,outch
=ms
.out
.channels
;
240 int outactive
[outch
];
242 float peak
[MIX_BLOCKS
+5][input_ch
];
243 float rms
[MIX_BLOCKS
+5][input_ch
];
250 memset(outactive
,0,sizeof(outactive
));
251 memset(peak
,0,sizeof(peak
));
252 memset(rms
,0,sizeof(rms
));
254 /* eliminate asynch change possibility */
255 memcpy(ms
.curr
,mix_set
,sizeof(*mix_set
)*input_ch
);
257 /* fillstate here is only used for lazy initialization/reset */
260 for(i
=0;i
<input_ch
;i
++){
261 memset(ms
.cacheP
[i
],0,sizeof(**ms
.cacheP
)*input_size
);
262 memset(ms
.cachePP
[i
],0,sizeof(**ms
.cachePP
)*input_size
);
263 memset(ms
.cachePA
[i
],0,sizeof(**ms
.cachePA
)*input_size
);
264 memset(ms
.cachePPA
[i
],0,sizeof(**ms
.cachePPA
)*input_size
);
265 memset(ms
.cachePB
[i
],0,sizeof(**ms
.cachePB
)*input_size
);
266 memset(ms
.cachePPB
[i
],0,sizeof(**ms
.cachePPB
)*input_size
);
268 memcpy(ms
.prev
,ms
.curr
,sizeof(*mix_set
)*input_ch
);
272 /* zero the output block; we'll me mixing into it input-by-input */
274 memset(ms
.out
.data
[i
],0,sizeof(**ms
.out
.data
)*input_size
);
276 /* a bit of laziness that may actually save CPU time by avoiding
277 special-cases later */
278 for(i
=0;i
<input_ch
;i
++){
279 if(mute_channel_muted(in
->active
,i
))
280 memset(in
->data
[i
],0,sizeof(**in
->data
)*input_size
);
281 if(mute_channel_muted(inA
->active
,i
))
282 memset(inA
->data
[i
],0,sizeof(**inA
->data
)*input_size
);
283 if(mute_channel_muted(inB
->active
,i
))
284 memset(inB
->data
[i
],0,sizeof(**inB
->data
)*input_size
);
288 for(i
=0;i
<input_ch
;i
++){
289 int feedit
=mixpanel_visible
[i
];
290 int feeditM
=atten_visible
;
292 /* master feedback is a bit of a pain; the metrics we need aren't
293 produced by any of the mixdowns below. Do it by hand */
295 float mix
[input_size
];
296 float att
=fromdB(ms
.curr
[i
].master_att
* .1);
297 int del
=rint(ms
.curr
[i
].master_delay
*.00001*input_rate
);
300 if(!mute_channel_muted(in
->active
,i
)){
301 memset(mix
,0,sizeof(mix
));
302 mixwork(in
->data
[i
],ms
.cacheP
[i
],ms
.cachePP
[i
],
303 mix
,att
,del
,0,att
,del
,0);
306 for(j
=0;j
<input_size
;j
++){
307 float val
=mix
[j
]*mix
[j
];
308 if(val
>peak
[0][i
])peak
[0][i
]=val
;
312 rms
[0][i
]=acc
/input_size
;
316 if(inA
&& !mute_channel_muted(inA
->active
,i
)){
317 memset(mix
,0,sizeof(mix
));
318 mixwork(inA
->data
[i
],ms
.cachePA
[i
],ms
.cachePPA
[i
],
319 mix
,att
,del
,0,att
,del
,0);
322 for(j
=0;j
<input_size
;j
++){
323 float val
=mix
[j
]*mix
[j
];
324 if(val
>peak
[1][i
])peak
[1][i
]=val
;
328 rms
[1][i
]=acc
/input_size
;
332 if(inB
&& !mute_channel_muted(inB
->active
,i
)){
333 memset(mix
,0,sizeof(mix
));
334 mixwork(inB
->data
[i
],ms
.cachePB
[i
],ms
.cachePPB
[i
],
335 mix
,att
,del
,0,att
,del
,0);
338 for(j
=0;j
<input_size
;j
++){
339 float val
=mix
[j
]*mix
[j
];
340 if(val
>peak
[2][i
])peak
[2][i
]=val
;
344 rms
[2][i
]=acc
/input_size
;
348 /* placer settings; translate to final numbers */
349 int placer
=ms
.curr
[i
].placer_place
;
350 int placerP
=ms
.prev
[i
].placer_place
;
354 int mixedA
=0,mixedB
=0;
355 float mixA
[input_size
],mixB
[input_size
];
357 for(j
=0;j
<OUTPUT_CHANNELS
;j
++){
358 int destA
=ms
.curr
[i
].placer_destA
[j
];
359 int destAP
=ms
.prev
[i
].placer_destA
[j
];
360 int destB
=ms
.curr
[i
].placer_destB
[j
];
361 int destBP
=ms
.prev
[i
].placer_destB
[j
];
367 float relA
=(placer
>100 ? placer
*.01-1. : 0.);
368 float relAP
=(placerP
>100 ? placerP
*.01-1. : 0.);
370 float attA
=fromdB((ms
.curr
[i
].master_att
+ ms
.curr
[i
].placer_att
* relA
)*.1);
371 float attAP
=fromdB((ms
.prev
[i
].master_att
+ ms
.prev
[i
].placer_att
* relAP
)*.1);
372 int delA
=rint((ms
.curr
[i
].master_delay
+ ms
.curr
[i
].placer_delay
* relA
)*.00001*input_rate
);
373 int delAP
=rint((ms
.prev
[i
].master_delay
+ ms
.prev
[i
].placer_delay
* relAP
)*.00001*input_rate
);
375 float attA_r
=fromdB(ms
.curr
[i
].master_att
*.1);
376 float attAP_r
=fromdB(ms
.prev
[i
].master_att
*.1);
377 int delA_r
=rint(ms
.curr
[i
].master_delay
*.00001*input_rate
);
378 int delAP_r
=rint(ms
.prev
[i
].master_delay
*.00001*input_rate
);
380 memset(mixA
,0,sizeof(mixA
));
381 mixwork(in
->data
[i
],ms
.cacheP
[i
],ms
.cachePP
[i
],
382 mixA
,attA
,delA
,0,attAP
,delAP
,0);
383 mixwork(inA
->data
[i
],ms
.cachePA
[i
],ms
.cachePPA
[i
],
384 mixA
,attA_r
,delA_r
,0,attAP_r
,delAP_r
,0);
388 mixadd(mixA
,ms
.out
.data
[j
],destA
,destAP
);
394 float relB
=(placer
<100 ? 1.-placer
*.01 : 0.);
395 float relBP
=(placerP
<100 ? 1.-placerP
*.01 : 0.);
397 float attB
=fromdB((ms
.curr
[i
].master_att
+ ms
.curr
[i
].placer_att
* relB
)*.1);
398 float attBP
=fromdB((ms
.prev
[i
].master_att
+ ms
.prev
[i
].placer_att
* relBP
)*.1);
399 int delB
=rint((ms
.curr
[i
].master_delay
+ ms
.curr
[i
].placer_delay
* relB
)*.00001*input_rate
);
400 int delBP
= rint((ms
.prev
[i
].master_delay
+ ms
.prev
[i
].placer_delay
* relBP
)*.00001*input_rate
);
402 float attB_r
=fromdB(ms
.curr
[i
].master_att
*.1);
403 float attBP_r
=fromdB(ms
.prev
[i
].master_att
*.1);
404 int delB_r
=rint(ms
.curr
[i
].master_delay
*.00001*input_rate
);
405 int delBP_r
= rint(ms
.prev
[i
].master_delay
*.00001*input_rate
);
407 memset(mixB
,0,sizeof(mixB
));
408 mixwork(in
->data
[i
],ms
.cacheP
[i
],ms
.cachePP
[i
],
409 mixB
,attB
,delB
,0,attBP
,delBP
,0);
410 mixwork(inB
->data
[i
],ms
.cachePB
[i
],ms
.cachePPB
[i
],
411 mixB
,attB_r
,delB_r
,0,attBP_r
,delBP_r
,0);
414 mixadd(mixB
,ms
.out
.data
[j
],destB
,destBP
);
423 for(j
=0;j
<input_size
;j
++){
424 float val
=mixA
[j
]*mixA
[j
];
425 if(val
>peak
[3][i
])peak
[3][i
]=val
;
429 peak
[3][i
]=peak
[3][i
];
430 rms
[3][i
]=acc
/input_size
;
439 for(j
=0;j
<input_size
;j
++){
440 float val
=mixB
[j
]*mixB
[j
];
441 if(val
>peak
[4][i
])peak
[4][i
]=val
;
445 peak
[4][i
]=peak
[4][i
];
446 rms
[4][i
]=acc
/input_size
;
451 /* direct block mix */
452 for(k
=0;k
<MIX_BLOCKS
;k
++){
453 float mix
[input_size
];
455 int sourceM
=ms
.curr
[i
].insert_source
[k
][0];
456 int sourceMP
=ms
.prev
[i
].insert_source
[k
][0];
457 int sourceA
=ms
.curr
[i
].insert_source
[k
][1];
458 int sourceAP
=ms
.prev
[i
].insert_source
[k
][1];
459 int sourceB
=ms
.curr
[i
].insert_source
[k
][2];
460 int sourceBP
=ms
.prev
[i
].insert_source
[k
][2];
463 fromdB((ms
.curr
[i
].master_att
+
464 ms
.curr
[i
].insert_att
[k
])*.1);
467 rint((ms
.curr
[i
].master_delay
+
468 ms
.curr
[i
].insert_delay
[k
])*.00001*input_rate
);
471 fromdB((ms
.prev
[i
].master_att
+
472 ms
.prev
[i
].insert_att
[k
])*.1);
475 rint((ms
.prev
[i
].master_delay
+
476 ms
.prev
[i
].insert_delay
[k
])*.00001*input_rate
);
478 if(sourceM
|| sourceMP
||
479 sourceA
|| sourceAP
||
480 sourceB
|| sourceBP
){
481 memset(mix
,0,sizeof(mix
));
484 if(sourceM
|| sourceMP
)
485 mixwork(in
->data
[i
],ms
.cacheP
[i
],ms
.cachePP
[i
],
488 del
,ms
.curr
[i
].insert_invert
[k
],
489 (sourceMP
? attP
: 0),
490 delP
,ms
.prev
[i
].insert_invert
[k
]);
493 if(sourceA
|| sourceAP
)
495 mixwork(inA
->data
[i
],ms
.cachePA
[i
],ms
.cachePPA
[i
],
498 del
,ms
.curr
[i
].insert_invert
[k
],
499 (sourceAP
? attP
: 0),
500 delP
,ms
.prev
[i
].insert_invert
[k
]);
503 if(sourceB
|| sourceBP
)
505 mixwork(inB
->data
[i
],ms
.cachePB
[i
],ms
.cachePPB
[i
],
508 del
,ms
.curr
[i
].insert_invert
[k
],
509 (sourceBP
? attP
: 0),
510 delP
,ms
.prev
[i
].insert_invert
[k
]);
512 /* mix into output */
513 for(j
=0;j
<OUTPUT_CHANNELS
;j
++){
514 int dest
=ms
.curr
[i
].insert_dest
[k
][j
];
515 int destP
=ms
.prev
[i
].insert_dest
[k
][j
];
519 mixadd(mix
,ms
.out
.data
[j
],dest
,destP
);
527 for(j
=0;j
<input_size
;j
++){
528 float val
=mix
[j
]*mix
[j
];
529 if(val
>peak
[5+k
][i
])peak
[5+k
][i
]=val
;
533 peak
[5+k
][i
]=peak
[5+k
][i
];
534 rms
[5+k
][i
]=acc
/input_size
;
539 /* rotate data cache */
541 float *temp
=ms
.cachePP
[i
];
542 ms
.cachePP
[i
]=ms
.cacheP
[i
];
543 ms
.cacheP
[i
]=in
->data
[i
];
548 ms
.cachePPA
[i
]=ms
.cachePA
[i
];
549 ms
.cachePA
[i
]=inA
->data
[i
];
555 ms
.cachePPB
[i
]=ms
.cachePB
[i
];
556 ms
.cachePB
[i
]=inB
->data
[i
];
562 /* finish output data */
563 ms
.out
.samples
=in
->samples
;
565 for(i
=0;i
<OUTPUT_CHANNELS
;i
++)
567 ms
.out
.active
|=(1<<i
);
569 /* rotate settings cache */
571 mix_settings
*temp
=ms
.curr
;
579 (mix_feedback
*)feedback_new(&ms
.feedpool
,new_mix_feedback
);
581 feedback_push(&ms
.feedpool
,(feedback_generic
*)mf
);
584 (mix_feedback
*)feedback_new(&ms
.feedpool
,new_mix_feedback
);
587 mf
->peak
=malloc((MIX_BLOCKS
+5)*sizeof(*mf
->peak
));
588 mf
->rms
=malloc((MIX_BLOCKS
+5)*sizeof(*mf
->rms
));
590 for(i
=0;i
<MIX_BLOCKS
+5;i
++)
591 mf
->rms
[i
]=malloc(input_ch
*sizeof(**mf
->rms
));
592 for(i
=0;i
<MIX_BLOCKS
+5;i
++)
593 mf
->peak
[i
]=malloc(input_ch
*sizeof(**mf
->peak
));
596 for(i
=0;i
<MIX_BLOCKS
+5;i
++){
597 memcpy(mf
->peak
[i
],peak
[i
],input_ch
*sizeof(**peak
));
598 memcpy(mf
->rms
[i
],rms
[i
],input_ch
*sizeof(**rms
));
601 feedback_push(&ms
.feedpool
,(feedback_generic
*)mf
);