Path: blob/master/libs/mpg123/src/libmpg123/dither_impl.h
4394 views
/*1dither: Generate shaped noise for dithering23copyright 2009 by the mpg123 project - free software under the terms of the LGPL 2.14see COPYING and AUTHORS files in distribution or http://mpg123.org5initially written by Taihei Monma6*/78#include "config.h"9#include "../compat/compat.h"10#include "dither.h"1112static const uint32_t init_seed = 2463534242UL;1314#define LAP 1001516/*17xorshift random number generator, with output scaling to [-0.5, 0.5]18This is the white noise...19See http://www.jstatsoft.org/v08/i14/paper on XOR shift random number generators.20*/21static float rand_xorshift32(uint32_t *seed)22{23union24{25uint32_t i;26float f;27} fi;2829fi.i = *seed;30fi.i ^= (fi.i<<13);31fi.i ^= (fi.i>>17);32fi.i ^= (fi.i<<5);33*seed = fi.i;3435/* scale the number to [-0.5, 0.5] */36#ifdef IEEE_FLOAT37fi.i = (fi.i>>9)|0x3f800000;38fi.f -= 1.5f;39#else40fi.f = (double)fi.i / 4294967295.0;41fi.f -= 0.5f;42#endif43return fi.f;44}4546static void white_noise(float *table, size_t count)47{48size_t i;49uint32_t seed = init_seed;5051for(i=0; i<count; ++i)52table[i] = rand_xorshift32(&seed);53}5455static void tpdf_noise(float *table, size_t count)56{57size_t i;58uint32_t seed = init_seed;5960for(i=0; i<count; ++i)61table[i] = rand_xorshift32(&seed) + rand_xorshift32(&seed);62}6364static void highpass_tpdf_noise(float *table, size_t count)65{66size_t i;67uint32_t seed = init_seed;68/* Ensure some minimum lap for keeping the high-pass filter circular. */69size_t lap = count > 2*LAP ? LAP : count/2;7071float input_noise;72float xv[9], yv[9];7374for(i=0;i<9;i++)75{76xv[i] = yv[i] = 0.0f;77}7879for(i=0;i<count+lap;i++)80{81if(i==count) seed=init_seed;8283/* generate and add 2 random numbers, to make a TPDF noise distribution */84input_noise = rand_xorshift32(&seed) + rand_xorshift32(&seed);8586/* apply 8th order Chebyshev high-pass IIR filter */87/* Coefficients are from http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html88Given parameters are: Chebyshev, Highpass, ripple=-1, order=8, samplerate=44100, corner1=19000 */89xv[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];90xv[8] = input_noise / 1.382814179e+07;91yv[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];92yv[8] = (xv[0] + xv[8]) - 8 * (xv[1] + xv[7]) + 28 * (xv[2] + xv[6])93- 56 * (xv[3] + xv[5]) + 70 * xv[4]94+ ( -0.6706204984 * yv[0]) + ( -5.3720827038 * yv[1])95+ (-19.0865382480 * yv[2]) + (-39.2831607860 * yv[3])96+ (-51.2308985070 * yv[4]) + (-43.3590135780 * yv[5])97+ (-23.2632305320 * yv[6]) + ( -7.2370122050 * yv[7]);98if(i>=lap) table[i-lap] = yv[8] * 3.0f;99}100}101102void mpg123_noise(float* table, size_t count, enum mpg123_noise_type noisetype)103{104switch(noisetype)105{106case mpg123_white_noise: white_noise(table, count); break;107case mpg123_tpdf_noise: tpdf_noise(table, count); break;108case mpg123_highpass_tpdf_noise:109highpass_tpdf_noise(table, count);110break;111}112}113114/* Generate white noise and shape it with a high pass filter. */115void INT123_dither_table_init(float *dithertable)116{117highpass_tpdf_noise(dithertable, DITHERSIZE);118}119120121