Ejemplo n.º 1
0
void compute_curve(VorbisPsy *psy, float *audio, float *curve)
{
   int i;
   float work[psy->n];

   float scale=4.f/psy->n;
   float scale_dB;

   scale_dB=todB(scale);
  
   /* window the PCM data; use a BH4 window, not vorbis */
   for(i=0;i<psy->n;i++)
     work[i]=audio[i] * psy->window[i];

   {
     static int seq=0;
     
     //_analysis_output("win",seq,work,psy->n,0,0);

     seq++;
   }

    /* FFT yields more accurate tonal estimation (not phase sensitive) */
    spx_drft_forward(&psy->lookup,work);

    /* magnitudes */
    work[0]=scale_dB+todB(work[0]);
    for(i=1;i<psy->n-1;i+=2){
      float temp = work[i]*work[i] + work[i+1]*work[i+1];
      work[(i+1)>>1] = scale_dB+.5f * todB(temp);
    }

    /* derive a noise curve */
    _vp_noisemask(psy,work,curve);
#define SIDEL 12
    for (i=0;i<SIDEL;i++)
    {
       curve[i]=curve[SIDEL];
    }
#define SIDEH 12
    for (i=0;i<SIDEH;i++)
    {
       curve[(psy->n>>1)-i-1]=curve[(psy->n>>1)-SIDEH];
    }
    for(i=0;i<((psy->n)>>1);i++)
       curve[i] = fromdB(1.2*curve[i]+.2*i);
       //curve[i] = fromdB(0.8*curve[i]+.35*i);
       //curve[i] = fromdB(0.9*curve[i])*pow(1.0*i+45,1.3);
}
Ejemplo n.º 2
0
/* called only by playback thread */
time_linkage *mix_read(time_linkage *in, 
		       time_linkage *inA,  // reverb channel 
		       time_linkage *inB){ // reverb channel

  int i,j,k,outch=ms.out.channels;  
  int outactive[outch];

  float peak[MIX_BLOCKS+5][input_ch];
  float rms[MIX_BLOCKS+5][input_ch];
  int bypass=1;

  if(in->samples==0){
    ms.out.samples=0;
    return &ms.out;
  }
  memset(outactive,0,sizeof(outactive));
  memset(peak,0,sizeof(peak));
  memset(rms,0,sizeof(rms));

  /* eliminate asynch change possibility */
  memcpy(ms.curr,mix_set,sizeof(*mix_set)*input_ch);

  /* fillstate here is only used for lazy initialization/reset */
  if(ms.fillstate==0){
    /* zero the cache */
    for(i=0;i<input_ch;i++){
      memset(ms.cacheP[i],0,sizeof(**ms.cacheP)*input_size);
      memset(ms.cachePP[i],0,sizeof(**ms.cachePP)*input_size);
      memset(ms.cachePA[i],0,sizeof(**ms.cachePA)*input_size);
      memset(ms.cachePPA[i],0,sizeof(**ms.cachePPA)*input_size);
      memset(ms.cachePB[i],0,sizeof(**ms.cachePB)*input_size);
      memset(ms.cachePPB[i],0,sizeof(**ms.cachePPB)*input_size);
    }
    memcpy(ms.prev,ms.curr,sizeof(*mix_set)*input_ch);
    ms.fillstate=1;
  }

  /* zero the output block; we'll me mixing into it input-by-input */
  for(i=0;i<outch;i++)
    memset(ms.out.data[i],0,sizeof(**ms.out.data)*input_size);

  /* a bit of laziness that may actually save CPU time by avoiding
     special-cases later */
  for(i=0;i<input_ch;i++){
    if(mute_channel_muted(in->active,i))
      memset(in->data[i],0,sizeof(**in->data)*input_size);
    if(mute_channel_muted(inA->active,i))
      memset(inA->data[i],0,sizeof(**inA->data)*input_size);
    if(mute_channel_muted(inB->active,i))
      memset(inB->data[i],0,sizeof(**inB->data)*input_size);
  }

    /* input-by-input */
  for(i=0;i<input_ch;i++){
    int feedit=mixpanel_visible[i];
    int feeditM=atten_visible;

    /* master feedback is a bit of a pain; the metrics we need aren't
       produced by any of the mixdowns below. Do it by hand */
    if(feeditM){
      float mix[input_size];
      float att=fromdB(ms.curr[i].master_att * .1);
      int del=rint(ms.curr[i].master_delay*.00001*input_rate);
      float acc=0.;

      if(!mute_channel_muted(in->active,i)){
	memset(mix,0,sizeof(mix));
	mixwork(in->data[i],ms.cacheP[i],ms.cachePP[i],
		mix,att,del,0,att,del,0);
	
	bypass=0;
	for(j=0;j<input_size;j++){
	  float val=mix[j]*mix[j];
	  if(val>peak[0][i])peak[0][i]=val;
	  acc+=val;
	}
	
	rms[0][i]=acc/input_size;
      }

      acc=0.;
      if(inA && !mute_channel_muted(inA->active,i)){
	memset(mix,0,sizeof(mix));
	mixwork(inA->data[i],ms.cachePA[i],ms.cachePPA[i],
		mix,att,del,0,att,del,0);
	
	bypass=0;
	for(j=0;j<input_size;j++){
	  float val=mix[j]*mix[j];
	  if(val>peak[1][i])peak[1][i]=val;
	  acc+=val;
	}
	
	rms[1][i]=acc/input_size;
      }

      acc=0.;
      if(inB && !mute_channel_muted(inB->active,i)){
	memset(mix,0,sizeof(mix));
	mixwork(inB->data[i],ms.cachePB[i],ms.cachePPB[i],
		mix,att,del,0,att,del,0);
	
	bypass=0;
	for(j=0;j<input_size;j++){
	  float val=mix[j]*mix[j];
	  if(val>peak[2][i])peak[2][i]=val;
	  acc+=val;
	}
	
	rms[2][i]=acc/input_size;
      }
    }

    /* placer settings; translate to final numbers */
    int placer=ms.curr[i].placer_place;
    int placerP=ms.prev[i].placer_place;

    /* place mix */
    {
      int mixedA=0,mixedB=0;
      float mixA[input_size],mixB[input_size];

      for(j=0;j<OUTPUT_CHANNELS;j++){
	int destA=ms.curr[i].placer_destA[j];
	int destAP=ms.prev[i].placer_destA[j];
	int destB=ms.curr[i].placer_destB[j];
	int destBP=ms.prev[i].placer_destB[j];
	
	if(destA || destAP){
	  outactive[j]=1;
	  
	  if(!mixedA){
	    float relA=(placer>100 ? placer*.01-1. : 0.);
	    float relAP=(placerP>100 ? placerP*.01-1. : 0.);

	    float attA=fromdB((ms.curr[i].master_att + ms.curr[i].placer_att * relA)*.1);
	    float attAP=fromdB((ms.prev[i].master_att + ms.prev[i].placer_att * relAP)*.1);
	    int delA=rint((ms.curr[i].master_delay + ms.curr[i].placer_delay * relA)*.00001*input_rate);
	    int delAP=rint((ms.prev[i].master_delay + ms.prev[i].placer_delay * relAP)*.00001*input_rate);

	    float attA_r=fromdB(ms.curr[i].master_att*.1);
	    float attAP_r=fromdB(ms.prev[i].master_att*.1);
	    int delA_r=rint(ms.curr[i].master_delay*.00001*input_rate);
	    int delAP_r=rint(ms.prev[i].master_delay*.00001*input_rate);

	    memset(mixA,0,sizeof(mixA));
	    mixwork(in->data[i],ms.cacheP[i],ms.cachePP[i],
		    mixA,attA,delA,0,attAP,delAP,0);
	    mixwork(inA->data[i],ms.cachePA[i],ms.cachePPA[i],
		    mixA,attA_r,delA_r,0,attAP_r,delAP_r,0);
	    mixedA=1;

	  }
	  mixadd(mixA,ms.out.data[j],destA,destAP);
	}
	if(destB || destBP){
	  outactive[j]=1;
	  
	  if(!mixedB){
	    float relB=(placer<100 ? 1.-placer*.01 : 0.);
	    float relBP=(placerP<100 ? 1.-placerP*.01 : 0.);

	    float attB=fromdB((ms.curr[i].master_att + ms.curr[i].placer_att * relB)*.1);
	    float attBP=fromdB((ms.prev[i].master_att + ms.prev[i].placer_att * relBP)*.1);
	    int delB=rint((ms.curr[i].master_delay + ms.curr[i].placer_delay * relB)*.00001*input_rate);
	    int delBP= rint((ms.prev[i].master_delay + ms.prev[i].placer_delay * relBP)*.00001*input_rate);

	    float attB_r=fromdB(ms.curr[i].master_att*.1);
	    float attBP_r=fromdB(ms.prev[i].master_att*.1);
	    int delB_r=rint(ms.curr[i].master_delay*.00001*input_rate);
	    int delBP_r= rint(ms.prev[i].master_delay*.00001*input_rate);
	    
	    memset(mixB,0,sizeof(mixB));
	    mixwork(in->data[i],ms.cacheP[i],ms.cachePP[i],
		    mixB,attB,delB,0,attBP,delBP,0);
	    mixwork(inB->data[i],ms.cachePB[i],ms.cachePPB[i],
		    mixB,attB_r,delB_r,0,attBP_r,delBP_r,0);
	    mixedB=1;
	  }
	  mixadd(mixB,ms.out.data[j],destB,destBP);
	}
      }
      
      /* feedback for A */
      if(feedit){
	float acc=0.;
	bypass=0;
	if(mixedA){
	  for(j=0;j<input_size;j++){
	    float val=mixA[j]*mixA[j];
	    if(val>peak[3][i])peak[3][i]=val;
	    acc+=val;
	  }
	  
	  peak[3][i]=peak[3][i];
	  rms[3][i]=acc/input_size;
	}
      }

      /* feedback for B */
      if(feedit){
	float acc=0.;
	bypass=0;
	if(mixedB){
	  for(j=0;j<input_size;j++){
	    float val=mixB[j]*mixB[j];
	    if(val>peak[4][i])peak[4][i]=val;
	    acc+=val;
	  }
	  
	  peak[4][i]=peak[4][i];
	  rms[4][i]=acc/input_size;
	}
      }
    }

    /* direct block mix */
    for(k=0;k<MIX_BLOCKS;k++){
      float mix[input_size];

      int sourceM=ms.curr[i].insert_source[k][0];
      int sourceMP=ms.prev[i].insert_source[k][0];
      int sourceA=ms.curr[i].insert_source[k][1];
      int sourceAP=ms.prev[i].insert_source[k][1];
      int sourceB=ms.curr[i].insert_source[k][2];
      int sourceBP=ms.prev[i].insert_source[k][2];

      float att=
	fromdB((ms.curr[i].master_att +
		ms.curr[i].insert_att[k])*.1);
      
      int del=
	rint((ms.curr[i].master_delay +
	      ms.curr[i].insert_delay[k])*.00001*input_rate);

      float attP=
	fromdB((ms.prev[i].master_att +
		ms.prev[i].insert_att[k])*.1);
      
      int delP=
	rint((ms.prev[i].master_delay +
	      ms.prev[i].insert_delay[k])*.00001*input_rate);

      if(sourceM || sourceMP || 
	 sourceA || sourceAP ||
	 sourceB || sourceBP){
	memset(mix,0,sizeof(mix));

	/* master */
	if(sourceM || sourceMP)
	  mixwork(in->data[i],ms.cacheP[i],ms.cachePP[i],
		  mix,
		  (sourceM ? att : 0),
		  del,ms.curr[i].insert_invert[k],
		  (sourceMP ? attP : 0),
		  delP,ms.prev[i].insert_invert[k]);

	/* reverbA */
	if(sourceA || sourceAP)
	  if(inA)
	    mixwork(inA->data[i],ms.cachePA[i],ms.cachePPA[i],
		    mix,
		    (sourceA ? att : 0),
		    del,ms.curr[i].insert_invert[k],
		    (sourceAP ? attP : 0),
		    delP,ms.prev[i].insert_invert[k]);

	/* reverbB */
	if(sourceB || sourceBP)
	  if(inB)
	    mixwork(inB->data[i],ms.cachePB[i],ms.cachePPB[i],
		    mix,
		    (sourceB ? att : 0),
		    del,ms.curr[i].insert_invert[k],
		    (sourceBP ? attP : 0),
		    delP,ms.prev[i].insert_invert[k]);

	/* mix into output */
	for(j=0;j<OUTPUT_CHANNELS;j++){
	  int dest=ms.curr[i].insert_dest[k][j];
	  int destP=ms.prev[i].insert_dest[k][j];
	  
	  if(dest || destP){
	    outactive[j]=1;	    
	    mixadd(mix,ms.out.data[j],dest,destP);
	  }
	}
	
	/* feedback */
	if(feedit){
	  float acc=0.;
	  bypass=0;
	  for(j=0;j<input_size;j++){
	    float val=mix[j]*mix[j];
	    if(val>peak[5+k][i])peak[5+k][i]=val;
	    acc+=val;
	  }
	  
	  peak[5+k][i]=peak[5+k][i];
	  rms[5+k][i]=acc/input_size;

	}
      }
    }
    /* rotate data cache */
    {
      float *temp=ms.cachePP[i];
      ms.cachePP[i]=ms.cacheP[i];
      ms.cacheP[i]=in->data[i];
      in->data[i]=temp;

      if(inA){
	temp=ms.cachePPA[i];
	ms.cachePPA[i]=ms.cachePA[i];
	ms.cachePA[i]=inA->data[i];
	inA->data[i]=temp;
      }

      if(inB){
	temp=ms.cachePPB[i];
	ms.cachePPB[i]=ms.cachePB[i];
	ms.cachePB[i]=inB->data[i];
	inB->data[i]=temp;
      }
    }
  }
  
  /* finish output data */
  ms.out.samples=in->samples;
  ms.out.active=0;
  for(i=0;i<OUTPUT_CHANNELS;i++)
    if(outactive[i])
      ms.out.active|=(1<<i);
  
  /* rotate settings cache */
  {
    mix_settings *temp=ms.curr;
    ms.curr=ms.prev;
    ms.prev=temp;
  }

  /* push feedback */
  if(bypass){
    mix_feedback *mf=
      (mix_feedback *)feedback_new(&ms.feedpool,new_mix_feedback);
    mf->bypass=1;
    feedback_push(&ms.feedpool,(feedback_generic *)mf);
  }else{
    mix_feedback *mf=
      (mix_feedback *)feedback_new(&ms.feedpool,new_mix_feedback);
    
    if(!mf->peak){
      mf->peak=malloc((MIX_BLOCKS+5)*sizeof(*mf->peak));
      mf->rms=malloc((MIX_BLOCKS+5)*sizeof(*mf->rms));
  
      for(i=0;i<MIX_BLOCKS+5;i++)
        mf->rms[i]=malloc(input_ch*sizeof(**mf->rms));
      for(i=0;i<MIX_BLOCKS+5;i++)
        mf->peak[i]=malloc(input_ch*sizeof(**mf->peak));
    }
    
    for(i=0;i<MIX_BLOCKS+5;i++){
      memcpy(mf->peak[i],peak[i],input_ch*sizeof(**peak));
      memcpy(mf->rms[i],rms[i],input_ch*sizeof(**rms));
    } 
    mf->bypass=0;
    feedback_push(&ms.feedpool,(feedback_generic *)mf);
  }

  return &ms.out;
}