Пример #1
0
void glPassThrough(GLfloat token) {
    ERROR_IN_BLOCK();
    if (feedback_overflow(2)) return;
    feedback_push(GL_PASS_THROUGH_TOKEN);
    feedback_push(token);
    state.feedback.values -= 1;
}
Пример #2
0
static void feedback_vertex(block_t *block, int i) {
    static GLfloat color[] = {0, 0, 0, 1};
    static GLfloat tex[] = {0, 0, 0, 0};
    GLfloat v[4], *c, *t;
    c = block->color ?: color;
    // glFeedbackBuffer returns only the texture coordinate of texture unit GL_TEXTURE0.
    t = block->tex[0] ?: tex;

    // TODO: this will be called extra times on stuff like triangle strips
    gl_transform_vertex(v, &block->vert[i * 3]);
    switch (state.feedback.type) {
        case GL_2D:
            feedback_push_n(v, 2);
            break;
        case GL_3D:
            feedback_push_n(v, 3);
            break;
        case GL_3D_COLOR:
            feedback_push_n(v, 3);
            feedback_push_n(c, 4);
            break;
        case GL_3D_COLOR_TEXTURE:
            feedback_push_n(v, 3);
            feedback_push_n(c, 4);
            feedback_push_n(t, 2);
            // we only store 2d texture coordinates for now
            feedback_push(0.0f);
            feedback_push(0.0f);
            break;
        case GL_4D_COLOR_TEXTURE:
            feedback_push_n(v, 3);
            // our vertices are already normalized, so W is redundant here
            feedback_push(1.0f);
            feedback_push_n(c, 4);
            feedback_push_n(t, 4);
            break;
    }
}
Пример #3
0
static void feedback_push_n(GLfloat *values, int length) {
    for (int i = 0; i < length; i++) {
        feedback_push(values[i]);
    }
}
Пример #4
0
static void feedback_polygon(int n) {
    feedback_push(GL_POLYGON_TOKEN);
    feedback_push(n);
}
Пример #5
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;
}