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