2 ** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
19 #ifndef SFENDIAN_INCLUDED
20 #define SFENDIAN_INCLUDED
30 #if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
31 /* Good, we have int64_t. */
32 #elif (defined (SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
33 typedef long long int64_t ;
34 #elif (defined (SIZEOF_LONG) && (SIZEOF_LONG == 8))
35 typedef long int64_t ;
36 #elif (defined (WIN32) || defined (_WIN32))
37 typedef __int64
int64_t ;
39 #error "No 64 bit integer type."
46 #define ENDSWAP_SHORT(x) ((short) bswap_16 (x))
47 #define ENDSWAP_INT(x) ((int) bswap_32 (x))
51 #define ENDSWAP_SHORT(x) ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
52 #define ENDSWAP_INT(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
57 ** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a
58 ** marker indicating different sections of the file.
59 ** The following MAKE_MARKER macro allows th creation of integer constants
63 #if (CPU_IS_LITTLE_ENDIAN == 1)
64 #define MAKE_MARKER(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
65 #elif (CPU_IS_BIG_ENDIAN == 1)
66 #define MAKE_MARKER(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
68 #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
72 ** Macros to handle reading of data of a specific endian-ness into host endian
73 ** shorts and ints. The single input is an unsigned char* pointer to the start
74 ** of the object. There are two versions of each macro as we need to deal with
75 ** both big and little endian CPUs.
78 #if (CPU_IS_LITTLE_ENDIAN == 1)
79 #define LES2H_SHORT(x) (x)
80 #define LEI2H_INT(x) (x)
82 #define BES2H_SHORT(x) ENDSWAP_SHORT (x)
83 #define BEI2H_INT(x) ENDSWAP_INT (x)
85 #define H2BE_SHORT(x) ENDSWAP_SHORT (x)
86 #define H2BE_INT(x) ENDSWAP_INT (x)
88 #elif (CPU_IS_BIG_ENDIAN == 1)
89 #define LES2H_SHORT(x) ENDSWAP_SHORT (x)
90 #define LEI2H_INT(x) ENDSWAP_INT (x)
92 #define BES2H_SHORT(x) (x)
93 #define BEI2H_INT(x) (x)
95 #define H2LE_SHORT(x) ENDSWAP_SHORT (x)
96 #define H2LE_INT(x) ENDSWAP_INT (x)
99 #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
102 #define LET2H_SHORT_PTR(x) ((x) [1] + ((x) [2] << 8))
103 #define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
105 #define BET2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1])
106 #define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
108 /*-----------------------------------------------------------------------------------------------
109 ** Generic functions for performing endian swapping on integer arrays.
113 endswap_short_array (short *ptr
, int len
)
118 ptr
[len
] = ENDSWAP_SHORT (temp
) ;
120 } /* endswap_short_array */
123 endswap_short_copy (short *dest
, const short *src
, int len
)
126 { dest
[len
] = ENDSWAP_SHORT (src
[len
]) ;
128 } /* endswap_short_copy */
131 endswap_int_array (int *ptr
, int len
)
136 ptr
[len
] = ENDSWAP_INT (temp
) ;
138 } /* endswap_int_array */
141 endswap_int_copy (int *dest
, const int *src
, int len
)
144 { dest
[len
] = ENDSWAP_INT (src
[len
]) ;
146 } /* endswap_int_copy */
148 /*========================================================================================
151 #if (HAVE_BYTESWAP_H && defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
154 endswap_int64_t_array (int64_t *ptr
, int len
)
158 { value
= ptr
[len
] ;
159 ptr
[len
] = bswap_64 (value
) ;
161 } /* endswap_int64_t_array */
164 endswap_int64_t_copy (int64_t *dest
, const int64_t *src
, int len
)
168 { value
= src
[len
] ;
169 dest
[len
] = bswap_64 (value
) ;
171 } /* endswap_int64_t_copy */
176 endswap_int64_t_array (int64_t *ptr
, int len
)
177 { unsigned char *ucptr
, temp
;
179 ucptr
= (unsigned char *) ptr
;
185 ucptr
[0] = ucptr
[7] ;
189 ucptr
[1] = ucptr
[6] ;
193 ucptr
[2] = ucptr
[5] ;
197 ucptr
[3] = ucptr
[4] ;
200 } /* endswap_int64_t_array */
203 endswap_int64_t_copy (int64_t *dest
, const int64_t *src
, int len
)
204 { const unsigned char *psrc
;
205 unsigned char *pdest
;
208 { endswap_int64_t_array (dest
, len
) ;
212 psrc
= ((const unsigned char *) src
) + 8 * len
;
213 pdest
= ((unsigned char *) dest
) + 8 * len
;
218 pdest
[0] = psrc
[7] ;
219 pdest
[2] = psrc
[5] ;
220 pdest
[4] = psrc
[3] ;
221 pdest
[6] = psrc
[1] ;
222 pdest
[7] = psrc
[0] ;
223 pdest
[1] = psrc
[6] ;
224 pdest
[3] = psrc
[4] ;
225 pdest
[5] = psrc
[2] ;
227 } /* endswap_int64_t_copy */
231 /* A couple of wrapper functions. */
234 endswap_float_array (float *ptr
, int len
)
235 { endswap_int_array ((void *) ptr
, len
) ;
236 } /* endswap_float_array */
239 endswap_double_array (double *ptr
, int len
)
240 { endswap_int64_t_array ((void *) ptr
, len
) ;
241 } /* endswap_double_array */
244 endswap_float_copy (float *dest
, const float *src
, int len
)
245 { endswap_int_copy ((int *) dest
, (const int *) src
, len
) ;
246 } /* endswap_float_copy */
249 endswap_double_copy (double *dest
, const double *src
, int len
)
250 { endswap_int64_t_copy ((int64_t *) dest
, (const int64_t *) src
, len
) ;
251 } /* endswap_double_copy */
253 #endif /* SFENDIAN_INCLUDED */