| /* |
| * Copyright (c) 2011 Apple Inc. All rights reserved. |
| * |
| * @APPLE_APACHE_LICENSE_HEADER_START@ |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * @APPLE_APACHE_LICENSE_HEADER_END@ |
| */ |
| |
| /* |
| File: dp_enc.c |
| |
| Contains: Dynamic Predictor encode routines |
| |
| Copyright: (c) 2001-2011 Apple, Inc. |
| */ |
| |
| #include "dplib.h" |
| #include <string.h> |
| |
| #if __GNUC__ |
| #define ALWAYS_INLINE __attribute__((always_inline)) |
| #else |
| #define ALWAYS_INLINE |
| #endif |
| |
| #if TARGET_CPU_PPC && (__MWERKS__ >= 0x3200) |
| // align loops to a 16 byte boundary to make the G5 happy |
| #pragma function_align 16 |
| #define LOOP_ALIGN asm { align 16 } |
| #else |
| #define LOOP_ALIGN |
| #endif |
| |
| void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs ) |
| { |
| int32_t k; |
| int32_t den = 1 << denshift; |
| |
| coefs[0] = (AINIT * den) >> 4; |
| coefs[1] = (BINIT * den) >> 4; |
| coefs[2] = (CINIT * den) >> 4; |
| for ( k = 3; k < numPairs; k++ ) |
| coefs[k] = 0; |
| } |
| |
| void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs ) |
| { |
| int32_t k; |
| |
| for ( k = 0; k < numPairs; k++ ) |
| dstCoefs[k] = srcCoefs[k]; |
| } |
| |
| static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i ) |
| { |
| int32_t negishift; |
| |
| negishift = ((uint32_t)-i) >> 31; |
| return negishift | (i >> 31); |
| } |
| |
| void pc_block( int32_t * in, int32_t * pc1, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift ) |
| { |
| register int16_t a0, a1, a2, a3; |
| register int32_t b0, b1, b2, b3; |
| int32_t j, k, lim; |
| int32_t * pin; |
| int32_t sum1, dd; |
| int32_t sg, sgn; |
| int32_t top; |
| int32_t del, del0; |
| uint32_t chanshift = 32 - chanbits; |
| int32_t denhalf = 1 << (denshift - 1); |
| |
| pc1[0] = in[0]; |
| if ( numactive == 0 ) |
| { |
| // just copy if numactive == 0 (but don't bother if in/out pointers the same) |
| if ( (num > 1) && (in != pc1) ) |
| memcpy( &pc1[1], &in[1], (num - 1) * sizeof(int32_t) ); |
| return; |
| } |
| if ( numactive == 31 ) |
| { |
| // short-circuit if numactive == 31 |
| for( j = 1; j < num; j++ ) |
| { |
| del = in[j] - in[j-1]; |
| pc1[j] = (del << chanshift) >> chanshift; |
| } |
| return; |
| } |
| |
| for ( j = 1; j <= numactive; j++ ) |
| { |
| del = in[j] - in[j-1]; |
| pc1[j] = (del << chanshift) >> chanshift; |
| } |
| |
| lim = numactive + 1; |
| |
| if ( numactive == 4 ) |
| { |
| // optimization for numactive == 4 |
| a0 = coefs[0]; |
| a1 = coefs[1]; |
| a2 = coefs[2]; |
| a3 = coefs[3]; |
| |
| for ( j = lim; j < num; j++ ) |
| { |
| LOOP_ALIGN |
| |
| top = in[j - lim]; |
| pin = in + j - 1; |
| |
| b0 = top - pin[0]; |
| b1 = top - pin[-1]; |
| b2 = top - pin[-2]; |
| b3 = top - pin[-3]; |
| |
| sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3) >> denshift; |
| |
| del = in[j] - top - sum1; |
| del = (del << chanshift) >> chanshift; |
| pc1[j] = del; |
| del0 = del; |
| |
| sg = sign_of_int(del); |
| if ( sg > 0 ) |
| { |
| sgn = sign_of_int( b3 ); |
| a3 -= sgn; |
| del0 -= (4 - 3) * ((sgn * b3) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b2 ); |
| a2 -= sgn; |
| del0 -= (4 - 2) * ((sgn * b2) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b1 ); |
| a1 -= sgn; |
| del0 -= (4 - 1) * ((sgn * b1) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| a0 -= sign_of_int( b0 ); |
| } |
| else if ( sg < 0 ) |
| { |
| // note: to avoid unnecessary negations, we flip the value of "sgn" |
| sgn = -sign_of_int( b3 ); |
| a3 -= sgn; |
| del0 -= (4 - 3) * ((sgn * b3) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b2 ); |
| a2 -= sgn; |
| del0 -= (4 - 2) * ((sgn * b2) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b1 ); |
| a1 -= sgn; |
| del0 -= (4 - 1) * ((sgn * b1) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| a0 += sign_of_int( b0 ); |
| } |
| } |
| |
| coefs[0] = a0; |
| coefs[1] = a1; |
| coefs[2] = a2; |
| coefs[3] = a3; |
| } |
| else if ( numactive == 8 ) |
| { |
| // optimization for numactive == 8 |
| register int16_t a4, a5, a6, a7; |
| register int32_t b4, b5, b6, b7; |
| |
| a0 = coefs[0]; |
| a1 = coefs[1]; |
| a2 = coefs[2]; |
| a3 = coefs[3]; |
| a4 = coefs[4]; |
| a5 = coefs[5]; |
| a6 = coefs[6]; |
| a7 = coefs[7]; |
| |
| for ( j = lim; j < num; j++ ) |
| { |
| LOOP_ALIGN |
| |
| top = in[j - lim]; |
| pin = in + j - 1; |
| |
| b0 = top - (*pin--); |
| b1 = top - (*pin--); |
| b2 = top - (*pin--); |
| b3 = top - (*pin--); |
| b4 = top - (*pin--); |
| b5 = top - (*pin--); |
| b6 = top - (*pin--); |
| b7 = top - (*pin); |
| pin += 8; |
| |
| sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3 |
| - a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift; |
| |
| del = in[j] - top - sum1; |
| del = (del << chanshift) >> chanshift; |
| pc1[j] = del; |
| del0 = del; |
| |
| sg = sign_of_int(del); |
| if ( sg > 0 ) |
| { |
| sgn = sign_of_int( b7 ); |
| a7 -= sgn; |
| del0 -= 1 * ((sgn * b7) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b6 ); |
| a6 -= sgn; |
| del0 -= 2 * ((sgn * b6) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b5 ); |
| a5 -= sgn; |
| del0 -= 3 * ((sgn * b5) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b4 ); |
| a4 -= sgn; |
| del0 -= 4 * ((sgn * b4) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b3 ); |
| a3 -= sgn; |
| del0 -= 5 * ((sgn * b3) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b2 ); |
| a2 -= sgn; |
| del0 -= 6 * ((sgn * b2) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| sgn = sign_of_int( b1 ); |
| a1 -= sgn; |
| del0 -= 7 * ((sgn * b1) >> denshift); |
| if ( del0 <= 0 ) |
| continue; |
| |
| a0 -= sign_of_int( b0 ); |
| } |
| else if ( sg < 0 ) |
| { |
| // note: to avoid unnecessary negations, we flip the value of "sgn" |
| sgn = -sign_of_int( b7 ); |
| a7 -= sgn; |
| del0 -= 1 * ((sgn * b7) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b6 ); |
| a6 -= sgn; |
| del0 -= 2 * ((sgn * b6) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b5 ); |
| a5 -= sgn; |
| del0 -= 3 * ((sgn * b5) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b4 ); |
| a4 -= sgn; |
| del0 -= 4 * ((sgn * b4) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b3 ); |
| a3 -= sgn; |
| del0 -= 5 * ((sgn * b3) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b2 ); |
| a2 -= sgn; |
| del0 -= 6 * ((sgn * b2) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| sgn = -sign_of_int( b1 ); |
| a1 -= sgn; |
| del0 -= 7 * ((sgn * b1) >> denshift); |
| if ( del0 >= 0 ) |
| continue; |
| |
| a0 += sign_of_int( b0 ); |
| } |
| } |
| |
| coefs[0] = a0; |
| coefs[1] = a1; |
| coefs[2] = a2; |
| coefs[3] = a3; |
| coefs[4] = a4; |
| coefs[5] = a5; |
| coefs[6] = a6; |
| coefs[7] = a7; |
| } |
| else |
| { |
| //pc_block_general: |
| // general case |
| for ( j = lim; j < num; j++ ) |
| { |
| LOOP_ALIGN |
| |
| top = in[j - lim]; |
| pin = in + j - 1; |
| |
| sum1 = 0; |
| for ( k = 0; k < numactive; k++ ) |
| sum1 -= coefs[k] * (top - pin[-k]); |
| |
| del = in[j] - top - ((sum1 + denhalf) >> denshift); |
| del = (del << chanshift) >> chanshift; |
| pc1[j] = del; |
| del0 = del; |
| |
| sg = sign_of_int( del ); |
| if ( sg > 0 ) |
| { |
| for ( k = (numactive - 1); k >= 0; k-- ) |
| { |
| dd = top - pin[-k]; |
| sgn = sign_of_int( dd ); |
| coefs[k] -= sgn; |
| del0 -= (numactive - k) * ((sgn * dd) >> denshift); |
| if ( del0 <= 0 ) |
| break; |
| } |
| } |
| else if ( sg < 0 ) |
| { |
| for ( k = (numactive - 1); k >= 0; k-- ) |
| { |
| dd = top - pin[-k]; |
| sgn = sign_of_int( dd ); |
| coefs[k] += sgn; |
| del0 -= (numactive - k) * ((-sgn * dd) >> denshift); |
| if ( del0 >= 0 ) |
| break; |
| } |
| } |
| } |
| } |
| } |