Ejemplo n.º 1
0
Archivo: af_hrtf.c Proyecto: 0x0all/mpv
/* Initialization and runtime control */
static int control(struct af_instance *af, int cmd, void* arg)
{
    af_hrtf_t *s = af->priv;
    int test_output_res;

    switch(cmd) {
    case AF_CONTROL_REINIT:
        reset(s);
        af->data->rate = 48000;
        mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch);
        if(af->data->nch == 2) {
            /* 2 channel input */
            if(s->decode_mode != HRTF_MIX_MATRIX2CH) {
                /* Default behavior is stereo mixing. */
                s->decode_mode = HRTF_MIX_STEREO;
            }
        } else if (af->data->nch < 5) {
            mp_audio_set_channels_old(af->data, 5);
        }
        mp_audio_set_format(af->data, AF_FORMAT_S16);
        test_output_res = af_test_output(af, (struct mp_audio*)arg);
        // after testing input set the real output format
        mp_audio_set_num_channels(af->data, 2);
        s->print_flag = 1;
        return test_output_res;
    case AF_CONTROL_RESET:
        reset(s);
        return AF_OK;
    }

    return AF_UNKNOWN;
}
Ejemplo n.º 2
0
/* Initialization and runtime control */
static int control(struct af_instance *af, int cmd, void* arg)
{
    af_hrtf_t *s = af->setup;
    int test_output_res;
    char mode;

    switch(cmd) {
    case AF_CONTROL_REINIT:
	af->data->rate   = ((struct mp_audio*)arg)->rate;
	if(af->data->rate != 48000) {
	    // automatic samplerate adjustment in the filter chain
	    // is not yet supported.
	    mp_msg(MSGT_AFILTER, MSGL_ERR,
		   "[hrtf] ERROR: Sampling rate is not 48000 Hz (%d)!\n",
		   af->data->rate);
	    return AF_ERROR;
	}
	mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch);
	    if(af->data->nch == 2) {
 	       /* 2 channel input */
 	       if(s->decode_mode != HRTF_MIX_MATRIX2CH) {
   		  /* Default behavior is stereo mixing. */
 		  s->decode_mode = HRTF_MIX_STEREO;
	       }
	    }
	    else if (af->data->nch < 5)
	      mp_audio_set_channels_old(af->data, 5);
        mp_audio_set_format(af->data, AF_FORMAT_S16);
	test_output_res = af_test_output(af, (struct mp_audio*)arg);
	// after testing input set the real output format
        mp_audio_set_num_channels(af->data, 2);
	s->print_flag = 1;
	return test_output_res;
    case AF_CONTROL_COMMAND_LINE:
	sscanf((char*)arg, "%c", &mode);
	switch(mode) {
	case 'm':
	    /* Use matrix rear decoding. */
	    s->matrix_mode = 1;
	    break;
	case 's':
	    /* Input needs matrix decoding. */
	    s->decode_mode = HRTF_MIX_MATRIX2CH;
	    break;
	case '0':
	    s->matrix_mode = 0;
	    break;
	default:
	    mp_msg(MSGT_AFILTER, MSGL_ERR,
		   "[hrtf] Mode is neither 'm', 's', nor '0' (%c).\n",
		   mode);
	    return AF_ERROR;
	}
	s->print_flag = 1;
	return AF_OK;
    }

    return AF_UNKNOWN;
}
Ejemplo n.º 3
0
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
  af_sub_t* s   = af->setup;

  switch(cmd){
  case AF_CONTROL_REINIT:{
    // Sanity check
    if(!arg) return AF_ERROR;

    af->data->rate   = ((struct mp_audio*)arg)->rate;
    mp_audio_set_channels_old(af->data, MPMAX(s->ch+1,((struct mp_audio*)arg)->nch));
    mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE);

    // Design low-pass filter
    s->k = 1.0;
    if((-1 == af_filter_szxform(sp[0].a, sp[0].b, Q, s->fc,
       (float)af->data->rate, &s->k, s->w[0])) ||
       (-1 == af_filter_szxform(sp[1].a, sp[1].b, Q, s->fc,
       (float)af->data->rate, &s->k, s->w[1])))
      return AF_ERROR;
    return af_test_output(af,(struct mp_audio*)arg);
  }
  case AF_CONTROL_COMMAND_LINE:{
    int   ch=5;
    float fc=60.0;
    sscanf(arg,"%f:%i", &fc , &ch);
    if(AF_OK != control(af,AF_CONTROL_SUB_CH | AF_CONTROL_SET, &ch))
      return AF_ERROR;
    return control(af,AF_CONTROL_SUB_FC | AF_CONTROL_SET, &fc);
  }
  case AF_CONTROL_SUB_CH | AF_CONTROL_SET: // Requires reinit
    // Sanity check
    if((*(int*)arg >= AF_NCH) || (*(int*)arg < 0)){
      mp_msg(MSGT_AFILTER, MSGL_ERR, "[sub] Subwoofer channel number must be between "
	     " 0 and %i current value is %i\n", AF_NCH-1, *(int*)arg);
      return AF_ERROR;
    }
    s->ch = *(int*)arg;
    return AF_OK;
  case AF_CONTROL_SUB_CH | AF_CONTROL_GET:
    *(int*)arg = s->ch;
    return AF_OK;
  case AF_CONTROL_SUB_FC | AF_CONTROL_SET: // Requires reinit
    // Sanity check
    if((*(float*)arg > 300) || (*(float*)arg < 20)){
      mp_msg(MSGT_AFILTER, MSGL_ERR, "[sub] Cutoff frequency must be between 20Hz and"
	     " 300Hz current value is %0.2f",*(float*)arg);
      return AF_ERROR;
    }
    // Set cutoff frequency
    s->fc = *(float*)arg;
    return AF_OK;
  case AF_CONTROL_SUB_FC | AF_CONTROL_GET:
    *(float*)arg = s->fc;
    return AF_OK;
  }
  return AF_UNKNOWN;
}
Ejemplo n.º 4
0
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
  af_surround_t *s = af->setup;
  switch(cmd){
  case AF_CONTROL_REINIT:{
    float fc;
    mp_audio_copy_config(af->data, (struct mp_audio*)arg);
    mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch*2);
    mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE);

    if (af->data->nch != 4){
      mp_msg(MSGT_AFILTER, MSGL_ERR, "[surround] Only stereo input is supported.\n");
      return AF_DETACH;
    }
    // Surround filer coefficients
    fc = 2.0 * 7000.0/(float)af->data->rate;
    if (-1 == af_filter_design_fir(L, s->w, &fc, LP|HAMMING, 0)){
      mp_msg(MSGT_AFILTER, MSGL_ERR, "[surround] Unable to design low-pass filter.\n");
      return AF_ERROR;
    }

    // Free previous delay queues
    free(s->dl);
    free(s->dr);
    // Allocate new delay queues
    s->dl = calloc(LD,af->data->bps);
    s->dr = calloc(LD,af->data->bps);
    if((NULL == s->dl) || (NULL == s->dr))
      mp_msg(MSGT_AFILTER, MSGL_FATAL, "[delay] Out of memory\n");

    // Initialize delay queue index
    if(AF_OK != af_from_ms(1, &s->d, &s->wi, af->data->rate, 0.0, 1000.0))
      return AF_ERROR;
//    printf("%i\n",s->wi);
    s->ri = 0;

    if((af->data->format != ((struct mp_audio*)arg)->format) ||
       (af->data->bps    != ((struct mp_audio*)arg)->bps)){
      mp_audio_set_format((struct mp_audio*)arg, af->data->format);
      return AF_FALSE;
    }
    return AF_OK;
  }
  case AF_CONTROL_COMMAND_LINE:{
    float d = 0;
    sscanf((char*)arg,"%f",&d);
    if ((d < 0) || (d > 1000)){
      mp_msg(MSGT_AFILTER, MSGL_ERR, "[surround] Invalid delay time, valid time values"
	     " are 0ms to 1000ms current value is %0.3f ms\n",d);
      return AF_ERROR;
    }
    s->d = d;
    return AF_OK;
  }
  }
  return AF_UNKNOWN;
}
Ejemplo n.º 5
0
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
  af_center_t* s   = af->priv;

  switch(cmd){
  case AF_CONTROL_REINIT:{
    // Sanity check
    if(!arg) return AF_ERROR;

    af->data->rate   = ((struct mp_audio*)arg)->rate;
    mp_audio_set_channels_old(af->data, MPMAX(s->ch+1,((struct mp_audio*)arg)->nch));
    mp_audio_set_format(af->data, AF_FORMAT_FLOAT);

    return af_test_output(af,(struct mp_audio*)arg);
  }
  }
  return AF_UNKNOWN;
}
Ejemplo n.º 6
0
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
  af_surround_t *s = af->priv;
  switch(cmd){
  case AF_CONTROL_REINIT:{
    struct mp_audio *in = arg;
    float fc;
    if (!mp_chmap_is_stereo(&in->channels)) {
        MP_ERR(af, "Only stereo input is supported.\n");
        return AF_DETACH;
    }

    mp_audio_set_format(in, AF_FORMAT_FLOAT);
    mp_audio_copy_config(af->data, in);
    mp_audio_set_channels_old(af->data, in->nch * 2);

    // Surround filer coefficients
    fc = 2.0 * 7000.0/(float)af->data->rate;
    if (-1 == af_filter_design_fir(L, s->w, &fc, LP|HAMMING, 0)){
      MP_ERR(af, "Unable to design low-pass filter.\n");
      return AF_ERROR;
    }

    // Free previous delay queues
    free(s->dl);
    free(s->dr);
    // Allocate new delay queues
    s->dl = calloc(LD,af->data->bps);
    s->dr = calloc(LD,af->data->bps);
    if((NULL == s->dl) || (NULL == s->dr))
      MP_FATAL(af, "Out of memory\n");

    // Initialize delay queue index
    if(AF_OK != af_from_ms(1, &s->d, &s->wi, af->data->rate, 0.0, 1000.0))
      return AF_ERROR;
//    printf("%i\n",s->wi);
    s->ri = 0;

    return AF_OK;
  }
  }
  return AF_UNKNOWN;
}
Ejemplo n.º 7
0
// Filter data through filter
static int filter(struct af_instance* af, struct mp_audio* data, int flags){
  af_surround_t* s   = (af_surround_t*)af->priv;
  const float*   m   = steering_matrix[0];
  float*         in  = data->planes[0];         // Input audio data
  float*         out = NULL;            // Output audio data
  float*         end = in + data->samples * data->nch;
  int            i   = s->i;    // Filter queue index
  int            ri  = s->ri;   // Read index for delay queue
  int            wi  = s->wi;   // Write index for delay queue

  mp_audio_realloc_min(af->data, data->samples);

  out = af->data->planes[0];

  while(in < end){
    /* Dominance:
       abs(in[0])  abs(in[1]);
       abs(in[0]+in[1])  abs(in[0]-in[1]);
       10 * log( abs(in[0]) / (abs(in[1])|1) );
       10 * log( abs(in[0]+in[1]) / (abs(in[0]-in[1])|1) ); */

    /* About volume balancing...
       Surround encoding does the following:
           Lt=L+.707*C+.707*S, Rt=R+.707*C-.707*S
       So S should be extracted as:
           (Lt-Rt)
       But we are splitting the S to two output channels, so we
       must take 3dB off as we split it:
           Ls=Rs=.707*(Lt-Rt)
       Trouble is, Lt could be +1, Rt -1, so possibility that S will
       overflow. So to avoid that, we cut L/R by 3dB (*.707), and S by
       6dB (/2). This keeps the overall balance, but guarantees no
       overflow. */

    // Output front left and right
    out[0] = m[0]*in[0] + m[1]*in[1];
    out[1] = m[2]*in[0] + m[3]*in[1];

    // Low-pass output @ 7kHz
    FIR((&s->lq[i]), s->w, s->dl[wi]);

    // Delay output by d ms
    out[2] = s->dl[ri];

#ifdef SPLITREAR
    // Low-pass output @ 7kHz
    FIR((&s->rq[i]), s->w, s->dr[wi]);

    // Delay output by d ms
    out[3] = s->dr[ri];
#else
    out[3] = -out[2];
#endif

    // Update delay queues indexes
    UPDATEQI(ri);
    UPDATEQI(wi);

    // Calculate and save surround in circular queue
#ifdef SPLITREAR
    ADDQUE(i, s->rq, s->lq, m[6]*in[0]+m[7]*in[1], m[8]*in[0]+m[9]*in[1]);
#else
    ADDQUE(i, s->lq, m[4]*in[0]+m[5]*in[1]);
#endif

    // Next sample...
    in = &in[data->nch];
    out = &out[af->data->nch];
  }

  // Save indexes
  s->i  = i; s->ri = ri; s->wi = wi;

  // Set output data
  data->planes[0] = af->data->planes[0];
  mp_audio_set_channels_old(data, af->data->nch);

  return 0;
}