// 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; }