And simplify code. Given the nature of noise we do not have to match noise energy exactly. Matching the expected energy seems to be good enough, and have much cleaner code. Now we do not need FP division and square root.
Unified · Split
| @@ -148,8 +148,9 @@ NeAACDecHandle NeAACDecOpen(void) · 147 unmodified lines | ||
| 148 | 148 | hDecoder->frame = 0; |
| 149 | 149 | hDecoder->sample_buffer = NULL; |
| 150 | 150 | |
| 151 | − hDecoder->__r1 = 1; | |
| 152 | − hDecoder->__r2 = 1; | |
| 151 | + // Same as (1, 1) after 1024 iterations; otherwise first values does not look random at all. | |
| 152 | + hDecoder->__r1 = 0x2bb431ea; | |
| 153 | + hDecoder->__r2 = 0x206155b7; | |
| 153 | 154 | |
| 154 | 155 | for (i = 0; i < MAX_CHANNELS; i++) |
| 155 | 156 | { |
| @@ -42,36 +42,6 @@ static void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t size, · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | #ifdef FIXED_POINT |
| 44 | 44 | |
| 45 | −#define DIV(A, B) (((int64_t)A << REAL_BITS)/B) | |
| 46 | − | |
| 47 | −#define step(shift) \ | |
| 48 | − if ((0x40000000l >> shift) + root <= value) \ | |
| 49 | − { \ | |
| 50 | − value -= (0x40000000l >> shift) + root; \ | |
| 51 | − root = (root >> 1) | (0x40000000l >> shift); \ | |
| 52 | − } else { \ | |
| 53 | − root = root >> 1; \ | |
| 54 | − } | |
| 55 | − | |
| 56 | −/* fixed point square root approximation */ | |
| 57 | −/* !!!! ONLY WORKS FOR EVEN %REAL_BITS% !!!! */ | |
| 58 | −real_t fp_sqrt(real_t value) | |
| 59 | −{ | |
| 60 | − real_t root = 0; | |
| 61 | − | |
| 62 | − step( 0); step( 2); step( 4); step( 6); | |
| 63 | − step( 8); step(10); step(12); step(14); | |
| 64 | − step(16); step(18); step(20); step(22); | |
| 65 | − step(24); step(26); step(28); step(30); | |
| 66 | − | |
| 67 | − if (root < value) | |
| 68 | − ++root; | |
| 69 | − | |
| 70 | − root <<= (REAL_BITS/2); | |
| 71 | − | |
| 72 | − return root; | |
| 73 | −} | |
| 74 | − | |
| 75 | 45 | static real_t const pow2_table[] = |
| 76 | 46 | { |
| 77 | 47 | COEF_CONST(1.0), |
| @@ -79,6 +49,27 @@ static real_t const pow2_table[] = · 1 unmodified line | ||
| 79 | 49 | COEF_CONST(1.41421356237310), |
| 80 | 50 | COEF_CONST(1.68179283050743) |
| 81 | 51 | }; |
| 52 | + | |
| 53 | +// mean_energy_table[x] == sqrt(3 / x) | |
| 54 | +static real_t const mean_energy_table[] = | |
| 55 | +{ | |
| 56 | + COEF_CONST(0.0), // should not happen | |
| 57 | + COEF_CONST(1.7320508075688772), | |
| 58 | + COEF_CONST(1.224744871391589), | |
| 59 | + COEF_CONST(1.0), // sqrt(3/3) | |
| 60 | + COEF_CONST(0.8660254037844386), | |
| 61 | + COEF_CONST(0.7745966692414834), | |
| 62 | + COEF_CONST(0.7071067811865476), | |
| 63 | + COEF_CONST(0.6546536707079771), | |
| 64 | + COEF_CONST(0.6123724356957945), | |
| 65 | + COEF_CONST(0.5773502691896257), | |
| 66 | + COEF_CONST(0.5477225575051661), | |
| 67 | + COEF_CONST(0.5222329678670935), | |
| 68 | + COEF_CONST(0.5), // sqrt(3/12) | |
| 69 | + COEF_CONST(0.4803844614152614), | |
| 70 | + COEF_CONST(0.4629100498862757), | |
| 71 | + COEF_CONST(0.4472135954999579), | |
| 72 | +}; | |
| 82 | 73 | #endif |
| 83 | 74 | |
| 84 | 75 | /* The function gen_rand_vector(addr, size) generates a vector of length |
| @@ -114,49 +105,43 @@ static INLINE void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t · 29 unmodified lines | ||
| 114 | 105 | } |
| 115 | 106 | #else |
| 116 | 107 | uint16_t i; |
| 117 | − real_t energy = 0, scale; | |
| 108 | + real_t scale; | |
| 118 | 109 | int32_t exp, frac; |
| 110 | + int32_t idx, mask; | |
| 119 | 111 | |
| 120 | 112 | /* IMDCT pre-scaling */ |
| 121 | 113 | scale_factor -= 4 * sub; |
| 122 | 114 | |
| 123 | − scale_factor = min(max(scale_factor, -60), 60); | |
| 115 | + // 52 stands for 2**13 == 8192 factor; larger factor causes overflows later (in cfft). | |
| 116 | + scale_factor = min(max(scale_factor, -(REAL_BITS * 4)), 52); | |
| 124 | 117 | |
| 125 | 118 | exp = scale_factor >> 2; |
| 126 | 119 | frac = scale_factor & 3; |
| 127 | 120 | |
| 128 | − for (i = 0; i < size; i++) | |
| 129 | − { | |
| 130 | − /* this can be replaced by a 16 bit random generator!!!! */ | |
| 131 | − real_t tmp = (int32_t)ne_rng(__r1, __r2); | |
| 132 | − if (tmp < 0) | |
| 133 | − tmp = -(tmp & ((1<<(REAL_BITS-1))-1)); | |
| 134 | − else | |
| 135 | − tmp = (tmp & ((1<<(REAL_BITS-1))-1)); | |
| 136 | − | |
| 137 | − energy += MUL_R(tmp,tmp); | |
| 121 | + /* 29 <= REAL_BITS + exp <= 0 */ | |
| 122 | + mask = (1 << (REAL_BITS + exp)) - 1; | |
| 138 | 123 | |
| 139 | − spec[i] = tmp; | |
| 124 | + idx = size; | |
| 125 | + scale = COEF_CONST(1); | |
| 126 | + // At most 2 iterations. | |
| 127 | + while (idx >= 16) | |
| 128 | + { | |
| 129 | + idx >>= 2; | |
| 130 | + scale >>= 1; | |
| 140 | 131 | } |
| 141 | − /* energy ~= size / 3 */ | |
| 132 | + scale = MUL_C(scale, mean_energy_table[idx]); | |
| 133 | + if (frac) | |
| 134 | + scale = MUL_C(scale, pow2_table[frac]); | |
| 135 | + // scale is less than 4.0 now. | |
| 142 | 136 | |
| 143 | − energy = fp_sqrt(energy); | |
| 144 | − if (energy > 0) | |
| 137 | + for (i = 0; i < size; i++) | |
| 145 | 138 | { |
| 146 | − scale = DIV(REAL_CONST(1),energy); | |
| 147 | − | |
| 148 | − if (exp < 0) | |
| 149 | − scale >>= -exp; | |
| 139 | + real_t tmp = (int32_t)ne_rng(__r1, __r2); | |
| 140 | + if (tmp < 0) | |
| 141 | + tmp = -(tmp & mask); | |
| 150 | 142 | else |
| 151 | − scale <<= exp; | |
| 152 | − | |
| 153 | − if (frac) | |
| 154 | − scale = MUL_C(scale, pow2_table[frac]); | |
| 155 | − | |
| 156 | − for (i = 0; i < size; i++) | |
| 157 | − { | |
| 158 | − spec[i] = MUL_R(spec[i], scale); | |
| 159 | − } | |
| 143 | + tmp = (tmp & mask); | |
| 144 | + spec[i] = MUL_C(tmp, scale); | |
| 160 | 145 | } |
| 161 | 146 | #endif |
| 162 | 147 | } |