Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1905 serge 1
/*
2
	sample.h: The conversion from internal data to output samples of differing formats.
3
 
4
	copyright 2007-9 by the mpg123 project - free software under the terms of the LGPL 2.1
5
	see COPYING and AUTHORS files in distribution or http://mpg123.org
6
	initially written by Thomas Orgis, taking WRITE_SAMPLE from decode.c
7
	Later added the end-conversion specific macros here, too.
8
*/
9
 
10
#ifndef SAMPLE_H
11
#define SAMPLE_H
12
 
13
/* mpg123lib_intern.h is included already, right? */
14
 
15
/* Special case is fixed point math... which does work, but not that nice yet.  */
16
#ifdef REAL_IS_FIXED
17
static inline short idiv_signed_rounded(long x, int shift)
18
{
19
	x >>= (shift - 1);
20
	x += (x & 1);
21
	return (short)(x >> 1);
22
}
23
#  define REAL_PLUS_32767       ( 32767 << 15 )
24
#  define REAL_MINUS_32768      ( -32768 << 15 )
25
#  define REAL_TO_SHORT(x)      (idiv_signed_rounded(x, 15))
26
/* No better code (yet).  */
27
#  define REAL_TO_SHORT_ACCURATE(x) REAL_TO_SHORT(x)
28
/* This is just here for completeness, it is not used! */
29
# define REAL_TO_S32(x)        (x)
30
#endif
31
 
32
/* From now on for single precision float... double precision is a possible option once we added some bits. But, it would be rather insane. */
33
#ifndef REAL_TO_SHORT
34
 
35
/* Define the accurate rounding function. */
36
# if (defined REAL_IS_FLOAT) && (defined IEEE_FLOAT)
37
/* This function is only available for IEEE754 single-precision values
38
   This is nearly identical to proper rounding, just -+0.5 is rounded to 0 */
39
static inline short ftoi16(float x)
40
{
41
	union
42
	{
43
		float f;
44
		int32_t i;
45
	} u_fi;
46
	u_fi.f = x + 12582912.0f; /* Magic Number: 2^23 + 2^22 */
47
	return (short)u_fi.i;
48
}
49
#  define REAL_TO_SHORT_ACCURATE(x)      ftoi16(x)
50
# else
51
/* The "proper" rounding, plain C, a bit slow. */
52
#  define REAL_TO_SHORT_ACCURATE(x)      (short)((x)>0.0?(x)+0.5:(x)-0.5)
53
# endif
54
 
55
/* Now define the normal rounding. */
56
# ifdef ACCURATE_ROUNDING
57
#  define REAL_TO_SHORT(x)      REAL_TO_SHORT_ACCURATE(x)
58
# else
59
/* Non-accurate rounding... simple truncation. Fastest, most LSB errors. */
60
#  define REAL_TO_SHORT(x)      (short)(x)
61
# endif
62
 
63
#endif /* REAL_TO_SHORT */
64
 
65
/* We should add dithering for S32, too? */
66
#ifndef REAL_TO_S32
67
# ifdef ACCURATE_ROUNDING
68
#  define REAL_TO_S32(x) (int32_t)((x)>0.0?(x)+0.5:(x)-0.5)
69
# else
70
#  define REAL_TO_S32(x) (int32_t)(x)
71
# endif
72
#endif
73
 
74
#ifndef REAL_PLUS_32767
75
# define REAL_PLUS_32767 32767.0
76
#endif
77
#ifndef REAL_MINUS_32768
78
# define REAL_MINUS_32768 -32768.0
79
#endif
80
#ifndef REAL_PLUS_S32
81
# define REAL_PLUS_S32 2147483647.0
82
#endif
83
#ifndef REAL_MINUS_S32
84
# define REAL_MINUS_S32 -2147483648.0
85
#endif
86
 
87
 
88
/* The actual storage of a decoded sample is separated in the following macros.
89
   We can handle different types, we could also handle dithering here. */
90
 
91
/* Macro to produce a short (signed 16bit) output sample from internal representation,
92
   which may be float, double or indeed some integer for fixed point handling. */
93
#define WRITE_SHORT_SAMPLE(samples,sum,clip) \
94
  if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \
95
  else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \
96
  else { *(samples) = REAL_TO_SHORT(sum); }
97
 
98
/* Same as above, but always using accurate rounding. Would we want softer clipping here, too? */
99
#define WRITE_SHORT_SAMPLE_ACCURATE(samples,sum,clip) \
100
  if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \
101
  else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \
102
  else { *(samples) = REAL_TO_SHORT_ACCURATE(sum); }
103
 
104
/*
105
	32bit signed
106
	We do clipping with the same old borders... but different conversion.
107
	We see here that we need extra work for non-16bit output... we optimized for 16bit.
108
	-0x7fffffff-1 is the minimum 32 bit signed integer value expressed so that MSVC
109
	does not give a compile time warning.
110
*/
111
#define WRITE_S32_SAMPLE(samples,sum,clip) \
112
	{ \
113
		real tmpsum = REAL_MUL((sum),S32_RESCALE); \
114
		if( tmpsum > REAL_PLUS_S32 ){ *(samples) = 0x7fffffff; (clip)++; } \
115
		else if( tmpsum < REAL_MINUS_S32 ) { *(samples) = -0x7fffffff-1; (clip)++; } \
116
		else { *(samples) = REAL_TO_S32(tmpsum); } \
117
	}
118
 
119
/* Produce an 8bit sample, via 16bit intermediate. */
120
#define WRITE_8BIT_SAMPLE(samples,sum,clip) \
121
{ \
122
	short write_8bit_tmp; \
123
	if( (sum) > REAL_PLUS_32767) { write_8bit_tmp = 0x7fff; (clip)++; } \
124
	else if( (sum) < REAL_MINUS_32768) { write_8bit_tmp = -0x8000; (clip)++; } \
125
	else { write_8bit_tmp = REAL_TO_SHORT(sum); } \
126
	*(samples) = fr->conv16to8[write_8bit_tmp>>AUSHIFT]; \
127
}
128
#ifndef REAL_IS_FIXED
129
#define WRITE_REAL_SAMPLE(samples,sum,clip) *(samples) = ((real)1./SHORT_SCALE)*(sum)
130
#endif
131
 
132
#endif