fix merge with master
[ardour.git] / libs / ardour / mix.cc
1 /*
2     Copyright (C) 2000-2005 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cmath>
21 #include "ardour/types.h"
22 #include "ardour/utils.h"
23 #include "ardour/mix.h"
24 #include "ardour/runtime_functions.h"
25 #include <stdint.h>
26
27 using namespace ARDOUR;
28
29 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
30 // Debug wrappers
31
32 float
33 debug_compute_peak (ARDOUR::Sample *buf, pframes_t nsamples, float current)
34 {
35         if ( ((intptr_t)buf % 16) != 0) {
36                 std::cerr << "compute_peak(): buffer unaligned!" << std::endl;
37         }
38
39         return x86_sse_compute_peak(buf, nsamples, current);
40 }
41
42 void
43 debug_apply_gain_to_buffer (ARDOUR::Sample *buf, pframes_t nframes, float gain)
44 {
45         if ( ((intptr_t)buf % 16) != 0) {
46                 std::cerr << "apply_gain_to_buffer(): buffer unaligned!" << std::endl;
47         }
48
49         x86_sse_apply_gain_to_buffer(buf, nframes, gain);
50 }
51
52 void
53 debug_mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, pframes_t nframes, float gain)
54 {
55         if ( ((intptr_t)dst & 15) != 0) {
56                 std::cerr << "mix_buffers_with_gain(): dst unaligned!" << std::endl;
57         }
58
59         if ( ((intptr_t)dst & 15) != ((intptr_t)src & 15) ) {
60                 std::cerr << "mix_buffers_with_gain(): dst & src don't have the same alignment!" << std::endl;
61                 mix_buffers_with_gain(dst, src, nframes, gain);
62         } else {
63                 x86_sse_mix_buffers_with_gain(dst, src, nframes, gain);
64         }
65 }
66
67 void
68 debug_mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, pframes_t nframes)
69 {
70         if ( ((intptr_t)dst & 15) != 0) {
71                 std::cerr << "mix_buffers_no_gain(): dst unaligned!" << std::endl;
72         }
73
74         if ( ((intptr_t)dst & 15) != ((intptr_t)src & 15) ) {
75                 std::cerr << "mix_buffers_no_gain(): dst & src don't have the same alignment!" << std::endl;
76                 mix_buffers_no_gain(dst, src, nframes);
77         } else {
78                 x86_sse_mix_buffers_no_gain(dst, src, nframes);
79         }
80 }
81
82 #endif
83
84
85 float
86 default_compute_peak (const ARDOUR::Sample * buf, pframes_t nsamples, float current)
87 {
88         for (pframes_t i = 0; i < nsamples; ++i) {
89                 current = f_max (current, fabsf (buf[i]));
90         }
91
92         return current;
93 }
94
95 void
96 default_find_peaks (const ARDOUR::Sample * buf, pframes_t nframes, float *min, float *max)
97 {
98         pframes_t i;
99         float a, b;
100
101         a = *max;
102         b = *min;
103
104         for (i = 0; i < nframes; i++)
105         {
106                 a = fmax (buf[i], a);
107                 b = fmin (buf[i], b);
108         }
109
110         *max = a;
111         *min = b;
112 }
113
114 void
115 default_apply_gain_to_buffer (ARDOUR::Sample * buf, pframes_t nframes, float gain)
116 {
117         for (pframes_t i=0; i<nframes; i++)
118                 buf[i] *= gain;
119 }
120
121 void
122 default_mix_buffers_with_gain (ARDOUR::Sample * dst, const ARDOUR::Sample * src, pframes_t nframes, float gain)
123 {
124         for (pframes_t i = 0; i < nframes; i++) {
125                 dst[i] += src[i] * gain;
126         }
127 }
128
129 void
130 default_mix_buffers_no_gain (ARDOUR::Sample * dst, const ARDOUR::Sample * src, pframes_t nframes)
131 {
132         for (pframes_t i=0; i < nframes; i++) {
133                 dst[i] += src[i];
134         }
135 }
136
137 #if defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
138 #include <Accelerate/Accelerate.h>
139
140 float
141 veclib_compute_peak (const ARDOUR::Sample * buf, pframes_t nsamples, float current)
142 {
143         float tmpmax = 0.0f;
144         vDSP_maxmgv(buf, 1, &tmpmax, nsamples);
145         return f_max(current, tmpmax);
146 }
147
148 void
149 veclib_find_peaks (const ARDOUR::Sample * buf, pframes_t nframes, float *min, float *max)
150 {
151         vDSP_maxv (const_cast<ARDOUR::Sample*>(buf), 1, max, nframes);
152         vDSP_minv (const_cast<ARDOUR::Sample*>(buf), 1, min, nframes);
153 }
154
155 void
156 veclib_apply_gain_to_buffer (ARDOUR::Sample * buf, pframes_t nframes, float gain)
157 {
158         vDSP_vsmul(buf, 1, &gain, buf, 1, nframes);
159 }
160
161 void
162 veclib_mix_buffers_with_gain (ARDOUR::Sample * dst, const ARDOUR::Sample * src, pframes_t nframes, float gain)
163 {
164         vDSP_vsma(src, 1, &gain, dst, 1, dst, 1, nframes);
165 }
166
167 void
168 veclib_mix_buffers_no_gain (ARDOUR::Sample * dst, const ARDOUR::Sample * src, pframes_t nframes)
169 {
170         // It seems that a vector mult only operation does not exist...
171         float gain = 1.0f;
172         vDSP_vsma(src, 1, &gain, dst, 1, dst, 1, nframes);
173 }
174
175 #endif
176
177