// Filter data through filter static af_data_t* play(struct af_instance_s* af, af_data_t* data) { af_data_t* c = data; // Current working data af_delay_t* s = af->setup; // Setup for this instance int nch = c->nch; // Number of channels int len = c->len/c->bps; // Number of sample in data chunk int ri = 0; int ch,i; for(ch=0;ch<nch;ch++){ switch(c->bps){ case 1:{ int8_t* a = c->audio; int8_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; for(i=ch;i<len;i+=nch){ q[wi] = a[i]; a[i] = q[ri]; UPDATEQI(wi); UPDATEQI(ri); } s->wi[ch] = wi; break; } case 2:{ int16_t* a = c->audio; int16_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; for(i=ch;i<len;i+=nch){ q[wi] = a[i]; a[i] = q[ri]; UPDATEQI(wi); UPDATEQI(ri); } s->wi[ch] = wi; break; } case 4:{ int32_t* a = c->audio; int32_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; for(i=ch;i<len;i+=nch){ q[wi] = a[i]; a[i] = q[ri]; UPDATEQI(wi); UPDATEQI(ri); } s->wi[ch] = wi; break; } } } s->ri = ri; return c; }
// Filter data through filter static int filter(struct af_instance* af, struct mp_audio* data, int flags) { struct mp_audio* c = data; // Current working data af_delay_t* s = af->priv; // Setup for this instance int nch = c->nch; // Number of channels int len = mp_audio_psize(c)/c->bps; // Number of sample in data chunk int ri = 0; int ch,i; for(ch=0;ch<nch;ch++){ switch(c->bps){ case 1:{ int8_t* a = c->planes[0]; int8_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; for(i=ch;i<len;i+=nch){ q[wi] = a[i]; a[i] = q[ri]; UPDATEQI(wi); UPDATEQI(ri); } s->wi[ch] = wi; break; } case 2:{ int16_t* a = c->planes[0]; int16_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; for(i=ch;i<len;i+=nch){ q[wi] = a[i]; a[i] = q[ri]; UPDATEQI(wi); UPDATEQI(ri); } s->wi[ch] = wi; break; } case 4:{ int32_t* a = c->planes[0]; int32_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; for(i=ch;i<len;i+=nch){ q[wi] = a[i]; a[i] = q[ri]; UPDATEQI(wi); UPDATEQI(ri); } s->wi[ch] = wi; break; } } } s->ri = ri; return 0; }
// Filter data through filter static af_data_t* play(struct af_instance_s* af, af_data_t* data){ af_surround_t* s = (af_surround_t*)af->setup; float* m = steering_matrix[0]; float* in = data->audio; // Input audio data float* out = NULL; // Output audio data float* end = in + data->len / sizeof(float); // Loop end 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 if (AF_OK != RESIZE_LOCAL_BUFFER(af, data)) return NULL; out = af->data->audio; 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->audio = af->data->audio; data->len = (data->len*af->mul.n)/af->mul.d; data->nch = af->data->nch; return data; }
static int filter_frame(struct af_instance *af, struct mp_audio *data) { if (!data) return 0; struct mp_audio *outframe = mp_audio_pool_get(af->out_pool, &af->fmt_out, data->samples); if (!outframe) { talloc_free(data); return -1; } mp_audio_copy_attributes(outframe, data); 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 = outframe->planes[0]; // 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 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; talloc_free(data); af_add_output_frame(af, outframe); return 0; }