/src/mpg123/src/libmpg123/dither_impl.h
Line | Count | Source |
1 | | /* |
2 | | dither: Generate shaped noise for dithering |
3 | | |
4 | | copyright 2009 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 Taihei Monma |
7 | | */ |
8 | | |
9 | | #include "config.h" |
10 | | #include "../compat/compat.h" |
11 | | #include "dither.h" |
12 | | |
13 | | static const uint32_t init_seed = 2463534242UL; |
14 | | |
15 | 0 | #define LAP 100 |
16 | | |
17 | | /* |
18 | | xorshift random number generator, with output scaling to [-0.5, 0.5] |
19 | | This is the white noise... |
20 | | See http://www.jstatsoft.org/v08/i14/paper on XOR shift random number generators. |
21 | | */ |
22 | | static float rand_xorshift32(uint32_t *seed) |
23 | 0 | { |
24 | 0 | union |
25 | 0 | { |
26 | 0 | uint32_t i; |
27 | 0 | float f; |
28 | 0 | } fi; |
29 | | |
30 | 0 | fi.i = *seed; |
31 | 0 | fi.i ^= (fi.i<<13); |
32 | 0 | fi.i ^= (fi.i>>17); |
33 | 0 | fi.i ^= (fi.i<<5); |
34 | 0 | *seed = fi.i; |
35 | | |
36 | | /* scale the number to [-0.5, 0.5] */ |
37 | 0 | #ifdef IEEE_FLOAT |
38 | 0 | fi.i = (fi.i>>9)|0x3f800000; |
39 | 0 | fi.f -= 1.5f; |
40 | | #else |
41 | | fi.f = (double)fi.i / 4294967295.0; |
42 | | fi.f -= 0.5f; |
43 | | #endif |
44 | 0 | return fi.f; |
45 | 0 | } |
46 | | |
47 | | static void white_noise(float *table, size_t count) |
48 | 0 | { |
49 | 0 | size_t i; |
50 | 0 | uint32_t seed = init_seed; |
51 | | |
52 | 0 | for(i=0; i<count; ++i) |
53 | 0 | table[i] = rand_xorshift32(&seed); |
54 | 0 | } |
55 | | |
56 | | static void tpdf_noise(float *table, size_t count) |
57 | 0 | { |
58 | 0 | size_t i; |
59 | 0 | uint32_t seed = init_seed; |
60 | | |
61 | 0 | for(i=0; i<count; ++i) |
62 | 0 | table[i] = rand_xorshift32(&seed) + rand_xorshift32(&seed); |
63 | 0 | } |
64 | | |
65 | | static void highpass_tpdf_noise(float *table, size_t count) |
66 | 0 | { |
67 | 0 | size_t i; |
68 | 0 | uint32_t seed = init_seed; |
69 | | /* Ensure some minimum lap for keeping the high-pass filter circular. */ |
70 | 0 | size_t lap = count > 2*LAP ? LAP : count/2; |
71 | |
|
72 | 0 | float input_noise; |
73 | 0 | float xv[9], yv[9]; |
74 | |
|
75 | 0 | for(i=0;i<9;i++) |
76 | 0 | { |
77 | 0 | xv[i] = yv[i] = 0.0f; |
78 | 0 | } |
79 | |
|
80 | 0 | for(i=0;i<count+lap;i++) |
81 | 0 | { |
82 | 0 | if(i==count) seed=init_seed; |
83 | | |
84 | | /* generate and add 2 random numbers, to make a TPDF noise distribution */ |
85 | 0 | input_noise = rand_xorshift32(&seed) + rand_xorshift32(&seed); |
86 | | |
87 | | /* apply 8th order Chebyshev high-pass IIR filter */ |
88 | | /* Coefficients are from http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html |
89 | | Given parameters are: Chebyshev, Highpass, ripple=-1, order=8, samplerate=44100, corner1=19000 */ |
90 | 0 | xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; xv[6] = xv[7]; xv[7] = xv[8]; |
91 | 0 | xv[8] = input_noise / 1.382814179e+07; |
92 | 0 | yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; yv[6] = yv[7]; yv[7] = yv[8]; |
93 | 0 | yv[8] = (xv[0] + xv[8]) - 8 * (xv[1] + xv[7]) + 28 * (xv[2] + xv[6]) |
94 | 0 | - 56 * (xv[3] + xv[5]) + 70 * xv[4] |
95 | 0 | + ( -0.6706204984 * yv[0]) + ( -5.3720827038 * yv[1]) |
96 | 0 | + (-19.0865382480 * yv[2]) + (-39.2831607860 * yv[3]) |
97 | 0 | + (-51.2308985070 * yv[4]) + (-43.3590135780 * yv[5]) |
98 | 0 | + (-23.2632305320 * yv[6]) + ( -7.2370122050 * yv[7]); |
99 | 0 | if(i>=lap) table[i-lap] = yv[8] * 3.0f; |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | void mpg123_noise(float* table, size_t count, enum mpg123_noise_type noisetype) |
104 | 0 | { |
105 | 0 | switch(noisetype) |
106 | 0 | { |
107 | 0 | case mpg123_white_noise: white_noise(table, count); break; |
108 | 0 | case mpg123_tpdf_noise: tpdf_noise(table, count); break; |
109 | 0 | case mpg123_highpass_tpdf_noise: |
110 | 0 | highpass_tpdf_noise(table, count); |
111 | 0 | break; |
112 | 0 | } |
113 | 0 | } |
114 | | |
115 | | /* Generate white noise and shape it with a high pass filter. */ |
116 | | void INT123_dither_table_init(float *dithertable) |
117 | 0 | { |
118 | 0 | highpass_tpdf_noise(dithertable, DITHERSIZE); |
119 | 0 | } |