| 
							- // Copyright 2011 Olivier Gillet.
 - //
 - // Author: Olivier Gillet (ol.gillet@gmail.com)
 - //
 - // This program is free software: you can redistribute it and/or modify
 - // it under the terms of the GNU General Public License as published by
 - // the Free Software Foundation, either version 3 of the License, or
 - // (at your option) any later version.
 - // This program is distributed in the hope that it will be useful,
 - // but WITHOUT ANY WARRANTY; without even the implied warranty of
 - // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - // GNU General Public License for more details.
 - // You should have received a copy of the GNU General Public License
 - // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 - //
 - // -----------------------------------------------------------------------------
 - //
 - // A set of basic operands, especially useful for fixed-point arithmetic, with
 - // fast ASM implementations.
 - 
 - #ifndef AVRLIBX_UTILS_OP_H_
 - #define AVRLIBX_UTILS_OP_H_
 - 
 - #define USE_OPTIMIZED_OP
 - 
 - #include <avr/pgmspace.h>
 - 
 - #include "avrlibx/avrlibx.h"
 - 
 - namespace avrlibx {
 - 
 - static inline int16_t Clip(int16_t value, int16_t min, int16_t max) {
 -   return value < min ? min : (value > max ? max : value);
 - }
 - 
 - static inline int16_t S16ClipU14(int16_t value) {
 -   uint8_t msb = static_cast<uint16_t>(value) >> 8;
 -   if (msb & 0x80) {
 -     return 0;
 -   } if (msb & 0x40) {
 -     return 16383;
 -   }
 -   return value;
 - }
 - 
 - static inline uint8_t U8AddClip(uint8_t value, uint8_t increment, uint8_t max) {
 -   value += increment;
 -   if (value > max) {
 -     value = max;
 -   }
 -   return value;
 - }
 - 
 - // Correct only if the input is positive.
 - static inline uint8_t S16ShiftRight8(int16_t value) {
 -   return static_cast<uint16_t>(value) >> 8;
 - }
 - 
 - #ifdef USE_OPTIMIZED_OP
 - 
 - static inline uint24c_t U24AddC(uint24c_t a, uint24_t b) {
 -   uint16_t a_int = a.integral;
 -   uint16_t b_int = b.integral;
 -   uint8_t a_frac = a.fractional;
 -   uint8_t b_frac = b.fractional;
 -   uint8_t a_carry = 0;
 -   uint24c_t result;
 -   asm(
 -     "add %0, %6"      "\n\t"
 -     "adc %A1, %A7"    "\n\t"
 -     "adc %B1, %B7"    "\n\t"
 -     "adc %2, r1"      "\n\t"
 -     : "=r" (a_frac), "=r" (a_int), "=r" (a_carry)
 -     : "0" (a_frac), "1" (a_int), "2" (a_carry), "a" (b_frac), "a" (b_int)
 -   );
 -   result.integral = a_int;
 -   result.fractional = a_frac;
 -   result.carry = a_carry;
 -   return result;
 - }
 - 
 - static inline uint24_t U24Add(uint24_t a, uint24_t b) {
 -   uint16_t a_int = a.integral;
 -   uint16_t b_int = b.integral;
 -   uint8_t a_frac = a.fractional;
 -   uint8_t b_frac = b.fractional;
 -   uint24_t result;
 -   asm(
 -     "add %0, %4"      "\n\t"
 -     "adc %A1, %A5"    "\n\t"
 -     "adc %B1, %B5"    "\n\t"
 -     : "=r" (a_frac), "=r" (a_int)
 -     : "0" (a_frac), "1" (a_int), "a" (b_frac), "a" (b_int)
 -   );
 -   result.integral = a_int;
 -   result.fractional = a_frac;
 -   return result;
 - }
 - 
 - static inline uint24_t U24Sub(uint24_t a, uint24_t b) {
 -   uint16_t a_int = a.integral;
 -   uint16_t b_int = b.integral;
 -   uint8_t a_frac = a.fractional;
 -   uint8_t b_frac = b.fractional;
 -   uint24_t result;
 -   asm(
 -     "sub %0, %4"      "\n\t"
 -     "sbc %A1, %A5"    "\n\t"
 -     "sbc %B1, %B5"    "\n\t"
 -     : "=r" (a_frac), "=r" (a_int)
 -     : "0" (a_frac), "1" (a_int), "a" (b_frac), "a" (b_int)
 -   );
 -   result.integral = a_int;
 -   result.fractional = a_frac;
 -   return result;
 - }
 - 
 - static inline uint24_t U24ShiftRight(uint24_t a) {
 -   uint16_t a_int = a.integral;
 -   uint8_t a_frac = a.fractional;
 -   uint24_t result;
 -   asm(
 -     "lsr %B1"      "\n\t"
 -     "ror %A1"    "\n\t"
 -     "ror %0"    "\n\t"
 -     : "=r" (a_frac), "=r" (a_int)
 -     : "0" (a_frac), "1" (a_int)
 -   );
 -   result.integral = a_int;
 -   result.fractional = a_frac;
 -   return result;
 - }
 - 
 - static inline uint24_t U24ShiftLeft(uint24_t a) {
 -   uint16_t a_int = a.integral;
 -   uint8_t a_frac = a.fractional;
 -   uint24_t result;
 -   asm(
 -     "lsl %0"    "\n\t"
 -     "rol %A1"    "\n\t"
 -     "rol %B1"      "\n\t"
 -     : "=r" (a_frac), "=r" (a_int)
 -     : "0" (a_frac), "1" (a_int)
 -   );
 -   result.integral = a_int;
 -   result.fractional = a_frac;
 -   return result;
 - }
 - 
 - static inline uint8_t S16ClipU8(int16_t value) {
 -   uint8_t result;
 -   asm(
 -     "mov %0, %A1"   "\n\t"  // by default, copy the value.
 -     "or %B1, %B1"   "\n\t"  // load H to set flags.
 -     "brpl .+4"      "\n\t"  // if positive, skip
 -     "ldi %0, 0"     "\n\t"  // set to 0.
 -     "rjmp .+4"      "\n\t"  // and jump.
 -     "breq .+2"      "\n\t"  // if null, skip
 -     "ldi %0, 255"   "\n\t"  // set to 255
 -     : "=r" (result)
 -     : "a" (value)
 -   );
 -   return result;
 - }
 - 
 - static inline int8_t S16ClipS8(int16_t value) {
 -   return S16ClipU8(value + 128) + 128;
 - }
 - 
 - static inline uint8_t U8Mix(uint8_t a, uint8_t b, uint8_t balance) {
 -   Word sum;
 -   asm(
 -     "mul %3, %2"      "\n\t"  // b * balance
 -     "movw %A0, r0"    "\n\t"  // to sum
 -     "com %2"          "\n\t"  // 255 - balance
 -     "mul %1, %2"      "\n\t"  // a * (255 - balance)
 -     "com %2"          "\n\t"  // reset balance to its previous value
 -     "add %A0, r0"     "\n\t"  // add to sum L
 -     "adc %B0, r1"     "\n\t"  // add to sum H
 -     "eor r1, r1"      "\n\t"  // reset r1 after multiplication
 -     : "&=r" (sum)
 -     : "a" (a), "a" (balance), "a" (b)
 -     );
 -   return sum.bytes[1];
 - }
 - 
 - static inline uint8_t U8Mix(
 -     uint8_t a, uint8_t b,
 -     uint8_t gain_a, uint8_t gain_b) {
 -   Word sum;
 -   asm(
 -     "mul %3, %4"      "\n\t"  // b * gain_b
 -     "movw %A0, r0"    "\n\t"  // to sum
 -     "mul %1, %2"      "\n\t"  // a * gain_a
 -     "add %A0, r0"     "\n\t"  // add to sum L
 -     "adc %B0, r1"     "\n\t"  // add to sum H
 -     "eor r1, r1"      "\n\t"  // reset r1 after multiplication
 -     : "&=r" (sum)
 -     : "a" (a), "a" (gain_a), "a" (b), "a" (gain_b)
 -     );
 -   return sum.bytes[1];
 - }
 - 
 - static inline int8_t S8Mix(
 -     int8_t a, int8_t b,
 -     uint8_t gain_a, uint8_t gain_b) {
 -   Word sum;
 -   asm(
 -     "mulsu %3, %4"    "\n\t"  // b * gain_b
 -     "movw %A0, r0"    "\n\t"  // to sum
 -     "mulsu %1, %2"    "\n\t"  // a * gain_a
 -     "add %A0, r0"     "\n\t"  // add to sum L
 -     "adc %B0, r1"     "\n\t"  // add to sum H
 -     "eor r1, r1"      "\n\t"  // reset r1 after multiplication
 -     : "&=r" (sum)
 -     : "a" (a), "a" (gain_a), "a" (b), "a" (gain_b)
 -     );
 -   return sum.bytes[1];
 - }
 - 
 - static inline uint16_t U8MixU16(uint8_t a, uint8_t b, uint8_t balance) {
 -   Word sum;
 -   asm(
 -     "mul %3, %2"      "\n\t"  // b * balance
 -     "movw %A0, r0"    "\n\t"  // to sum
 -     "com %2"          "\n\t"  // 255 - balance
 -     "mul %1, %2"      "\n\t"  // a * (255 - balance)
 -     "com %2"          "\n\t"  // reset balance to its previous value
 -     "add %A0, r0"     "\n\t"  // add to sum L
 -     "adc %B0, r1"     "\n\t"  // add to sum H
 -     "eor r1, r1"      "\n\t"  // reset r1 after multiplication
 -     : "&=r" (sum)
 -     : "a" (a), "a" (balance), "a" (b)
 -     );
 -   return sum.value;
 - }
 - 
 - static inline uint8_t U8U4MixU8(uint8_t a, uint8_t b, uint8_t balance) {
 -   uint16_t sum;
 -   asm(
 -     "mul %2, %1"      "\n\t"  // b * balance
 -     "movw %A3, r0"    "\n\t"  // to sum
 -     "com %1"          "\n\t"  // 255 - balance
 -     "subi %1, 240"    "\n\t"  // 15 - balance
 -     "mul %0, %1"      "\n\t"  // a * (15 - balance)
 -     "subi %1, 16"     "\n\t"
 -     "com %1"          "\n\t"  // reset balance to its previous value
 -     "add %A3, r0"     "\n\t"  // add to sum L
 -     "adc %B3, r1"     "\n\t"  // add to sum H
 -     "eor r1, r1"      "\n\t"  // reset r1 after multiplication
 -     "andi %B3, 15"    "\n\t"  // keep 4 lowest bits of H
 -     "andi %A3, 240"   "\n\t"  // keep 4 highest bits of L 
 -     "or %B3, %A3"     "\n\t"  // copy 4 high bits of L to H -> LLLLHHHH
 -     "swap %B3"        "\n\t"  // swap to get HHHHLLLL
 -     "mov %0, %B3"     "\n\t"  // move to output
 -     : "=r" (a)
 -     : "a" (balance), "a" (b), "a" (sum)
 -     );
 -   return a;
 - }
 - 
 - static inline uint16_t U8U4MixU12(uint8_t a, uint8_t b, uint8_t balance) {
 -   uint16_t sum;
 -   asm(
 -     "mul %3, %2"      "\n\t"  // b * balance
 -     "movw %A0, r0"    "\n\t"  // to sum
 -     "com %2"          "\n\t"  // 255 - balance
 -     "subi %2, 240"    "\n\t"  // 15 - balance
 -     "mul %1, %2"      "\n\t"  // a * (15 - balance)
 -     "subi %2, 16"     "\n\t"
 -     "com %2"          "\n\t"  // reset balance to its previous value
 -     "add %A0, r0"     "\n\t"  // add to sum L
 -     "adc %B0, r1"     "\n\t"  // add to sum H
 -     "eor r1, r1"      "\n\t"  // reset r1 after multiplication
 -     : "&=r" (sum)
 -     : "a" (a), "a" (balance), "a" (b)
 -     );
 -   return sum;
 - }
 - 
 - static inline uint8_t U8ShiftLeft4(uint8_t a) {
 -   uint8_t result;
 -   asm(
 -     "mov %0, %1"      "\n\t"
 -     "swap %0"         "\n\t"
 -     "andi %0, 240"     "\n\t"
 -     : "=r" (result)
 -     : "a" (a)
 -     );
 -   return result;
 - }
 - 
 - static inline uint8_t U8Swap4(uint8_t a) {
 -   uint8_t result;
 -   asm(
 -     "mov %0, %1"      "\n\t"
 -     "swap %0"         "\n\t"
 -     : "=r" (result)
 -     : "a" (a)
 -     );
 -   return result;
 - }
 - 
 - static inline uint8_t U8ShiftRight4(uint8_t a) {
 -   uint8_t result;
 -   asm(
 -     "mov %0, %1"      "\n\t"
 -     "swap %0"         "\n\t"
 -     "andi %0, 15"     "\n\t"
 -     : "=r" (result)
 -     : "a" (a)
 -     );
 -   return result;
 - }
 - 
 - static inline uint16_t U16ShiftRight4(uint16_t a) {
 -   uint16_t result;
 -   asm(
 -     "movw %A0, %A1" "\n\t"
 -     "lsr %B0"      "\n\t"
 -     "ror %A0"      "\n\t"
 -     "lsr %B0"      "\n\t"
 -     "ror %A0"      "\n\t"
 -     "lsr %B0"      "\n\t"
 -     "ror %A0"      "\n\t"
 -     "lsr %B0"      "\n\t"
 -     "ror %A0"      "\n\t"
 -     : "=r" (result)
 -     : "a" (a)
 -     );
 -   return result;
 - }
 - 
 - 
 - static inline uint8_t U8U8MulShift8(uint8_t a, uint8_t b) {
 -   uint8_t result;
 -   asm(
 -     "mul %1, %2"      "\n\t"
 -     "mov %0, r1"      "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int8_t S8U8MulShift8(int8_t a, uint8_t b) {
 -   uint8_t result;
 -   asm(
 -     "mulsu %1, %2"    "\n\t"
 -     "mov %0, r1"      "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int16_t S8U8Mul(int8_t a, uint8_t b) {
 -   int16_t result;
 -   asm(
 -     "mulsu %1, %2"    "\n\t"
 -     "movw %0, r0"      "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int16_t S8S8Mul(int8_t a, int8_t b) {
 -   int16_t result;
 -   asm(
 -     "muls %1, %2"    "\n\t"
 -     "movw %0, r0"      "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline uint16_t U8U8Mul(uint8_t a, uint8_t b) {
 -   uint16_t result;
 -   asm(
 -     "mul %1, %2"    "\n\t"
 -     "movw %0, r0"      "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int8_t S8S8MulShift8(int8_t a, int8_t b) {
 -   uint8_t result;
 -   asm(
 -     "muls %1, %2"    "\n\t"
 -     "mov %0, r1"      "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - // The code generated by gcc for >> 6 is short but uses a loop. This saves
 - // a couple of cycles. Note that this solution only works for operands with
 - // a 14-bits resolution.
 - static inline uint8_t U14ShiftRight6(uint16_t value) {
 -   uint8_t b = value >> 8;
 -   uint8_t a = value & 0xff;
 -   uint8_t result;
 -   asm(
 -     "add %1, %1"       "\n\t"
 -     "adc %2, %2"       "\n\t"
 -     "add %1, %1"       "\n\t"
 -     "adc %2, %2"       "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "0" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline uint8_t U15ShiftRight7(uint16_t value) {
 -   uint8_t b = value >> 8;
 -   uint8_t a = value & 0xff;
 -   uint8_t result;
 -   asm(
 -     "add %1, %1"       "\n\t"
 -     "adc %2, %2"       "\n\t"
 -     : "=r" (result)
 -     : "a" (a), "0" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int16_t S16U16MulShift16(int16_t a, uint16_t b) {
 -   int16_t result;
 -   int16_t tmp;
 -   asm(
 -     "eor %A1, %A1"    "\n\t"
 -     "mul %A2, %A3"    "\n\t"
 -     "mov %B1, r1"    "\n\t"
 -     "mulsu %B2, %B3"  "\n\t"
 -     "movw %A0, r0"    "\n\t"
 -     "mul %B3, %A2"    "\n\t"
 -     "add %B1, r0"     "\n\t"
 -     "adc %A0, r1"     "\n\t"
 -     "adc %B0, %A1"    "\n\t"
 -     "mulsu %B2, %A3"  "\n\t"
 -     "sbc %B0, %A1"    "\n\t"
 -     "add %B1, r0"     "\n\t"
 -     "adc %A0, r1"     "\n\t"
 -     "adc %B0, %A1"    "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=&r" (result), "=&r" (tmp)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int16_t S16U12MulShift12(int16_t a, uint16_t b) {
 -   int16_t result;
 -   int16_t tmp;
 -   asm(
 -     "add %A3, %A3"    "\n\t"
 -     "adc %B3, %B3"    "\n\t"
 -     "add %A3, %A3"    "\n\t"
 -     "adc %B3, %B3"    "\n\t"
 -     "add %A3, %A3"    "\n\t"
 -     "adc %B3, %B3"    "\n\t"
 -     "add %A3, %A3"    "\n\t"
 -     "adc %B3, %B3"    "\n\t"
 -     "eor %A1, %A1"    "\n\t"
 -     "mul %A2, %A3"    "\n\t"
 -     "mov %B1, r1"    "\n\t"
 -     "mulsu %B2, %B3"  "\n\t"
 -     "movw %A0, r0"    "\n\t"
 -     "mul %B3, %A2"    "\n\t"
 -     "add %B1, r0"     "\n\t"
 -     "adc %A0, r1"     "\n\t"
 -     "adc %B0, %A1"    "\n\t"
 -     "mulsu %B2, %A3"  "\n\t"
 -     "sbc %B0, %A1"    "\n\t"
 -     "add %B1, r0"     "\n\t"
 -     "adc %A0, r1"     "\n\t"
 -     "adc %B0, %A1"    "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=&r" (result), "=&r" (tmp)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline uint16_t U16U16MulShift16(uint16_t a, uint16_t b) {
 -   uint16_t result;
 -   uint16_t tmp;
 -   asm(
 -     "eor %A1, %A1"    "\n\t"
 -     "mul %A2, %A3"    "\n\t"
 -     "mov %B1, r1"     "\n\t"
 -     "mul %B2, %B3"    "\n\t"
 -     "movw %A0, r0"    "\n\t"
 -     "mul %B3, %A2"    "\n\t"
 -     "add %B1, r0"     "\n\t"
 -     "adc %A0, r1"     "\n\t"
 -     "adc %B0, %A1"    "\n\t"
 -     "mul %B2, %A3"    "\n\t"
 -     "add %B1, r0"     "\n\t"
 -     "adc %A0, r1"     "\n\t"
 -     "adc %B0, %A1"    "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=&r" (result), "=&r" (tmp)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int16_t S16U8MulShift8(int16_t a, uint8_t b) {
 -   int16_t result;
 -   asm(
 -     "eor %B0, %B0"    "\n\t"
 -     "mul %A1, %A2"    "\n\t"
 -     "mov %A0, r1"     "\n\t"
 -     "mulsu %B1, %A2"  "\n\t"
 -     "add %A0, r0"     "\n\t"
 -     "adc %B0, r1"     "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=&r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline uint16_t U16U8MulShift8(uint16_t a, uint8_t b) {
 -   uint16_t result;
 -   asm(
 -     "eor %B0, %B0"    "\n\t"
 -     "mul %A1, %A2"    "\n\t"
 -     "mov %A0, r1"     "\n\t"
 -     "mul %B1, %A2"  "\n\t"
 -     "add %A0, r0"     "\n\t"
 -     "adc %B0, r1"     "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=&r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline int16_t S16S8MulShift8(int16_t a, int8_t b) {
 -   int16_t result;
 -   asm(
 -     "eor %B0, %B0"    "\n\t"
 -     "muls %A2, %B1"   "\n\t"
 -     "movw %A0, r0"    "\n\t"
 -     "mulsu %A2, %A1"  "\n\t"
 -     "eor r0, r0"      "\n\t"
 -     "sbc %B0, r0"     "\n\t"
 -     "add %A0, r1"     "\n\t"
 -     "adc %B0, r0"     "\n\t"
 -     "eor r1, r1"      "\n\t"
 -     : "=&r" (result)
 -     : "a" (a), "a" (b)
 -   );
 -   return result;
 - }
 - 
 - static inline uint8_t InterpolateSample(
 -     const prog_uint8_t* table,
 -     uint16_t phase) __attribute__((always_inline));
 - 
 - static inline uint8_t InterpolateSample(
 -     const prog_uint8_t* table,
 -     uint16_t phase) {
 -   uint8_t result;
 -   uint8_t work;
 -   asm(
 -     "movw r30, %A2"           "\n\t"  // copy base address to r30:r31
 -     "add r30, %B3"            "\n\t"  // increment table address by phaseH
 -     "adc r31, r1"             "\n\t"  // just carry
 -     "mov %1, %A3"             "\n\t"  // move phaseL to working register
 -     "lpm %0, z+"              "\n\t"  // load sample[n]
 -     "lpm r1, z+"              "\n\t"  // load sample[n+1]
 -     "mul %1, r1"              "\n\t"  // multiply second sample by phaseL
 -     "movw r30, r0"            "\n\t"  // result to accumulator
 -     "com %1"                  "\n\t"  // 255 - phaseL -> phaseL
 -     "mul %1, %0"              "\n\t"  // multiply first sample by phaseL
 -     "add r30, r0"             "\n\t"  // accumulate L
 -     "adc r31, r1"             "\n\t"  // accumulate H
 -     "eor r1, r1"              "\n\t"  // reset r1 after multiplication
 -     "mov %0, r31"             "\n\t"  // use sum H as output
 -     : "=r" (result), "=r" (work)
 -     : "r" (table), "r" (phase)
 -     : "r30", "r31"
 -   );
 -   return result;
 - }
 - 
 - #else
 - 
 - static inline uint24c_t U24AddC(uint24c_t a, uint24_t b) {
 -   uint24c_t result;
 - 
 -   uint32_t av = static_cast<uint32_t>(a.integral) << 8;
 -   av += a.fractional;
 - 
 -   uint32_t bv = static_cast<uint32_t>(b.integral) << 8;
 -   bv += b.fractional;
 - 
 -   uint32_t sum = av + bv;
 -   result.integral = sum >> 8;
 -   result.fractional = sum & 0xff;
 -   result.carry = (sum & 0xff000000) != 0;
 -   return result;
 - }
 - 
 - static inline uint24_t U24Add(uint24_t a, uint24_t b) {
 -   uint24_t result;
 - 
 -   uint32_t av = static_cast<uint32_t>(a.integral) << 8;
 -   av += a.fractional;
 - 
 -   uint32_t bv = static_cast<uint32_t>(b.integral) << 8;
 -   bv += b.fractional;
 - 
 -   uint32_t sum = av + bv;
 -   result.integral = sum >> 8;
 -   result.fractional = sum & 0xff;
 -   return result;
 - }
 - 
 - static inline uint24_t U24Sub(uint24_t a, uint24_t b) {
 -   uint24_t result;
 - 
 -   uint32_t av = static_cast<uint32_t>(a.integral) << 8;
 -   av += a.fractional;
 - 
 -   uint32_t bv = static_cast<uint32_t>(b.integral) << 8;
 -   bv += b.fractional;
 - 
 -   uint32_t difference = av - bv;
 -   result.integral = sum >> 8;
 -   result.fractional = sum & 0xff;
 -   return result;
 - }
 - 
 - static inline uint24_t U24ShiftRight(uint24_t a) {
 -   uint24_t result;
 -   uint32_t av = static_cast<uint32_t>(a.integral) << 8;
 -   av += a.fractional;
 -   av >>= 1;
 -   result.integral = av >> 8;
 -   result.fractional = av & 0xff;
 -   return result;
 - }
 - 
 - static inline uint24_t U24ShiftLeft(uint24_t a) {
 -   uint24_t result;
 -   uint32_t av = static_cast<uint32_t>(a.integral) << 8;
 -   av += a.fractional;
 -   av <<= 1;
 -   result.integral = av >> 8;
 -   result.fractional = av & 0xff;
 -   return result;
 - }
 - 
 - static inline uint8_t S16ClipU8(int16_t value) {
 -   return value < 0 ? 0 : (value > 255 ? 255 : value);
 - }
 - 
 - static inline int8_t S16ClipS8(int16_t value) {
 -   return value < -128 ? -128 : (value > 127 ? 127 : value);
 - }
 - 
 - static inline uint8_t U8Mix(uint8_t a, uint8_t b, uint8_t balance) {
 -   return a * (255 - balance) + b * balance >> 8;
 - }
 - 
 - static inline uint8_t U8Mix(uint8_t a, uint8_t b, uint8_t gain_a, uint8_t gain_b) {
 -   return a * gain_a + b * gain_b >> 8;
 - }
 - 
 - static inline int8_t S8Mix(
 -     int8_t a, int8_t b,
 -     uint8_t gain_a, uint8_t gain_b) {
 -   return a * gain_a + b * gain_b >> 8;
 - }
 - 
 - static inline uint16_t U8MixU16(uint8_t a, uint8_t b, uint8_t balance) {
 -   return a * (255 - balance) + b * balance;
 - }
 - 
 - static inline uint8_t U8U4MixU8(uint8_t a, uint8_t b, uint8_t balance) {
 -   return (a * (15 - balance) + b * balance) >> 4;
 - }
 - 
 - static inline uint16_t U8U4MixU12(uint8_t a, uint8_t b, uint8_t balance) {
 -   return a * (15 - balance) + b * balance;
 - }
 - 
 - static inline uint8_t U8ShiftRight4(uint8_t a) {
 -   return a >> 4;
 - }
 - 
 - static inline uint8_t U8ShiftLeft4(uint8_t a) {
 -   return a << 4;
 - }
 - 
 - static inline uint8_t U8Swap4(uint8_t a) {
 -   return (a << 4) | (a >> 4);
 - }
 - 
 - static inline uint8_t U8U8MulShift8(uint8_t a, uint8_t b) {
 -   return a * b >> 8;
 - }
 - 
 - static inline int8_t S8U8MulShift8(int8_t a, uint8_t b) {
 -   return a * b >> 8;
 - }
 - 
 - static inline int16_t S8U8Mul(int8_t a, uint8_t b) {
 -   return a * b;
 - }
 - 
 - static inline int16_t S8S8Mul(int8_t a, int8_t b) {
 -   return a * b;
 - }
 - 
 - static inline uint16_t U8U8Mul(uint8_t a, uint8_t b) {
 -   return a * b;
 - }
 - 
 - static inline int8_t S8S8MulShift8(int8_t a, int8_t b) {
 -   return a * b >> 8;
 - }
 - 
 - static inline uint16_t Mul16Scale8(uint16_t a, uint16_t b) {
 -   return static_cast<uint32_t>(a) * b >> 8;
 - }
 - 
 - static inline uint8_t U14ShiftRight6(uint16_t value) {
 -   return value >> 6;
 - }
 - 
 - static inline uint8_t U15ShiftRight7(uint16_t value) {
 -   return value >> 7;
 - }
 - 
 - static inline uint16_t U16ShiftRight4(uint16_t a) {
 -   return a >> 4;
 - }
 - 
 - static inline int16_t S16U16MulShift16(int16_t a, uint16_t b) {
 -   return (static_cast<int32_t>(a) * static_cast<uint32_t>(b)) >> 16;
 - }
 - 
 - static inline int12_t S16U12MulShift12(int16_t a, uint16_t b) {
 -   return (static_cast<int32_t>(a) * static_cast<uint32_t>(b)) >> 12;
 - }
 - 
 - static inline int16_t S16U8MulShift8(int16_t a, uint8_t b) {
 -   return (static_cast<int32_t>(a) * static_cast<uint32_t>(b)) >> 8;
 - }
 - 
 - static inline uint16_t U16U8MulShift8(uint16_t a, uint8_t b) {
 -   return (static_cast<uint32_t>(a) * static_cast<uint32_t>(b)) >> 8;
 - }
 - 
 - static inline uint8_t InterpolateSample(
 -     const prog_uint8_t* table,
 -     uint16_t phase) {
 -   return U8Mix(
 -       pgm_read_byte(table + (phase >> 8)),
 -       pgm_read_byte(1 + table + (phase >> 8)),
 -       phase & 0xff);
 - }
 - 
 - #endif  // USE_OPTIMIZED_OP
 - 
 - }  // namespace avrlibx
 - 
 - #endif  // AVRLIBX_UTILS_OP_H_
 
 
  |