示例#1
0
文件: matrix.c 项目: pombreda/yael
/* Construct a Hadamard matrix of dimension d using the Sylvester construction.
   d should be a power of 2 */
float *hadamard (int d)
{
  assert ((d & (d - 1)) == 0 || !"d must be power of 2");

  int i, j;
  float *had = fvec_new (d * d);

  if (d == 1) {
    had[0] = 1;
    return had;
  }

  /* Compute the Hadamard matrix of dimension d / 2 */
  int dd = d / 2;
  float *had_part = hadamard (dd);

  for (i = 0; i < dd; i++)
    for (j = 0; j < dd; j++) {
      had[i * d + j] = had_part[i * dd + j];
      had[i * d + j + dd] = had_part[i * dd + j];
      had[(i + dd) * d + j] = had_part[i * dd + j];
      had[(i + dd) * d + j + dd] = -had_part[i * dd + j];
    }

  free (had_part);
  return (had);
}
void LateReflectionsNode::recompute() {
	float density = getProperty(Lav_LATE_REFLECTIONS_DENSITY).getFloatValue();
	float t60=getProperty(Lav_LATE_REFLECTIONS_T60).getFloatValue();
	float t60_high =getProperty(Lav_LATE_REFLECTIONS_HF_T60).getFloatValue();
	float t60_low =getProperty(Lav_LATE_REFLECTIONS_LF_T60).getFloatValue();
	float hf_reference=getProperty(Lav_LATE_REFLECTIONS_HF_REFERENCE).getFloatValue();
	float lf_reference = getProperty(Lav_LATE_REFLECTIONS_LF_REFERENCE).getFloatValue();
	//The base delay is the amount we are delaying all delay lines by.
	float baseDelay = 0.003+(1.0f-density)*0.025;
	//Approximate delay line lengths using powers of primes.
	for(int i = 0; i < 16; i+=1) {
		//0, 4, 8, 12, 1, 5, 9, 13...
		int prime= coprimes[(i%4)*4+i/4];
		//use change of base.
		double powerApprox = log(baseDelay*simulation->getSr())/log(prime);
		int neededPower=round(powerApprox);
		double delayInSamples = pow(prime, neededPower);
		double delay=delayInSamples/simulation->getSr();
		delay = std::min(delay, 1.0);
		delays[i] = delay;
	}
	//The following two lines were determined experimentaly, and greatly reduce metallicness.
	//This is probably because, by default, the shortest and longest delay line are adjacent and this node  is typically used with panners at the input and output.
	std::swap(delays[0], delays[15]);
	std::swap(delays[1], delays[14]);
	fdn.setDelays(delays);
	//configure the gains.
	for(int i= 0; i < order; i++) {
		gains[i] = t60ToGain(t60_low, delays[i]);
	}
	//Configure the filters.
	for(int i = 0; i < order; i++) {
		//We get the mid and high t60 gains, and turn them into db.
		double highGain=t60ToGain(t60_high, delays[i]);
		double midGain=t60ToGain(t60, delays[i]);
		double midDb=scalarToDb(midGain, gains[i]);
		double highDb = scalarToDb(highGain, midGain);
		//Careful reading of the audio eq cookbook reveals that when s=1, q is always sqrt(2).
		//We add a very tiny bit to help against numerical error.
		highshelves[i]->configure(Lav_BIQUAD_TYPE_HIGHSHELF, hf_reference, highDb, 1/sqrt(2.0)+1e-4);
		midshelves[i]->configure(Lav_BIQUAD_TYPE_HIGHSHELF, lf_reference, midDb, 1.0/sqrt(2.0)+1e-4);
	}
	//Finally, bake the gains into the fdn matrix:
	hadamard(order, fdn_matrix);
	for(int i=0; i < order; i++) {
		for(int j = 0; j < order; j++) {
			fdn_matrix[i*order+j]*=gains[i];
		}
	}
	fdn.setMatrix(fdn_matrix);
	//Reduce the panning effect.
	//Explanation: the first sample of output should reach all of the 16 outputs at the same time, before degrading normally.
	//This offset basically helps the reflections feel more "centered" when all channels are fed by the source.
	//We add one sample here so that we never have a delay of 0, which reduces some possible compatability issues with delay lines.
	double panReductionDelay = *std::max_element(delays, delays+order)+1.0/simulation->getSr();
	for(int i=0; i < order; i++) {
		double neededDelay = panReductionDelay-delays[i];
		pan_reducers[i]->setDelay(neededDelay);
	}
}
示例#3
0
			Vec2 positionAbsolute() const noexcept final
				{
				if(m_pos_relative)
					{
					Vec2 size(r_rc->surface().width(),r_rc->surface().height());
					return 0.5*hadamard(size,m_pos + Vec2{1,1});
					}
				return m_pos;
				}
示例#4
0
void solve1(ZZ& d_out, vec_ZZ& x_out, const mat_ZZ& A, const vec_ZZ& b)
{
    long n = A.NumRows();

    if (A.NumCols() != n)
        Error("solve1: nonsquare matrix");

    if (b.length() != n)
        Error("solve1: dimension mismatch");

    if (n == 0) {
        set(d_out);
        x_out.SetLength(0);
        return;
    }

    ZZ num_bound, den_bound;

    hadamard(num_bound, den_bound, A, b);

    if (den_bound == 0) {
        clear(d_out);
        return;
    }

    zz_pBak zbak;
    zbak.save();

    long i;
    long j;

    ZZ prod;
    prod = 1;

    mat_zz_p B;


    for (i = 0; ; i++) {
        zz_p::FFTInit(i);

        mat_zz_p AA, BB;
        zz_p dd;

        conv(AA, A);
        inv(dd, BB, AA);

        if (dd != 0) {
            transpose(B, BB);
            break;
        }

        mul(prod, prod, zz_p::modulus());

        if (prod > den_bound) {
            d_out = 0;
            return;
        }
    }

    long max_A_len = MaxBits(A);

    long use_double_mul1 = 0;
    long use_double_mul2 = 0;
    long double_limit = 0;

    if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_DOUBLE_PRECISION-1)
        use_double_mul1 = 1;

    if (!use_double_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_DOUBLE_PRECISION-1) {
        use_double_mul2 = 1;
        double_limit = (1L << (NTL_DOUBLE_PRECISION-1-max_A_len-NTL_SP_NBITS));
    }

    long use_long_mul1 = 0;
    long use_long_mul2 = 0;
    long long_limit = 0;

    if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_BITS_PER_LONG-1)
        use_long_mul1 = 1;

    if (!use_long_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_BITS_PER_LONG-1) {
        use_long_mul2 = 1;
        long_limit = (1L << (NTL_BITS_PER_LONG-1-max_A_len-NTL_SP_NBITS));
    }



    if (use_double_mul1 && use_long_mul1)
        use_long_mul1 = 0;
    else if (use_double_mul1 && use_long_mul2)
        use_long_mul2 = 0;
    else if (use_double_mul2 && use_long_mul1)
        use_double_mul2 = 0;
    else if (use_double_mul2 && use_long_mul2) {
        if (long_limit > double_limit)
            use_double_mul2 = 0;
        else
            use_long_mul2 = 0;
    }


    double **double_A;
    double *double_h;

    typedef double *double_ptr;

    if (use_double_mul1 || use_double_mul2) {
        double_h = NTL_NEW_OP double[n];
        double_A = NTL_NEW_OP double_ptr[n];
        if (!double_h || !double_A) Error("solve1: out of mem");

        for (i = 0; i < n; i++) {
            double_A[i] = NTL_NEW_OP double[n];
            if (!double_A[i]) Error("solve1: out of mem");
        }

        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++)
                double_A[j][i] = to_double(A[i][j]);
    }
示例#5
0
void solve1(ZZ& d_out, vec_ZZ& x_out, const mat_ZZ& A, const vec_ZZ& b)
{
   long n = A.NumRows();

   if (A.NumCols() != n)
      LogicError("solve1: nonsquare matrix");

   if (b.length() != n)
      LogicError("solve1: dimension mismatch");

   if (n == 0) {
      set(d_out);
      x_out.SetLength(0);
      return;
   }

   ZZ num_bound, den_bound;

   hadamard(num_bound, den_bound, A, b);

   if (den_bound == 0) {
      clear(d_out);
      return;
   }

   zz_pBak zbak;
   zbak.save();

   long i;
   long j;

   ZZ prod;
   prod = 1;

   mat_zz_p B;


   for (i = 0; ; i++) {
      zz_p::FFTInit(i);

      mat_zz_p AA, BB;
      zz_p dd;

      conv(AA, A);
      inv(dd, BB, AA);

      if (dd != 0) {
         transpose(B, BB);
         break;
      }

      mul(prod, prod, zz_p::modulus());
      
      if (prod > den_bound) {
         d_out = 0;
         return;
      }
   }

   long max_A_len = MaxBits(A);

   long use_double_mul1 = 0;
   long use_double_mul2 = 0;
   long double_limit = 0;

   if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_DOUBLE_PRECISION-1)
      use_double_mul1 = 1;

   if (!use_double_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_DOUBLE_PRECISION-1) {
      use_double_mul2 = 1;
      double_limit = (1L << (NTL_DOUBLE_PRECISION-1-max_A_len-NTL_SP_NBITS));
   }

   long use_long_mul1 = 0;
   long use_long_mul2 = 0;
   long long_limit = 0;

   if (max_A_len + NTL_SP_NBITS + NumBits(n) <= NTL_BITS_PER_LONG-1)
      use_long_mul1 = 1;

   if (!use_long_mul1 && max_A_len+NTL_SP_NBITS+2 <= NTL_BITS_PER_LONG-1) {
      use_long_mul2 = 1;
      long_limit = (1L << (NTL_BITS_PER_LONG-1-max_A_len-NTL_SP_NBITS));
   }



   if (use_double_mul1 && use_long_mul1)
      use_long_mul1 = 0;
   else if (use_double_mul1 && use_long_mul2)
      use_long_mul2 = 0;
   else if (use_double_mul2 && use_long_mul1)
      use_double_mul2 = 0;
   else if (use_double_mul2 && use_long_mul2) {
      if (long_limit > double_limit)
         use_double_mul2 = 0;
      else
         use_long_mul2 = 0;
   }


   double **double_A=0;
   double *double_h=0;

   Unique2DArray<double> double_A_store;
   UniqueArray<double> double_h_store;


   if (use_double_mul1 || use_double_mul2) {
      double_h_store.SetLength(n);
      double_h = double_h_store.get();

      double_A_store.SetDims(n, n);
      double_A = double_A_store.get();

      for (i = 0; i < n; i++)
         for (j = 0; j < n; j++)
            double_A[j][i] = to_double(A[i][j]);
   }

   long **long_A=0;
   long *long_h=0;

   Unique2DArray<long> long_A_store;
   UniqueArray<long> long_h_store;


   if (use_long_mul1 || use_long_mul2) {
      long_h_store.SetLength(n);
      long_h = long_h_store.get();

      long_A_store.SetDims(n, n);
      long_A = long_A_store.get();

      for (i = 0; i < n; i++)
         for (j = 0; j < n; j++)
            long_A[j][i] = to_long(A[i][j]);
   }


   vec_ZZ x;
   x.SetLength(n);

   vec_zz_p h;
   h.SetLength(n);

   vec_ZZ e;
   e = b;

   vec_zz_p ee;

   vec_ZZ t;
   t.SetLength(n);

   prod = 1;

   ZZ bound1;
   mul(bound1, num_bound, den_bound);
   mul(bound1, bound1, 2);

   while (prod <= bound1) {
      conv(ee, e);

      mul(h, B, ee);

      if (use_double_mul1) {
         for (i = 0; i < n; i++)
            double_h[i] = to_double(rep(h[i]));

         double_MixedMul1(t, double_h, double_A, n);
      }
      else if (use_double_mul2) {
         for (i = 0; i < n; i++)
            double_h[i] = to_double(rep(h[i]));

         double_MixedMul2(t, double_h, double_A, n, double_limit);
      }
      else if (use_long_mul1) {
         for (i = 0; i < n; i++)
            long_h[i] = to_long(rep(h[i]));

         long_MixedMul1(t, long_h, long_A, n);
      }
      else if (use_long_mul2) {
         for (i = 0; i < n; i++)
            long_h[i] = to_long(rep(h[i]));

         long_MixedMul2(t, long_h, long_A, n, long_limit);
      }
      else
         MixedMul(t, h, A); // t = h*A

      SubDiv(e, t, zz_p::modulus()); // e = (e-t)/p
      MulAdd(x, prod, h);  // x = x + prod*h

      mul(prod, prod, zz_p::modulus());
   }

   vec_ZZ num, denom;
   ZZ d, d_mod_prod, tmp1;

   num.SetLength(n);
   denom.SetLength(n);
 
   d = 1;
   d_mod_prod = 1;

   for (i = 0; i < n; i++) {
      rem(x[i], x[i], prod);
      MulMod(x[i], x[i], d_mod_prod, prod);

      if (!ReconstructRational(num[i], denom[i], x[i], prod, 
           num_bound, den_bound))
          LogicError("solve1 internal error: rat recon failed!");

      mul(d, d, denom[i]);

      if (i != n-1) {
         if (denom[i] != 1) {
            div(den_bound, den_bound, denom[i]); 
            mul(bound1, num_bound, den_bound);
            mul(bound1, bound1, 2);

            div(tmp1, prod, zz_p::modulus());
            while (tmp1 > bound1) {
               prod = tmp1;
               div(tmp1, prod, zz_p::modulus());
            }

            rem(tmp1, denom[i], prod);
            rem(d_mod_prod, d_mod_prod, prod);
            MulMod(d_mod_prod, d_mod_prod, tmp1, prod);
         }
      }
   }

   tmp1 = 1;
   for (i = n-1; i >= 0; i--) {
      mul(num[i], num[i], tmp1);
      mul(tmp1, tmp1, denom[i]);
   }
   
   x_out.SetLength(n);

   for (i = 0; i < n; i++) {
      x_out[i] = num[i];
   }

   d_out = d;
}