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