1e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* Copyright (c) 2008-2011 Octasic Inc. 2e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org Written by Jean-Marc Valin */ 3e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* 4e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org Redistribution and use in source and binary forms, with or without 5e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org modification, are permitted provided that the following conditions 6e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org are met: 7e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 8e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org - Redistributions of source code must retain the above copyright 9e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org notice, this list of conditions and the following disclaimer. 10e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org - Redistributions in binary form must reproduce the above copyright 12e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org notice, this list of conditions and the following disclaimer in the 13e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org documentation and/or other materials provided with the distribution. 14e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 19e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org*/ 27e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 28e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifdef HAVE_CONFIG_H 29e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "config.h" 30e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif 31e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 323c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com#include "opus_types.h" 333c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com#include "opus_defines.h" 343c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com 35e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include <math.h> 36e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "mlp.h" 37e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "arch.h" 38e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "tansig_table.h" 39e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#define MAX_NEURONS 100 40e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 41e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if 0 423c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE opus_val16 tansig_approx(opus_val32 _x) /* Q19 */ 43e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{ 44e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int i; 45e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_val16 xx; /* Q11 */ 46e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /*double x, y;*/ 47e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_val16 dy, yy; /* Q14 */ 48e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /*x = 1.9073e-06*_x;*/ 49e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (_x>=QCONST32(8,19)) 50e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return QCONST32(1.,14); 51e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (_x<=-QCONST32(8,19)) 52e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return -QCONST32(1.,14); 53e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org xx = EXTRACT16(SHR32(_x, 8)); 54e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /*i = lrint(25*x);*/ 55e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org i = SHR32(ADD32(1024,MULT16_16(25, xx)),11); 56e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /*x -= .04*i;*/ 57e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org xx -= EXTRACT16(SHR32(MULT16_16(20972,i),8)); 58e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /*x = xx*(1./2048);*/ 59e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /*y = tansig_table[250+i];*/ 60e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org yy = tansig_table[250+i]; 61e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /*y = yy*(1./16384);*/ 62e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org dy = 16384-MULT16_16_Q14(yy,yy); 63e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org yy = yy + MULT16_16_Q14(MULT16_16_Q11(xx,dy),(16384 - MULT16_16_Q11(yy,xx))); 64e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return yy; 65e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org} 66e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#else 67e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/*extern const float tansig_table[501];*/ 683c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE float tansig_approx(float x) 69e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{ 70e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int i; 71e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org float y, dy; 72e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org float sign=1; 733c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com /* Tests are reversed to catch NaNs */ 743c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if (!(x<8)) 75e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return 1; 763c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if (!(x>-8)) 77e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return -1; 78e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (x<0) 79e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 80e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org x=-x; 81e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org sign=-1; 82e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 83e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org i = (int)floor(.5f+25*x); 84e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org x -= .04f*i; 85e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org y = tansig_table[i]; 86e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org dy = 1-y*y; 87e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org y = y + x*dy*(1 - y*x); 88e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return sign*y; 89e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org} 90e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif 91e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 92e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if 0 93e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgvoid mlp_process(const MLP *m, const opus_val16 *in, opus_val16 *out) 94e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{ 95e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int j; 96e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_val16 hidden[MAX_NEURONS]; 97e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org const opus_val16 *W = m->weights; 98e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /* Copy to tmp_in */ 99e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (j=0;j<m->topo[1];j++) 100e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 101e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int k; 102e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_val32 sum = SHL32(EXTEND32(*W++),8); 103e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (k=0;k<m->topo[0];k++) 104e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org sum = MAC16_16(sum, in[k],*W++); 105e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org hidden[j] = tansig_approx(sum); 106e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 107e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (j=0;j<m->topo[2];j++) 108e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 109e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int k; 110e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_val32 sum = SHL32(EXTEND32(*W++),14); 111e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (k=0;k<m->topo[1];k++) 112e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org sum = MAC16_16(sum, hidden[k], *W++); 113e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org out[j] = tansig_approx(EXTRACT16(PSHR32(sum,17))); 114e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 115e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org} 116e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#else 117e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgvoid mlp_process(const MLP *m, const float *in, float *out) 118e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{ 119e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int j; 120e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org float hidden[MAX_NEURONS]; 121e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org const float *W = m->weights; 122e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /* Copy to tmp_in */ 123e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (j=0;j<m->topo[1];j++) 124e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 125e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int k; 126e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org float sum = *W++; 127e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (k=0;k<m->topo[0];k++) 128e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org sum = sum + in[k]**W++; 129e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org hidden[j] = tansig_approx(sum); 130e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 131e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (j=0;j<m->topo[2];j++) 132e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 133e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int k; 134e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org float sum = *W++; 135e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org for (k=0;k<m->topo[1];k++) 136e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org sum = sum + hidden[k]**W++; 137e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org out[j] = tansig_approx(sum); 138e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 139e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org} 140e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif 141