Exemple #1
0
static void new_spread_dir(t_rvbap *x, t_float spreaddir[3], t_float vscartdir[3], t_float spread_base[3])
// subroutine for spreading
{
    t_float beta,m_gamma;
    t_float a,b;
    t_float pi = 3.141592653589793;
    t_float power;
    
    m_gamma = acos(vscartdir[0] * spread_base[0] +
                    vscartdir[1] * spread_base[1] +
                    vscartdir[2] * spread_base[2])/pi*180;
    if(fabs(m_gamma) < 1){
        angle_to_cart(x->x_azi+90, 0, spread_base);
        m_gamma = acos(vscartdir[0] * spread_base[0] +
                    vscartdir[1] * spread_base[1] +
                    vscartdir[2] * spread_base[2])/pi*180;
    }
    beta = 180 - m_gamma;
    b=sin(x->x_spread * pi / 180) / sin(beta * pi / 180);
    a=sin((180- x->x_spread - beta) * pi / 180) / sin (beta * pi / 180);
    spreaddir[0] = a * vscartdir[0] + b * spread_base[0];
    spreaddir[1] = a * vscartdir[1] + b * spread_base[1];
    spreaddir[2] = a * vscartdir[2] + b * spread_base[2];
    
    power=sqrt(spreaddir[0]*spreaddir[0] + spreaddir[1]*spreaddir[1] 
                + spreaddir[2]*spreaddir[2]);
    spreaddir[0] /= power;
    spreaddir[1] /= power;
    spreaddir[2] /= power;
}
Exemple #2
0
void vbap(double gains[MAX_CHANNELS], LS_DATA *ls_data, int azi, int ele) 
{
  /* calculates gain factors using loudspeaker setup and given direction */
  double *cartdir;
  double power;
  int i,j,k;
  double small_g;
  double big_sm_g, gtmp[3];
  int winner_triplet;
  int ls[3];
  double g[3];

  cartdir=angle_to_cart(azi,ele);  
  big_sm_g = -100000.0;
  for(i=0;i<ls_data->triplet_amount;i++){
    small_g = 10000000.0;
    for(j=0;j<ls_data->dimension;j++){
      gtmp[j]=0.0;
      for(k=0;k<ls_data->dimension;k++)
	gtmp[j]+=cartdir[k]*ls_data->lsm[i][k+j*ls_data->dimension]; 
      if(gtmp[j] < small_g){
	small_g = gtmp[j];
      }
    }
    if(small_g > big_sm_g){
      big_sm_g = small_g;
      winner_triplet=i;
      g[0]=gtmp[0]; g[1]=gtmp[1]; 
      ls[0]=ls_data->lstripl[i][0]; ls[1]=ls_data->lstripl[i][1]; 
      if(ls_data->dimension==3){
	g[2]=gtmp[2];
	ls[2]=ls_data->lstripl[i][2];
      } else {
	g[2]=0.0;
	ls[2]=1;
      }
    }
  }

  power=sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]);
  g[0] /= power; 
  g[1] /= power;
  g[2] /= power;

  for(i=0;i<MAX_CHANNELS;i++){
    gains[i]=0.0;
  }
  gains[ls[0]-1]=g[0];
  gains[ls[1]-1]=g[1];
  if(ls_data->dimension==3){
    gains[ls[2]-1]=g[2];
  }
  free(cartdir);
}
Exemple #3
0
static void equal_reverb(t_rvbap *x, t_float *final_gs)
// calculate constant reverb gains for equally distributed
// reverb levels
// this is achieved by calculating gains for a sound source 
// that is everywhere, i.e. present in all directions

{
    t_float vscartdir[3];
    t_float spreaddir[16][3];
    t_float spreadbase[16][3];
    long i, spreaddirnum;
    t_float power;
    if(x->x_dimension == 3){
        spreaddirnum=5;     
        
        // horizontal plane
        angle_to_cart(90, 0, spreaddir[0]);
        angle_to_cart(180, 0, spreaddir[1]);
        angle_to_cart(270, 0, spreaddir[2]);
        
        // above, below
        angle_to_cart(0, 90, spreaddir[3]);
        angle_to_cart(0, -90, spreaddir[4]);
        
        for(i=1;i<spreaddirnum;i++){
            additive_vbap(x->x_reverb_gs,spreaddir[i],x); 
        }
    } else if (x->x_dimension == 2) {
        // for 2-D we claculate virtual sources 
        // every 45 degrees in a horizontal plane
        spreaddirnum=7;     
        
        angle_to_cart(90, 0, spreaddir[0]);
        angle_to_cart(180, 0, spreaddir[1]);
        angle_to_cart(270, 0, spreaddir[2]);
        angle_to_cart(45, 0, spreaddir[3]);
        angle_to_cart(135, 0, spreaddir[4]);
        angle_to_cart(225, 0, spreaddir[5]);
        angle_to_cart(315, 0, spreaddir[6]);
        
        for(i=0;i<spreaddirnum;i++)
            additive_vbap(x->x_reverb_gs,spreaddir[i],x); 
    } else
        return;
        
    for(i=0,power=0.0;i<x->x_ls_amount;i++){
        power += x->x_reverb_gs[i] * x->x_reverb_gs[i];
    }
        
    power = sqrt(power);
    for(i=0;i<x->x_ls_amount;i++){
        final_gs[i] /= power;
    }
}   
Exemple #4
0
static void spread_it(t_rvbap *x, t_float *final_gs)
// apply the sound signal to multiple panning directions
// that causes some spreading.
// See theory in paper V. Pulkki "Uniform spreading of amplitude panned
// virtual sources" in WASPAA 99

{
    t_float vscartdir[3];
    t_float spreaddir[16][3];
    t_float spreadbase[16][3];
    long i, spreaddirnum;
    t_float power;
    if(x->x_dimension == 3){
        spreaddirnum=16;
        angle_to_cart(x->x_azi,x->x_ele,vscartdir);
        new_spread_dir(x, spreaddir[0], vscartdir, x->x_spread_base);
        new_spread_base(x, spreaddir[0], vscartdir);
        cross_prod(x->x_spread_base, vscartdir, spreadbase[1]); // four orthogonal dirs
        cross_prod(spreadbase[1], vscartdir, spreadbase[2]);
        cross_prod(spreadbase[2], vscartdir, spreadbase[3]);
    
        // four between them
        for(i=0;i<3;i++) spreadbase[4][i] =  (x->x_spread_base[i] + spreadbase[1][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[5][i] =  (spreadbase[1][i] + spreadbase[2][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[6][i] =  (spreadbase[2][i] + spreadbase[3][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[7][i] =  (spreadbase[3][i] + x->x_spread_base[i]) / 2.0;
        
        // four at half spreadangle
        for(i=0;i<3;i++) spreadbase[8][i] =  (vscartdir[i] + x->x_spread_base[i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[9][i] =  (vscartdir[i] + spreadbase[1][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[10][i] =  (vscartdir[i] + spreadbase[2][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[11][i] =  (vscartdir[i] + spreadbase[3][i]) / 2.0;
        
        // four at quarter spreadangle
        for(i=0;i<3;i++) spreadbase[12][i] =  (vscartdir[i] + spreadbase[8][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[13][i] =  (vscartdir[i] + spreadbase[9][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[14][i] =  (vscartdir[i] + spreadbase[10][i]) / 2.0;
        for(i=0;i<3;i++) spreadbase[15][i] =  (vscartdir[i] + spreadbase[11][i]) / 2.0;
        
        additive_vbap(final_gs,spreaddir[0],x); 
        for(i=1;i<spreaddirnum;i++){
            new_spread_dir(x, spreaddir[i], vscartdir, spreadbase[i]);
            additive_vbap(final_gs,spreaddir[i],x); 
        }
    } else if (x->x_dimension == 2) {
        spreaddirnum=6;     
        
        angle_to_cart(x->x_azi - x->x_spread, 0, spreaddir[0]);
        angle_to_cart(x->x_azi - x->x_spread/2, 0, spreaddir[1]);
        angle_to_cart(x->x_azi - x->x_spread/4, 0, spreaddir[2]);
        angle_to_cart(x->x_azi + x->x_spread/4, 0, spreaddir[3]);
        angle_to_cart(x->x_azi + x->x_spread/2, 0, spreaddir[4]);
        angle_to_cart(x->x_azi + x->x_spread, 0, spreaddir[5]);
        
        for(i=0;i<spreaddirnum;i++)
            additive_vbap(final_gs,spreaddir[i],x); 
    } else
        return;
        
    if(x->x_spread > 70)
        for(i=0;i<x->x_ls_amount;i++){
            final_gs[i] += (x->x_spread - 70) / 30.0 * (x->x_spread - 70) / 30.0 * 10.0;
        }
    
    for(i=0,power=0.0;i<x->x_ls_amount;i++){
        power += final_gs[i] * final_gs[i];
    }
        
    power = sqrt(power);
    for(i=0;i<x->x_ls_amount;i++){
        final_gs[i] /= power;
    }
}   
Exemple #5
0
static void vbap(t_float g[3], long ls[3], t_rvbap *x)
{
  /* calculates gain factors using loudspeaker setup and given direction */
  t_float power;
  int i,j,k, gains_modified;
  t_float small_g;
  t_float big_sm_g, gtmp[3];
  long winner_set=0;
  t_float cartdir[3];
  t_float new_cartdir[3];
  t_float new_angle_dir[3];
  long dim = x->x_dimension;
  long neg_g_am, best_neg_g_am;
  
  // transfering the azimuth angle to a decent value
  while(x->x_azi > 180)
    x->x_azi -= 360;
  while(x->x_azi < -179)
    x->x_azi += 360;
    
  // transferring the elevation to a decent value
  if(dim == 3){
    while(x->x_ele > 180)
        x->x_ele -= 360;
    while(x->x_ele < -179)
        x->x_ele += 360;
  } else
    x->x_ele = 0;
  
  
  // go through all defined loudspeaker sets and find the set which
  // has all positive values. If such is not found, set with largest
  // minimum value is chosen. If at least one of gain factors of one LS set is negative
  // it means that the virtual source does not lie in that LS set. 
  
  angle_to_cart(x->x_azi,x->x_ele,cartdir);
  big_sm_g = -100000.0;   // initial value for largest minimum gain value
  best_neg_g_am=3;        // how many negative values in this set
  
  
  for(i=0;i<x->x_lsset_amount;i++){
    small_g = 10000000.0;
    neg_g_am = 3;
    for(j=0;j<dim;j++){
      gtmp[j]=0.0;
      for(k=0;k<dim;k++)
        gtmp[j]+=cartdir[k]* x->x_set_inv_matx[i][k+j*dim];
      if(gtmp[j] < small_g)
        small_g = gtmp[j];
      if(gtmp[j]>= -0.01)
        neg_g_am--;
    }
    if(small_g > big_sm_g && neg_g_am <= best_neg_g_am){
      big_sm_g = small_g;
      best_neg_g_am = neg_g_am; 
      winner_set=i;
      g[0]=gtmp[0]; g[1]=gtmp[1];
      ls[0]= x->x_lsset[i][0]; ls[1]= x->x_lsset[i][1];
      if(dim==3){
        g[2]=gtmp[2];
        ls[2]= x->x_lsset[i][2];
      } else {
        g[2]=0.0;
        ls[2]=0;
      }
    }
  }
  
  // If chosen set produced a negative value, make it zero and
  // calculate direction that corresponds  to these new
  // gain values. This happens when the virtual source is outside of
  // all loudspeaker sets. 
  
  if(dim==3){
    gains_modified=0;
    for(i=0;i<dim;i++)
        if(g[i]<-0.01){
            g[i]=0.0001;
            gains_modified=1;
        }   
    if(gains_modified==1){
        new_cartdir[0] =  x->x_set_matx[winner_set][0] * g[0] 
                        + x->x_set_matx[winner_set][1] * g[1]
                        + x->x_set_matx[winner_set][2] * g[2];
        new_cartdir[1] =  x->x_set_matx[winner_set][3] * g[0] 
                        + x->x_set_matx[winner_set][4] * g[1] 
                        + x->x_set_matx[winner_set][5] * g[2];
        new_cartdir[2] =  x->x_set_matx[winner_set][6] * g[0] 
                        + x->x_set_matx[winner_set][7] * g[1]
                        + x->x_set_matx[winner_set][8] * g[2];
        cart_to_angle(new_cartdir,new_angle_dir);
        x->x_azi = (long) (new_angle_dir[0] + 0.5);
        x->x_ele = (long) (new_angle_dir[1] + 0.5);
     }
  }
  
  power=sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]);
  g[0] /= power;
  g[1] /= power;
  g[2] /= power;
}
Exemple #6
0
int vbap_zak_control(CSOUND *csound, VBAP_ZAK *p)
{
    CART_VEC spreaddir[16];
    CART_VEC spreadbase[16];
    ANG_VEC atmp;
    int32 i,j, spreaddirnum;
    int n = p->n;
    MYFLT tmp_gains[MAXCHNLS],sum = FL(0.0);
    if (UNLIKELY(p->dim == 2 && fabs(*p->ele) > 0.0)) {
      csound->Warning(csound,
                      Str("Warning: truncating elevation to 2-D plane\n"));
      *p->ele = FL(0.0);
    }
    if (*p->spread <FL(0.0))
      *p->spread=FL(0.0);
    else if (*p->spread >FL(100.0))
      *p->spread=FL(100.0);
    /* Current panning angles */
    p->ang_dir.azi = (MYFLT) *p->azi;
    p->ang_dir.ele = (MYFLT) *p->ele;
    p->ang_dir.length = FL(1.0);
    angle_to_cart(p->ang_dir, &(p->cart_dir));
    calc_vbap_gns(p->ls_set_am, p->dim,  p->ls_sets,
                  p->updated_gains, n, p->cart_dir);

    /* Calculated gain factors of a spreaded virtual source */
    if (*p->spread > FL(0.0)) {
      if (p->dim == 3) {
        spreaddirnum=16;
        /* four orthogonal dirs */
        new_spread_dir(&spreaddir[0], p->cart_dir,
                       p->spread_base, *p->azi, *p->spread);
        new_spread_base(spreaddir[0], p->cart_dir,*p->spread, &p->spread_base);
        cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]);
        cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]);
        cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]);
        /* four between them */
        vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]);
        vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]);
        vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]);
        vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]);

        /* four at half spreadangle */
        vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]);
        vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]);
        vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]);
        vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]);

        /* four at quarter spreadangle */
        vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]);
        vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]);
        vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]);
        vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]);

        for (i=1;i<spreaddirnum;i++) {
          new_spread_dir(&spreaddir[i], p->cart_dir,
                         spreadbase[i],*p->azi,*p->spread);
          calc_vbap_gns(p->ls_set_am, p->dim,  p->ls_sets,
                        tmp_gains, n, spreaddir[i]);
          for (j=0;j<n;j++) {
            p->updated_gains[j] += tmp_gains[j];
          }
        }
      }
      else if (p->dim == 2) {
        spreaddirnum = 6;
        atmp.ele = FL(0.0);
        atmp.azi = *p->azi - *p->spread;
        angle_to_cart(atmp, &spreaddir[0]);
        atmp.azi = *p->azi - *p->spread/2;
        angle_to_cart(atmp, &spreaddir[1]);
        atmp.azi = *p->azi - *p->spread/4;
        angle_to_cart(atmp, &spreaddir[2]);
        atmp.azi = *p->azi + *p->spread/4;
        angle_to_cart(atmp, &spreaddir[3]);
        atmp.azi = *p->azi + *p->spread/2;
        angle_to_cart(atmp, &spreaddir[4]);
        atmp.azi = *p->azi + *p->spread;
        angle_to_cart(atmp, &spreaddir[5]);

        for (i=0;i<spreaddirnum;i++) {
          calc_vbap_gns(p->ls_set_am, p->dim,  p->ls_sets,
                        tmp_gains, n, spreaddir[i]);
          for (j=0;j<n;j++) {
            p->updated_gains[j] += tmp_gains[j];
          }
        }
      }
    }
    if (*p->spread > FL(70.0))
      for (i=0;i<n ;i++) {
        p->updated_gains[i] +=(*p->spread - FL(70.0))/FL(30.0) *
          (*p->spread - FL(70.0))/FL(30.0)*FL(20.0);
      }

    /* normalization */
    for (i=0;i<n;i++) {
      sum = sum+(p->updated_gains[i]*p->updated_gains[i]);
    }

    sum = SQRT(sum);
    for (i=0;i<n;i++) {
      p->updated_gains[i] /= sum;
    }
    return OK;
}
Exemple #7
0
int vbap_zak_moving_init(CSOUND *csound, VBAP_ZAK_MOVING *p)
{
    int     i, j, indx;
    MYFLT   *ls_table, *ptr;
    LS_SET  *ls_set_ptr;
    int n = p->n;
    p->n = (int)MYFLT2LONG(*p->numb); /* Set size */
    /* Check to see this index is within the limits of za space.    */
    indx = (int32) *p->ndx;
    if (UNLIKELY(indx > csound->zalast)) {
      return csound->PerfError(csound, p->h.insdshead,
                               Str("outz index > isizea. No output"));
    }
    else if (UNLIKELY(indx < 0)) {
      return csound->PerfError(csound, p->h.insdshead,
                               Str("outz index < 0. No output."));
    }
    /* Now read from the array in za space and write to the output. */
    p->out_array     = csound->zastart + (indx * CS_KSMPS);/* outputs */
    csound->AuxAlloc(csound, p->n*sizeof(MYFLT)*4, &p->auxch);
    p->curr_gains    = (MYFLT*)p->auxch.auxp;
    p->beg_gains     = p->curr_gains + p->n;
    p->end_gains     = p->beg_gains + p->n;
    p->updated_gains = p->end_gains + p->n;
    /* reading in loudspeaker info */
    ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound,
                                                        "vbap_ls_table_0"));
    p->dim           = (int) ls_table[0];
    p->ls_am         = (int) ls_table[1];
    p->ls_set_am     = (int) ls_table[2];
    ptr              = &(ls_table[3]);
    csound->AuxAlloc(csound, p->ls_set_am * sizeof (LS_SET), &p->aux);
    if (UNLIKELY(p->aux.auxp == NULL)) {
      return csound->InitError(csound, Str("could not allocate memory"));
    }
    p->ls_sets = (LS_SET*) p->aux.auxp;
    ls_set_ptr = p->ls_sets;
    for (i=0 ; i < p->ls_set_am ; i++) {
      ls_set_ptr[i].ls_nos[2] = 0;     /* initial setting */
      for (j=0 ; j < p->dim ; j++) {
        ls_set_ptr[i].ls_nos[j] = (int) *(ptr++);
      }
      for (j=0 ; j < 9; j++)
        ls_set_ptr[i].ls_mx[j] = FL(0.0);  /* initial setting */
      for (j=0 ; j < (p->dim) * (p->dim); j++) {
        ls_set_ptr[i].ls_mx[j] = (MYFLT) *(ptr++);
      }
    }

    /* other initialization */
    p->ele_vel = FL(1.0);    /* functions specific to movement */
    if (UNLIKELY(fabs(*p->field_am) < (2+ (p->dim - 2)*2))) {
      return csound->InitError(csound,
                  Str("Have to have at least %d directions in vbapzmove"),
                  2 + (p->dim - 2) * 2);
    }
    if (p->dim == 2)
      p->point_change_interval = (int) (CS_EKR * *p->dur
                                        / (fabs(*p->field_am) - 1.0));
    else if (LIKELY(p->dim == 3))
      p->point_change_interval = (int) (CS_EKR * *p->dur
                                        / (fabs(*p->field_am) * 0.5 - 1.0));
    else
      return csound->InitError(csound, Str("Wrong dimension"));
    p->point_change_counter = 0;
    p->curr_fld = 0;
    p->next_fld = 1;
    p->ang_dir.azi = *p->fld[0];
    if (p->dim == 3) {
      p->ang_dir.ele = *p->fld[1];
    } else {
      p->ang_dir.ele = FL(0.0);
    }
    if (p->dim == 3) {
      p->curr_fld = 1;
      p->next_fld = 2;
    }
    angle_to_cart(p->ang_dir, &(p->cart_dir));
    p->spread_base.x = p->cart_dir.y;
    p->spread_base.y = p->cart_dir.z;
    p->spread_base.z = -p->cart_dir.x;
    vbap_zak_moving_control(csound,p);
    for (i=0;i<n;i++) {
      p->beg_gains[i] = p->updated_gains[i];
      p->end_gains[i] = p->updated_gains[i];
    }
    return OK;
}
Exemple #8
0
int vbap_zak_moving_control(CSOUND *csound, VBAP_ZAK_MOVING *p)
{
    CART_VEC spreaddir[16];
    CART_VEC spreadbase[16];
    ANG_VEC atmp;
    int32 i,j, spreaddirnum;
    int n = p->n;
    CART_VEC tmp1, tmp2, tmp3;
    MYFLT coeff, angle;
    MYFLT tmp_gains[MAXCHNLS],sum = FL(0.0); /* Array long enough */
    if (UNLIKELY(p->dim == 2 && fabs(p->ang_dir.ele) > 0.0)) {
      csound->Warning(csound,
                      Str("Warning: truncating elevation to 2-D plane\n"));
      p->ang_dir.ele = FL(0.0);
    }

    if (*p->spread <FL(0.0))
      *p->spread = FL(0.0);
    else if (*p->spread >FL(100.0))
      *p->spread = FL(100.0);
    if (p->point_change_counter++ >= p->point_change_interval) {
      p->point_change_counter = 0;
      p->curr_fld = p->next_fld;
      if (++p->next_fld >= (int) fabs(*p->field_am)) {
        if (*p->field_am >= FL(0.0)) /* point-to-point */
          p->next_fld = 0;
        else
          p->next_fld = 1;
      }
      if (p->dim == 3) { /* jumping over second field */
        p->curr_fld = p->next_fld;
        if (++p->next_fld >= ((int) fabs(*p->field_am))) {
          if (*p->field_am >= FL(0.0)) /* point-to-point */
            p->next_fld = 0;
          else
            p->next_fld = 1;
        }
      }
      if (UNLIKELY((p->fld[abs(p->next_fld)]==NULL)))
        return csound->PerfError(csound, p->h.insdshead,
                                 Str("Missing fields in vbapzmove\n"));
      if (*p->field_am >= FL(0.0) && p->dim == 2) /* point-to-point */
        if (UNLIKELY(fabs(fabs(*p->fld[p->next_fld] - *p->fld[p->curr_fld])
                          - 180.0) < 1.0))
          csound->Warning(csound,
                          Str("Warning: Ambiguous transition 180 degrees.\n"));
    }
    if (*p->field_am >= FL(0.0)) { /* point-to-point */
      if (p->dim == 3) { /* 3-D */
        p->prev_ang_dir.azi =  *p->fld[p->curr_fld-1];
        p->next_ang_dir.azi =  *p->fld[p->next_fld];
        p->prev_ang_dir.ele = *p->fld[p->curr_fld];
        p->next_ang_dir.ele = *p->fld[p->next_fld+1];
        coeff = ((MYFLT) p->point_change_counter) /
          ((MYFLT) p->point_change_interval);
        angle_to_cart( p->prev_ang_dir,&tmp1);
        angle_to_cart( p->next_ang_dir,&tmp2);
        tmp3.x = (FL(1.0)-coeff) * tmp1.x + coeff * tmp2.x;
        tmp3.y = (FL(1.0)-coeff) * tmp1.y + coeff * tmp2.y;
        tmp3.z = (FL(1.0)-coeff) * tmp1.z + coeff * tmp2.z;
        coeff = (MYFLT)sqrt((double)(tmp3.x * tmp3.x +
                                     tmp3.y * tmp3.y +
                                     tmp3.z * tmp3.z));
        tmp3.x /= coeff; tmp3.y /= coeff; tmp3.z /= coeff;
        cart_to_angle(tmp3,&(p->ang_dir));
      }
      else if (p->dim == 2) { /* 2-D */
        p->prev_ang_dir.azi =  *p->fld[p->curr_fld];
        p->next_ang_dir.azi =  *p->fld[p->next_fld ];
        p->prev_ang_dir.ele = p->next_ang_dir.ele =  FL(0.0);
        scale_angles(&(p->prev_ang_dir));
        scale_angles(&(p->next_ang_dir));
        angle = (p->prev_ang_dir.azi - p->next_ang_dir.azi);
        while(angle > FL(180.0))
          angle -= FL(360.0);
        while(angle < -FL(180.0))
          angle += FL(360.0);
        coeff = ((MYFLT) p->point_change_counter) /
          ((MYFLT) p->point_change_interval);
        angle  *=  (coeff);
        p->ang_dir.azi = p->prev_ang_dir.azi -  angle;
        p->ang_dir.ele = FL(0.0);
      }
      else {
        return csound->PerfError(csound, p->h.insdshead,
                                 Str("Missing fields in vbapzmove\n"));
      }
    }
    else { /* angular velocities */
      if (p->dim == 2) {
        p->ang_dir.azi = p->ang_dir.azi +
          (*p->fld[p->next_fld] * CS_ONEDKR);
        scale_angles(&(p->ang_dir));
      }
      else { /* 3D angular */
        p->ang_dir.azi = p->ang_dir.azi +
          (*p->fld[p->next_fld] * CS_ONEDKR);
        p->ang_dir.ele = p->ang_dir.ele +
          p->ele_vel * (*p->fld[p->next_fld+1] * CS_ONEDKR);
        if (p->ang_dir.ele > FL(90.0)) {
          p->ang_dir.ele = FL(90.0);
          p->ele_vel = -p->ele_vel;
        }
        if (p->ang_dir.ele < FL(0.0)) {
          p->ang_dir.ele = FL(0.0);
          p->ele_vel =  -p->ele_vel;
        }
        scale_angles(&(p->ang_dir));
      }
    }
    angle_to_cart(p->ang_dir, &(p->cart_dir));
    calc_vbap_gns(p->ls_set_am, p->dim,  p->ls_sets,
                  p->updated_gains, n, p->cart_dir);
    if (*p->spread > FL(0.0)) {
      if (p->dim == 3) {
        spreaddirnum=16;
        /* four orthogonal dirs */
        new_spread_dir(&spreaddir[0], p->cart_dir,
                       p->spread_base, p->ang_dir.azi, *p->spread);

        new_spread_base(spreaddir[0], p->cart_dir,*p->spread, &p->spread_base);
        cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]);
        cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]);
        cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]);
        /* four between them */
        vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]);
        vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]);
        vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]);
        vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]);

        /* four at half spreadangle */
        vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]);
        vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]);
        vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]);
        vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]);

        /* four at quarter spreadangle */
        vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]);
        vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]);
        vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]);
        vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]);

        for (i=1;i<spreaddirnum;i++) {
          new_spread_dir(&spreaddir[i], p->cart_dir,
                         spreadbase[i],p->ang_dir.azi,*p->spread);
          calc_vbap_gns(p->ls_set_am, p->dim,  p->ls_sets,
                        tmp_gains, n, spreaddir[i]);
          for (j=0;j<n;j++) {
            p->updated_gains[j] += tmp_gains[j];
          }
        }
      }
      else if (p->dim == 2) {
        spreaddirnum=6;
        atmp.ele=FL(0.0);
        atmp.azi=p->ang_dir.azi - *p->spread;
        angle_to_cart(atmp, &spreaddir[0]);
        atmp.azi=p->ang_dir.azi - *p->spread/2;
        angle_to_cart(atmp, &spreaddir[1]);
        atmp.azi=p->ang_dir.azi - *p->spread/4;
        angle_to_cart(atmp, &spreaddir[2]);
        atmp.azi=p->ang_dir.azi + *p->spread/4;
        angle_to_cart(atmp, &spreaddir[3]);
        atmp.azi=p->ang_dir.azi + *p->spread/2;
        angle_to_cart(atmp, &spreaddir[4]);
        atmp.azi=p->ang_dir.azi + *p->spread;
        angle_to_cart(atmp, &spreaddir[5]);

        for (i=0;i<spreaddirnum;i++) {
          calc_vbap_gns(p->ls_set_am, p->dim,  p->ls_sets,
                        tmp_gains, n, spreaddir[i]);
          for (j=0;j<n;j++) {
            p->updated_gains[j] += tmp_gains[j];
          }
        }
      }
    }
    if (*p->spread > FL(70.0))
      for (i=0;i<n ;i++) {
        p->updated_gains[i] += (*p->spread - FL(70.0))/FL(30.0) *
          (*p->spread - FL(70.0))/FL(30.0)*FL(10.0);
      }
    /* normalization */
    for (i=0;i<n;i++) {
      sum += (p->updated_gains[i]*p->updated_gains[i]);
  }

  sum = SQRT(sum);
  for (i=0;i<n;i++) {
    p->updated_gains[i] /= sum;
  }
  return OK;
}
Exemple #9
0
int vbap_zak_init(CSOUND *csound, VBAP_ZAK *p)
{                               /* Initializations before run time */
    int     i, j, indx;
    MYFLT   *ls_table, *ptr; /* , *gains; */
    LS_SET  *ls_set_ptr;
    int n = p->n = (int)MYFLT2LONG(*p->numb); /* Set size */
    char name[24];
    /* Check to see this index is within the limits of za space.    */
    indx = (int32) *p->ndx;
    if (UNLIKELY(indx > csound->zalast)) {
      return csound->PerfError(csound, p->h.insdshead,
                               Str("outz index > isizea. No output"));
    }
    else if (UNLIKELY(indx < 0)) {
      return csound->PerfError(csound, p->h.insdshead,
                               Str("outz index < 0. No output."));
    }
    if ((int)*p->layout==0) strcpy(name, "vbap_ls_table");
    else snprintf(name, 24, "vbap_ls_table_%d", (int)*p->layout==0);
    /* Now read from the array in za space and write to the output. */
    p->out_array     = csound->zastart + (indx * CS_KSMPS);/* outputs */
    csound->AuxAlloc(csound, p->n*sizeof(MYFLT)*4, &p->auxch);
    p->curr_gains    = (MYFLT*)p->auxch.auxp;
    p->beg_gains     = p->curr_gains + p->n;
    p->end_gains     = p->beg_gains + p->n;
    p->updated_gains = p->end_gains + p->n;
    ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, name));
    p->dim           = (int) ls_table[0];   /* reading in loudspeaker info */
    p->ls_am         = (int) ls_table[1];
    p->ls_set_am     = (int) ls_table[2];
    ptr              = &(ls_table[3]);
    csound->AuxAlloc(csound, p->ls_set_am * sizeof (LS_SET), &p->aux);
    if (UNLIKELY(p->aux.auxp == NULL)) {
      return csound->InitError(csound, Str("could not allocate memory"));
    }
    p->ls_sets = (LS_SET*) p->aux.auxp;
    ls_set_ptr = p->ls_sets;
    for (i=0 ; i < p->ls_set_am ; i++) {
      ls_set_ptr[i].ls_nos[2] = 0;     /* initial setting */
      for (j=0 ; j < p->dim ; j++) {
        ls_set_ptr[i].ls_nos[j] = (int) *(ptr++);
      }
      for (j=0 ; j < 9; j++)
        ls_set_ptr[i].ls_mx[j] = FL(0.0);  /* initial setting */
      for (j=0 ; j < (p->dim) * (p->dim); j++) {
        ls_set_ptr[i].ls_mx[j] = (MYFLT) *(ptr++);
      }
    }

    /* other initialization */
    if (UNLIKELY(p->dim == 2 && fabs(*p->ele) > 0.0)) {
      csound->Warning(csound,
                      Str("Warning: truncating elevation to 2-D plane\n"));
      *p->ele = FL(0.0);
    }
    p->ang_dir.azi = (MYFLT) *p->azi;
    p->ang_dir.ele = (MYFLT) *p->ele;
    p->ang_dir.length = FL(1.0);
    angle_to_cart(p->ang_dir, &(p->cart_dir));
    p->spread_base.x = p->cart_dir.y;
    p->spread_base.y = p->cart_dir.z;
    p->spread_base.z = -p->cart_dir.x;
    vbap_zak_control(csound,p);
    for (i=0;i<n;i++) {
      p->beg_gains[i] = p->updated_gains[i];
      p->end_gains[i] = p->updated_gains[i];
    }
    return OK;
}