Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 1 | /* |
| 2 | * AC-3 DSP utils |
| 3 | * Copyright (c) 2011 Justin Ruggles |
| 4 | * |
Mans Rullgard | 2912e87 | 2011-03-18 17:35:10 | [diff] [blame] | 5 | * This file is part of Libav. |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 6 | * |
Mans Rullgard | 2912e87 | 2011-03-18 17:35:10 | [diff] [blame] | 7 | * Libav is free software; you can redistribute it and/or |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 8 | * modify it under the terms of the GNU Lesser General Public |
| 9 | * License as published by the Free Software Foundation; either |
| 10 | * version 2.1 of the License, or (at your option) any later version. |
| 11 | * |
Mans Rullgard | 2912e87 | 2011-03-18 17:35:10 | [diff] [blame] | 12 | * Libav is distributed in the hope that it will be useful, |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * Lesser General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU Lesser General Public |
Mans Rullgard | 2912e87 | 2011-03-18 17:35:10 | [diff] [blame] | 18 | * License along with Libav; if not, write to the Free Software |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | */ |
| 21 | |
| 22 | #include "avcodec.h" |
| 23 | #include "ac3dsp.h" |
| 24 | |
| 25 | static void ac3_exponent_min_c(uint8_t *exp, int num_reuse_blocks, int nb_coefs) |
| 26 | { |
| 27 | int blk, i; |
| 28 | |
| 29 | if (!num_reuse_blocks) |
| 30 | return; |
| 31 | |
| 32 | for (i = 0; i < nb_coefs; i++) { |
| 33 | uint8_t min_exp = *exp; |
| 34 | uint8_t *exp1 = exp + 256; |
| 35 | for (blk = 0; blk < num_reuse_blocks; blk++) { |
| 36 | uint8_t next_exp = *exp1; |
| 37 | if (next_exp < min_exp) |
| 38 | min_exp = next_exp; |
| 39 | exp1 += 256; |
| 40 | } |
| 41 | *exp++ = min_exp; |
| 42 | } |
| 43 | } |
| 44 | |
Justin Ruggles | fbb6b49 | 2011-02-13 19:49:50 | [diff] [blame] | 45 | static int ac3_max_msb_abs_int16_c(const int16_t *src, int len) |
| 46 | { |
| 47 | int i, v = 0; |
| 48 | for (i = 0; i < len; i++) |
| 49 | v |= abs(src[i]); |
| 50 | return v; |
| 51 | } |
| 52 | |
Justin Ruggles | f1efbca | 2011-03-11 21:45:01 | [diff] [blame] | 53 | static void ac3_lshift_int16_c(int16_t *src, unsigned int len, |
| 54 | unsigned int shift) |
| 55 | { |
| 56 | uint32_t *src32 = (uint32_t *)src; |
| 57 | const uint32_t mask = ~(((1 << shift) - 1) << 16); |
| 58 | int i; |
| 59 | len >>= 1; |
| 60 | for (i = 0; i < len; i += 8) { |
| 61 | src32[i ] = (src32[i ] << shift) & mask; |
| 62 | src32[i+1] = (src32[i+1] << shift) & mask; |
| 63 | src32[i+2] = (src32[i+2] << shift) & mask; |
| 64 | src32[i+3] = (src32[i+3] << shift) & mask; |
| 65 | src32[i+4] = (src32[i+4] << shift) & mask; |
| 66 | src32[i+5] = (src32[i+5] << shift) & mask; |
| 67 | src32[i+6] = (src32[i+6] << shift) & mask; |
| 68 | src32[i+7] = (src32[i+7] << shift) & mask; |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | static void ac3_rshift_int32_c(int32_t *src, unsigned int len, |
| 73 | unsigned int shift) |
| 74 | { |
| 75 | do { |
| 76 | *src++ >>= shift; |
| 77 | *src++ >>= shift; |
| 78 | *src++ >>= shift; |
| 79 | *src++ >>= shift; |
| 80 | *src++ >>= shift; |
| 81 | *src++ >>= shift; |
| 82 | *src++ >>= shift; |
| 83 | *src++ >>= shift; |
| 84 | len -= 8; |
| 85 | } while (len > 0); |
| 86 | } |
| 87 | |
Justin Ruggles | 0f999cf | 2011-03-16 02:29:04 | [diff] [blame] | 88 | static void float_to_fixed24_c(int32_t *dst, const float *src, unsigned int len) |
| 89 | { |
| 90 | const float scale = 1 << 24; |
| 91 | do { |
| 92 | *dst++ = lrintf(*src++ * scale); |
| 93 | *dst++ = lrintf(*src++ * scale); |
| 94 | *dst++ = lrintf(*src++ * scale); |
| 95 | *dst++ = lrintf(*src++ * scale); |
| 96 | *dst++ = lrintf(*src++ * scale); |
| 97 | *dst++ = lrintf(*src++ * scale); |
| 98 | *dst++ = lrintf(*src++ * scale); |
| 99 | *dst++ = lrintf(*src++ * scale); |
| 100 | len -= 8; |
| 101 | } while (len > 0); |
| 102 | } |
| 103 | |
| 104 | av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact) |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 105 | { |
| 106 | c->ac3_exponent_min = ac3_exponent_min_c; |
Justin Ruggles | fbb6b49 | 2011-02-13 19:49:50 | [diff] [blame] | 107 | c->ac3_max_msb_abs_int16 = ac3_max_msb_abs_int16_c; |
Justin Ruggles | f1efbca | 2011-03-11 21:45:01 | [diff] [blame] | 108 | c->ac3_lshift_int16 = ac3_lshift_int16_c; |
| 109 | c->ac3_rshift_int32 = ac3_rshift_int32_c; |
Justin Ruggles | 0f999cf | 2011-03-16 02:29:04 | [diff] [blame] | 110 | c->float_to_fixed24 = float_to_fixed24_c; |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 111 | |
Mans Rullgard | f4855a9 | 2011-03-09 19:51:50 | [diff] [blame^] | 112 | if (ARCH_ARM) |
| 113 | ff_ac3dsp_init_arm(c, bit_exact); |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 114 | if (HAVE_MMX) |
Justin Ruggles | 0f999cf | 2011-03-16 02:29:04 | [diff] [blame] | 115 | ff_ac3dsp_init_x86(c, bit_exact); |
Justin Ruggles | dda3f0e | 2011-02-10 17:20:36 | [diff] [blame] | 116 | } |