1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Copyright (c) 2009-2010 Xiph.Org Foundation 2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Written by Jean-Marc Valin */ 3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* 4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Redistribution and use in source and binary forms, with or without 5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org modification, are permitted provided that the following conditions 6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org are met: 7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org - Redistributions of source code must retain the above copyright 9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org notice, this list of conditions and the following disclaimer. 10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 11885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org - Redistributions in binary form must reproduce the above copyright 12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org notice, this list of conditions and the following disclaimer in the 13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org documentation and/or other materials provided with the distribution. 14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 15885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org*/ 27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef HAVE_CONFIG_H 29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "config.h" 30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "celt_lpc.h" 33885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "stack_alloc.h" 34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "mathops.h" 35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 36885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid _celt_lpc( 37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */ 38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgconst opus_val32 *ac, /* in: [0...p] autocorrelation values */ 39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint p 40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org) 41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int i, j; 43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 r; 44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 error = ac[0]; 45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT 46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 lpc[LPC_ORDER]; 47885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#else 48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org float *lpc = _lpc; 49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i = 0; i < p; i++) 52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org lpc[i] = 0; 53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (ac[0] != 0) 54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i = 0; i < p; i++) { 56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Sum up this iteration's reflection coefficient */ 57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 rr = 0; 58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (j = 0; j < i; j++) 59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org rr += MULT32_32_Q31(lpc[j],ac[i - j]); 60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org rr += SHR32(ac[i + 1],3); 61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org r = -frac_div32(SHL32(rr,3), error); 62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Update LPC coefficients and total error */ 63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org lpc[i] = SHR32(r,3); 64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (j = 0; j < (i+1)>>1; j++) 65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 tmp1, tmp2; 67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org tmp1 = lpc[j]; 68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org tmp2 = lpc[i-1-j]; 69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2); 70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1); 71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error); 74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Bail out once we get 30 dB gain */ 75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT 76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (error<SHR32(ac[0],10)) 77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#else 79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (error<.001f*ac[0]) 80885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 81885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT 85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<p;i++) 86885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org _lpc[i] = ROUND16(lpc[i],16); 87885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 88885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid celt_fir(const opus_val16 *x, 91885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_val16 *num, 92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val16 *y, 93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int N, 94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ord, 95885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val16 *mem) 96885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int i,j; 98885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<N;i++) 100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT); 102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (j=0;j<ord;j++) 103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org sum += MULT16_16(num[j],mem[j]); 105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (j=ord-1;j>=1;j--) 107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mem[j]=mem[j-1]; 109885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 110885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mem[0] = x[i]; 111885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org y[i] = ROUND16(sum, SIG_SHIFT); 112885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 113885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 114885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 115885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid celt_iir(const opus_val32 *x, 116885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_val16 *den, 117885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 *y, 118885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int N, 119885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ord, 120885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val16 *mem) 121885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 122885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int i,j; 123885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<N;i++) 124885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 125885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 sum = x[i]; 126885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (j=0;j<ord;j++) 127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 128885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org sum -= MULT16_16(den[j],mem[j]); 129885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (j=ord-1;j>=1;j--) 131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 132885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mem[j]=mem[j-1]; 133885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mem[0] = ROUND16(sum,SIG_SHIFT); 135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org y[i] = sum; 136885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 137885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid _celt_autocorr( 140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_val16 *x, /* in: [0...n-1] samples x */ 141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 *ac, /* out: [0...lag-1] ac values */ 142885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_val16 *window, 143885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int overlap, 144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int lag, 145885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int n 146885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ) 147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 148885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 d; 149885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int i; 150885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org VARDECL(opus_val16, xx); 151885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org SAVE_STACK; 152885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ALLOC(xx, n, opus_val16); 153885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_assert(n>0); 154885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_assert(overlap>=0); 155885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<n;i++) 156885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xx[i] = x[i]; 157885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<overlap;i++) 158885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 159885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xx[i] = MULT16_16_Q15(x[i],window[i]); 160885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); 161885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 162885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT 163885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 164885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 ac0=0; 165885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int shift; 166885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for(i=0;i<n;i++) 167885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ac0 += SHR32(MULT16_16(xx[i],xx[i]),9); 168885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ac0 += 1+n; 169885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 170885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org shift = celt_ilog2(ac0)-30+10; 171885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org shift = (shift+1)/2; 172885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for(i=0;i<n;i++) 173885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org xx[i] = VSHR32(xx[i], shift); 174885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 175885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 176885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org while (lag>=0) 177885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 178885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i = lag, d = 0; i < n; i++) 179885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org d += xx[i] * xx[i-lag]; 180885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ac[lag] = d; 181885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*printf ("%f ", ac[lag]);*/ 182885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org lag--; 183885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 184885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*printf ("\n");*/ 185885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ac[0] += 10; 186885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 187885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 188885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 189