1 /* Copyright 2015 Sami Boukortt
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include "intersect.h"
18
19 #include <fftw3.h>
20 #include <string.h>
21 #include "types.h"
22 #include "util.h"
23
amplitude_squared(const float c[2])24 static float amplitude_squared(const float c[2]) {
25 return c[0] * c[0] + c[1] * c[1];
26 }
27
run(LV2_Handle handle,uint32_t sample_count,Effect effect)28 static void run(LV2_Handle handle, uint32_t sample_count, Effect effect) {
29 Intersect *intersect = handle;
30 float *cursor_input [2] = {intersect->input [LEFT], intersect->input [RIGHT]},
31 *cursor_output[3] = {intersect->output[LEFT], intersect->output[RIGHT], intersect->output[CENTER]};
32
33 while (sample_count > 0) {
34 const uint32_t block_size = min(sample_count, intersect->fft_jump_size - intersect->deviation);
35 uint32_t i;
36
37 for (i = 0; i < block_size; ++i) {
38 cursor_output[0][i] = intersect->output_buffer[CENTER][i + intersect->deviation] * intersect->normalization_factor;
39 }
40
41 switch (effect) {
42 case INTERSECT: break;
43
44 case UPMIX:
45 memcpy(cursor_output[CENTER], cursor_output[0], block_size * sizeof(float));
46
47 /* fallthrough */
48 case SYMMETRIC_DIFFERENCE: {
49 int c_;
50 for (c_ = 0; c_ < 2; ++c_) {
51 const int c = 1 - c_;
52 for (i = 0; i < block_size; ++i) {
53 cursor_output[c][i] = intersect->output_buffer[c][i + intersect->deviation] - cursor_output[0][i];
54 }
55 }
56 break;
57 }
58 }
59
60 for (i = 0; i < 2; ++i) {
61 memcpy(
62 intersect->input_buffer[i] + intersect->fft_size - intersect->fft_jump_size + intersect->deviation,
63 cursor_input[i],
64 block_size * sizeof(float)
65 );
66 }
67
68 intersect->deviation += block_size;
69
70 if (intersect->deviation == intersect->fft_jump_size) {
71 memmove(intersect->output_buffer[CENTER], intersect->output_buffer[CENTER] + intersect->fft_jump_size, (intersect->fft_size - intersect->fft_jump_size) * sizeof(float));
72 memset(intersect->output_buffer[CENTER] + (intersect->fft_size - intersect->fft_jump_size), 0, intersect->fft_jump_size * sizeof(float));
73
74 fftwf_execute(intersect->plan_r2c);
75
76 for (i = 0; i < intersect->fft_size / 2 + 1; ++i) {
77 const float * const left = intersect->transformed[LEFT] [i],
78 * const right = intersect->transformed[RIGHT][i],
79 * const winner = (amplitude_squared(left) < amplitude_squared(right)) ? left : right;
80 memcpy(intersect->pre_output[i], winner, 2 * sizeof(float));
81 }
82
83 fftwf_execute(intersect->plan_c2r);
84
85 for (i = 0; i < intersect->fft_size; ++i) {
86 intersect->output_buffer[CENTER][i] += intersect->ifft_result[i];
87 }
88 for (i = 0; i < 2; ++i) {
89 memcpy(intersect->output_buffer[i], intersect->input_buffer[i], intersect->fft_jump_size * sizeof(float));
90 memmove(intersect->input_buffer[i], intersect->input_buffer[i] + intersect->fft_jump_size, (intersect->fft_size - intersect->fft_jump_size) * sizeof(float));
91 }
92
93 intersect->deviation = 0;
94 }
95
96 cursor_input[LEFT] += block_size;
97 cursor_input[RIGHT] += block_size;
98 cursor_output[LEFT] += block_size;
99 cursor_output[RIGHT] += block_size;
100 cursor_output[CENTER] += block_size;
101 sample_count -= block_size;
102 }
103
104 if (intersect->latency != NULL) {
105 *intersect->latency = intersect->fft_size;
106 }
107 }
108
intersect_run(LV2_Handle handle,uint32_t sample_count)109 void intersect_run(LV2_Handle handle, uint32_t sample_count) {
110 run(handle, sample_count, INTERSECT);
111 }
112
symmetric_difference_run(LV2_Handle handle,uint32_t sample_count)113 void symmetric_difference_run(LV2_Handle handle, uint32_t sample_count) {
114 run(handle, sample_count, SYMMETRIC_DIFFERENCE);
115 }
116
upmix_run(LV2_Handle handle,uint32_t sample_count)117 void upmix_run(LV2_Handle handle, uint32_t sample_count) {
118 run(handle, sample_count, UPMIX);
119 }
120