merge and resolve conflict with master
[ardour.git] / libs / ardour / pcm_utils.cc
1 /*
2     Copyright (C) 2006 Paul Davis , portions Erik de Castro Lopo
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 #ifdef COMPILER_MSVC
21 #include <ardourext/float_cast.h>
22 #endif
23 #include "ardour/pcm_utils.h"
24 #include <cmath>
25
26 using namespace std;
27
28 // TODO: check CPU_CLIPS_POSITIVE and CPU_CLIPS_NEGATIVE with scons
29 #define CPU_CLIPS_NEGATIVE 0
30 #define CPU_CLIPS_POSITIVE 0
31
32 /* these routines deal with 24 bit int handling (tribytes)
33  *   originally from libsndfile, but modified.  XXX - Copyright Erik de Castro Lopo
34  */
35
36 void
37 pcm_let2f_array (tribyte *src, int count, float *dest)
38 {
39         /* Special normfactor because tribyte value is read into an int. */
40         static const float normfact = 1.0 / ((float) 0x80000000);
41
42         unsigned char   *ucptr ;
43         int                             value ;
44
45         ucptr = ((unsigned char*) src) + 3 * count ;
46         while (--count >= 0)
47         {       ucptr -= 3 ;
48                 value = LET2H_INT_PTR (ucptr) ;
49                 dest [count] = ((float) value) * normfact ;
50                 } ;
51 } /* let2f_array */
52
53 void
54 pcm_bet2f_array (tribyte *src, int count, float *dest)
55 {
56         /* Special normfactor because tribyte value is read into an int. */
57         static const float normfact = 1.0 / ((float) 0x80000000);
58
59         unsigned char   *ucptr ;
60         int                             value ;
61
62
63         ucptr = ((unsigned char*) src) + 3 * count ;
64         while (--count >= 0)
65         {       ucptr -= 3 ;
66                 value = BET2H_INT_PTR (ucptr) ;
67                 dest [count] = ((float) value) * normfact ;
68                         } ;
69 } /* bet2f_array */
70
71 void
72 pcm_f2let_array (float *src, tribyte *dest, int count)
73 {
74         static const float normfact = (1.0 * 0x7FFFFF);
75
76         unsigned char   *ucptr ;
77         int                             value ;
78
79         ucptr = ((unsigned char*) dest) + 3 * count ;
80
81         while (count)
82         {       count -- ;
83                 ucptr -= 3 ;
84                 value = lrintf (src [count] * normfact) ;
85                 ucptr [0] = value ;
86                 ucptr [1] = value >> 8 ;
87                 ucptr [2] = value >> 16 ;
88                 } ;
89 } /* f2let_array */
90
91 void
92 pcm_f2let_clip_array (float *src, tribyte *dest, int count)
93 {
94         static const float normfact = (8.0 * 0x10000000);
95
96         unsigned char   *ucptr ;
97         float                   scaled_value ;
98         int                             value ;
99
100         ucptr = ((unsigned char*) dest) + 3 * count ;
101
102         while (count)
103         {       count -- ;
104                 ucptr -= 3 ;
105                 scaled_value = src [count] * normfact ;
106                 if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
107                 {       ucptr [0] = 0xFF ;
108                         ucptr [1] = 0xFF ;
109                         ucptr [2] = 0x7F ;
110                         continue ;
111                         } ;
112                 if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
113                 {       ucptr [0] = 0x00 ;
114                         ucptr [1] = 0x00 ;
115                         ucptr [2] = 0x80 ;
116                         continue ;
117                         } ;
118
119                 value = lrintf (scaled_value) ;
120                 ucptr [0] = value >> 8 ;
121                 ucptr [1] = value >> 16 ;
122                 ucptr [2] = value >> 24 ;
123                 } ;
124 } /* f2let_clip_array */
125
126 void
127 pcm_f2bet_array (const float *src, tribyte *dest, int count)
128 {
129         static const float normfact = (1.0 * 0x7FFFFF);
130
131         unsigned char   *ucptr ;
132         int                             value ;
133
134         ucptr = ((unsigned char*) dest) + 3 * count ;
135
136         while (--count >= 0)
137         {       ucptr -= 3 ;
138                 value = lrintf (src [count] * normfact) ;
139                 ucptr [0] = value >> 16 ;
140                 ucptr [1] = value >> 8 ;
141                 ucptr [2] = value ;
142                 } ;
143 } /* f2bet_array */
144
145 void
146 pcm_f2bet_clip_array (const float *src, tribyte *dest, int count)
147 {
148         static const float normfact = (8.0 * 0x10000000);
149
150         unsigned char   *ucptr ;
151         float                   scaled_value ;
152         int                             value ;
153
154         ucptr = ((unsigned char*) dest) + 3 * count ;
155
156         while (--count >= 0)
157         {       ucptr -= 3 ;
158                 scaled_value = src [count] * normfact ;
159                 if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
160                 {       ucptr [0] = 0x7F ;
161                         ucptr [1] = 0xFF ;
162                         ucptr [2] = 0xFF ;
163                         continue ;
164                         } ;
165                 if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
166                 {       ucptr [0] = 0x80 ;
167                         ucptr [1] = 0x00 ;
168                         ucptr [2] = 0x00 ;
169                         continue ;
170                 } ;
171
172                 value = lrint (scaled_value) ;
173                 ucptr [0] = value >> 24 ;
174                 ucptr [1] = value >> 16 ;
175                 ucptr [2] = value >> 8 ;
176                 } ;
177 } /* f2bet_clip_array */
178
179 //@@@@@@@