many fixes to audio file code, SMPTE offset now works correctly
[ardour.git] / libs / libsndfile / src / sfendian.h
1 /*
2 ** Copyright (C) 1999-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "sfconfig.h"
20
21 #if HAVE_STDINT_H
22 #include <stdint.h>
23 #elif HAVE_INTTYPES_H
24 #include <inttypes.h>
25 #endif
26
27 #if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
28 /* Good, we have int64_t. */
29 #elif (defined (SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
30 typedef long long int64_t ;
31 #elif (defined (SIZEOF_LONG) && (SIZEOF_LONG == 8))
32 typedef long int64_t ;
33 #elif (defined (WIN32) || defined (_WIN32))
34 typedef __int64 int64_t ;
35 #else
36 #error "No 64 bit integer type."
37 #endif
38
39 #if HAVE_BYTESWAP_H
40
41 #include <byteswap.h>
42
43 #define ENDSWAP_SHORT(x)        ((short) bswap_16 (x))
44 #define ENDSWAP_INT(x)          ((int) bswap_32 (x))
45
46 #else
47
48 #define ENDSWAP_SHORT(x)        ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
49 #define ENDSWAP_INT(x)          ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
50
51 #endif
52
53 /*
54 ** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a
55 ** marker indicating different sections of the file.
56 ** The following MAKE_MARKER macro allows th creation of integer constants
57 ** for these markers.
58 */
59
60 #if (CPU_IS_LITTLE_ENDIAN == 1)
61         #define MAKE_MARKER(a,b,c,d)    ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
62 #elif (CPU_IS_BIG_ENDIAN == 1)
63         #define MAKE_MARKER(a,b,c,d)    (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
64 #else
65         #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
66 #endif
67
68 /*
69 ** Macros to handle reading of data of a specific endian-ness into host endian
70 ** shorts and ints. The single input is an unsigned char* pointer to the start
71 ** of the object. There are two versions of each macro as we need to deal with
72 ** both big and little endian CPUs.
73 */
74
75 #if (CPU_IS_LITTLE_ENDIAN == 1)
76         #define LES2H_SHORT(x)                  (x)
77         #define LEI2H_INT(x)                    (x)
78
79         #define BES2H_SHORT(x)                  ENDSWAP_SHORT (x)
80         #define BEI2H_INT(x)                    ENDSWAP_INT (x)
81
82         #define H2BE_SHORT(x)                   ENDSWAP_SHORT (x)
83         #define H2BE_INT(x)                             ENDSWAP_INT (x)
84
85 #elif (CPU_IS_BIG_ENDIAN == 1)
86         #define LES2H_SHORT(x)                  ENDSWAP_SHORT (x)
87         #define LEI2H_INT(x)                    ENDSWAP_INT (x)
88
89         #define BES2H_SHORT(x)                  (x)
90         #define BEI2H_INT(x)                    (x)
91
92         #define H2LE_SHORT(x)                   ENDSWAP_SHORT (x)
93         #define H2LE_INT(x)                             ENDSWAP_INT (x)
94
95 #else
96         #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
97 #endif
98
99 #define LET2H_SHORT_PTR(x)              ((x) [1] + ((x) [2] << 8))
100 #define LET2H_INT_PTR(x)                (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
101
102 #define BET2H_SHORT_PTR(x)              (((x) [0] << 8) + (x) [1])
103 #define BET2H_INT_PTR(x)                (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
104
105 /*-----------------------------------------------------------------------------------------------
106 ** Generic functions for performing endian swapping on integer arrays.
107 */
108
109 static inline void
110 endswap_short_array (short *ptr, int len)
111 {       short   temp ;
112
113         while (--len >= 0)
114         {       temp = ptr [len] ;
115                 ptr [len] = ENDSWAP_SHORT (temp) ;
116                 } ;
117 } /* endswap_short_array */
118
119 static inline void
120 endswap_short_copy (short *dest, const short *src, int len)
121 {
122         while (--len >= 0)
123         {       dest [len] = ENDSWAP_SHORT (src [len]) ;
124                 } ;
125 } /* endswap_short_copy */
126
127 static inline void
128 endswap_int_array (int *ptr, int len)
129 {       int temp ;
130
131         while (--len >= 0)
132         {       temp = ptr [len] ;
133                 ptr [len] = ENDSWAP_INT (temp) ;
134                 } ;
135 } /* endswap_int_array */
136
137 static inline void
138 endswap_int_copy (int *dest, const int *src, int len)
139 {
140         while (--len >= 0)
141         {       dest [len] = ENDSWAP_INT (src [len]) ;
142                 } ;
143 } /* endswap_int_copy */
144
145 /*========================================================================================
146 */
147
148 #if     (HAVE_BYTESWAP_H && defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
149
150 static inline void
151 endswap_int64_t_array (int64_t *ptr, int len)
152 {       int64_t value ;
153
154         while (--len >= 0)
155         {       value = ptr [len] ;
156                 ptr [len] = bswap_64 (value) ;
157                 } ;
158 } /* endswap_int64_t_array */
159
160 static inline void
161 endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
162 {       int64_t value ;
163
164         while (--len >= 0)
165         {       value = src [len] ;
166                 dest [len] = bswap_64 (value) ;
167                 } ;
168 } /* endswap_int64_t_copy */
169
170 #else
171
172 static inline void
173 endswap_int64_t_array (int64_t *ptr, int len)
174 {       unsigned char *ucptr, temp ;
175
176         ucptr = (unsigned char *) ptr ;
177         ucptr += 8 * len ;
178         while (--len >= 0)
179         {       ucptr -= 8 ;
180
181                 temp = ucptr [0] ;
182                 ucptr [0] = ucptr [7] ;
183                 ucptr [7] = temp ;
184
185                 temp = ucptr [1] ;
186                 ucptr [1] = ucptr [6] ;
187                 ucptr [6] = temp ;
188
189                 temp = ucptr [2] ;
190                 ucptr [2] = ucptr [5] ;
191                 ucptr [5] = temp ;
192
193                 temp = ucptr [3] ;
194                 ucptr [3] = ucptr [4] ;
195                 ucptr [4] = temp ;
196                 } ;
197 } /* endswap_int64_t_array */
198
199 static inline void
200 endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
201 {       const unsigned char *psrc ;
202         unsigned char *pdest ;
203
204         if (dest == src)
205         {       endswap_int64_t_array (dest, len) ;
206                 return ;
207                 } ;
208
209         psrc = ((const unsigned char *) src) + 8 * len ;
210         pdest = ((unsigned char *) dest) + 8 * len ;
211         while (--len >= 0)
212         {       psrc -= 8 ;
213                 pdest -= 8 ;
214
215                 pdest [0] = psrc [7] ;
216                 pdest [2] = psrc [5] ;
217                 pdest [4] = psrc [3] ;
218                 pdest [6] = psrc [1] ;
219                 pdest [7] = psrc [0] ;
220                 pdest [1] = psrc [6] ;
221                 pdest [3] = psrc [4] ;
222                 pdest [5] = psrc [2] ;
223                 } ;
224 } /* endswap_int64_t_copy */
225
226 #endif
227
228 /* A couple of wrapper functions. */
229
230 static inline void
231 endswap_float_array (float *ptr, int len)
232 {       endswap_int_array ((void *) ptr, len) ;
233 } /* endswap_float_array */
234
235 static inline void
236 endswap_double_array (double *ptr, int len)
237 {       endswap_int64_t_array ((void *) ptr, len) ;
238 } /* endswap_double_array */
239
240 static inline void
241 endswap_float_copy (float *dest, const float *src, int len)
242 {       endswap_int_copy ((int *) dest, (const int *) src, len) ;
243 } /* endswap_float_copy */
244
245 static inline void
246 endswap_double_copy (double *dest, const double *src, int len)
247 {       endswap_int64_t_copy ((int64_t *) dest, (const int64_t *) src, len) ;
248 } /* endswap_double_copy */
249
250 /*
251 ** Do not edit or modify anything in this comment block.
252 ** The arch-tag line is a file identity tag for the GNU Arch
253 ** revision control system.
254 **
255 ** arch-tag: f0c5cd54-42d3-4237-90ec-11fe24995de7
256 */