AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr) { AudioMix *am; int ret; am = av_mallocz(sizeof(*am)); if (!am) return NULL; am->avr = avr; if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) { av_log(avr, AV_LOG_ERROR, "Unsupported internal format for " "mixing: %s\n", av_get_sample_fmt_name(avr->internal_sample_fmt)); goto error; } am->fmt = avr->internal_sample_fmt; am->coeff_type = avr->mix_coeff_type; am->in_layout = avr->in_channel_layout; am->out_layout = avr->out_channel_layout; am->in_channels = avr->in_channels; am->out_channels = avr->out_channels; /* build matrix if the user did not already set one */ if (avr->mix_matrix) { ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels); if (ret < 0) goto error; av_freep(&avr->mix_matrix); } else { double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels * sizeof(*matrix_dbl)); if (!matrix_dbl) goto error; ret = avresample_build_matrix(avr->in_channel_layout, avr->out_channel_layout, avr->center_mix_level, avr->surround_mix_level, avr->lfe_mix_level, avr->normalize_mix_level, matrix_dbl, avr->in_channels, avr->matrix_encoding); if (ret < 0) { av_free(matrix_dbl); goto error; } ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels); if (ret < 0) { av_log(avr, AV_LOG_ERROR, "error setting mix matrix\n"); av_free(matrix_dbl); goto error; } av_free(matrix_dbl); } return am; error: av_free(am); return NULL; }
AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr) { AudioMix *am; int ret; am = av_mallocz(sizeof(*am)); if (!am) return NULL; am->avr = avr; if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) { av_log(avr, AV_LOG_ERROR, "Unsupported internal format for " "mixing: %s\n", av_get_sample_fmt_name(avr->internal_sample_fmt)); goto error; } am->fmt = avr->internal_sample_fmt; am->coeff_type = avr->mix_coeff_type; am->in_layout = avr->in_channel_layout; am->out_layout = avr->out_channel_layout; am->in_channels = avr->in_channels; am->out_channels = avr->out_channels; /* build matrix if the user did not already set one */ if (avr->mix_matrix) { ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels); if (ret < 0) goto error; av_freep(&avr->mix_matrix); } else { int i, j; char in_layout_name[128]; char out_layout_name[128]; double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels * sizeof(*matrix_dbl)); if (!matrix_dbl) goto error; ret = avresample_build_matrix(avr->in_channel_layout, avr->out_channel_layout, avr->center_mix_level, avr->surround_mix_level, avr->lfe_mix_level, avr->normalize_mix_level, matrix_dbl, avr->in_channels, avr->matrix_encoding); if (ret < 0) { av_free(matrix_dbl); goto error; } av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name), avr->in_channels, avr->in_channel_layout); av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name), avr->out_channels, avr->out_channel_layout); av_log(avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n", in_layout_name, out_layout_name); for (i = 0; i < avr->out_channels; i++) { for (j = 0; j < avr->in_channels; j++) { av_log(avr, AV_LOG_DEBUG, " %0.3f ", matrix_dbl[i * avr->in_channels + j]); } av_log(avr, AV_LOG_DEBUG, "\n"); } ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels); if (ret < 0) { av_free(matrix_dbl); goto error; } av_free(matrix_dbl); } return am; error: av_free(am); return NULL; }
void CMixer::Init(AVSampleFormat in_avsf, DWORD in_layout, DWORD out_layout, float matrix_norm, int in_samplerate, int out_samplerate) { // reset parameters m_in_avsf = AV_SAMPLE_FMT_NONE; m_in_layout = 0; m_out_layout = 0; m_matrix_norm = 0.0f; m_in_samplerate = 0; m_out_samplerate = 0; av_free(m_matrix_dbl); // Close Resample Context avresample_close(m_pAVRCxt); int ret = 0; // Set options av_opt_set_int(m_pAVRCxt, "in_sample_fmt", in_avsf, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_rate", in_samplerate, 0); av_opt_set_int(m_pAVRCxt, "out_sample_rate", out_samplerate, 0); // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); m_matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*m_matrix_dbl)); // expand stereo if (in_layout == AV_CH_LAYOUT_STEREO && (out_layout == AV_CH_LAYOUT_QUAD || out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1)) { m_matrix_dbl[0] = 1.0; m_matrix_dbl[1] = 0.0; m_matrix_dbl[2] = 0.0; m_matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { m_matrix_dbl[4] = 0.6666; m_matrix_dbl[5] = (-0.2222); m_matrix_dbl[6] = (-0.2222); m_matrix_dbl[7] = 0.6666; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[4] = 0.5; m_matrix_dbl[5] = 0.5; m_matrix_dbl[6] = 0.0; m_matrix_dbl[7] = 0.0; m_matrix_dbl[8] = 0.6666; m_matrix_dbl[9] = (-0.2222); m_matrix_dbl[10] = (-0.2222); m_matrix_dbl[11] = 0.6666; if (out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[12] = 0.6666; m_matrix_dbl[13] = (-0.2222); m_matrix_dbl[14] = (-0.2222); m_matrix_dbl[15] = 0.6666; } } } else { const double center_mix_level = M_SQRT1_2; const double surround_mix_level = 1.0; const double lfe_mix_level = 1.0; const int normalize = 0; ret = avresample_build_matrix(in_layout, out_layout, center_mix_level, surround_mix_level, lfe_mix_level, normalize, m_matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(m_matrix_dbl); return; } // if back channels do not have sound, then divide side channels for the back and side if (out_layout == AV_CH_LAYOUT_7POINT1) { bool back_no_sound = true; for (int i = 0; i < in_ch * 2; i++) { if (m_matrix_dbl[4 * in_ch + i] != 0.0) { back_no_sound = false; } } if (back_no_sound) { for (int i = 0; i < in_ch * 2; i++) { m_matrix_dbl[4 * in_ch + i] = (m_matrix_dbl[6 * in_ch + i] *= M_SQRT1_2); } } } } if (matrix_norm > 0.0f && matrix_norm <= 1.0f) { // 0.0 - normalize off; 1.0 - full normalize matrix double max_peak = 0; for (int j = 0; j < out_ch; j++) { double peak = 0; for (int i = 0; i < in_ch; i++) { peak += fabs(m_matrix_dbl[j * in_ch + i]); } if (peak > max_peak) { max_peak = peak; } } if (max_peak > 1.0) { double g = ((max_peak - 1.0) * (1.0 - matrix_norm) + 1.0) / max_peak; for (int i = 0, n = in_ch * out_ch; i < n; i++) { m_matrix_dbl[i] *= g; } } } #ifdef _DEBUG CString matrix_str = _T("matrix:\n"); for (int j = 0; j < out_ch; j++) { matrix_str.AppendFormat(_T("%d:"), j + 1); for (int i = 0; i < in_ch; i++) { double k = m_matrix_dbl[j * in_ch + i]; matrix_str.AppendFormat(_T(" %.4f"), k); } matrix_str += _T("\n"); } TRACE(matrix_str); #endif // Set Matrix on the context ret = avresample_set_matrix(m_pAVRCxt, m_matrix_dbl, in_ch); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); av_free(m_matrix_dbl); return; } m_in_avsf = in_avsf; m_in_layout = in_layout; m_out_layout = out_layout; m_matrix_norm = matrix_norm; m_in_samplerate = in_samplerate; m_out_samplerate = out_samplerate; }
void CMixer::Init(DWORD out_layout, DWORD in_layout, enum AVSampleFormat in_sf) { avresample_free(&m_pAVRCxt); int ret = 0; // Allocate Resample Context and set options. m_pAVRCxt = avresample_alloc_context(); av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_fmt", in_sf, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); avresample_free(&m_pAVRCxt); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); double* matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*matrix_dbl)); // expand stereo if (in_layout == AV_CH_LAYOUT_STEREO && (out_layout == AV_CH_LAYOUT_QUAD || out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1)) { matrix_dbl[0] = 1.0; matrix_dbl[1] = 0.0; matrix_dbl[2] = 0.0; matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { matrix_dbl[4] = 0.5; matrix_dbl[5] = (-0.5); matrix_dbl[6] = (-0.5); matrix_dbl[7] = 0.5; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { matrix_dbl[4] = 0.5; matrix_dbl[5] = 0.5; matrix_dbl[6] = 0.0; matrix_dbl[7] = 0.0; matrix_dbl[8] = 0.5; matrix_dbl[9] = (-0.5); matrix_dbl[10] = (-0.5); matrix_dbl[11] = 0.5; if (out_layout == AV_CH_LAYOUT_7POINT1) { matrix_dbl[12] = 0.5; matrix_dbl[13] = (-0.5); matrix_dbl[14] = (-0.5); matrix_dbl[15] = 0.5; } } } else { const double center_mix_level = M_SQRT1_2; const double surround_mix_level = M_SQRT1_2; const double lfe_mix_level = M_SQRT1_2; const int normalize = 0; ret = avresample_build_matrix(in_layout, out_layout, center_mix_level, surround_mix_level, lfe_mix_level, normalize, matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(matrix_dbl); avresample_free(&m_pAVRCxt); return; } } #ifdef _DEBUG CString matrix_str; for (int j = 0; j < out_ch; j++) { matrix_str.AppendFormat(_T("%d:"), j + 1); for (int i = 0; i < in_ch; i++) { double k = matrix_dbl[j * in_ch + i]; matrix_str.AppendFormat(_T(" %.4f"), k); } matrix_str += _T("\n"); } TRACE(matrix_str); #endif // Set Matrix on the context ret = avresample_set_matrix(m_pAVRCxt, matrix_dbl, in_ch); av_free(matrix_dbl); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); avresample_free(&m_pAVRCxt); return; } last_in_layout = in_layout; last_out_layout = out_layout; last_in_sf = in_sf; }
void CMixer::Init(AVSampleFormat in_avsf, DWORD in_layout, DWORD out_layout, int in_samplerate, int out_samplerate) { // reset parameters m_in_avsf = AV_SAMPLE_FMT_NONE; m_in_layout = 0; m_out_layout = 0; m_in_samplerate = 0; m_out_samplerate = 0; av_free(m_matrix_dbl); // Close Resample Context avresample_close(m_pAVRCxt); if (in_avsf >= AV_SAMPLE_FMT_U8P && in_avsf <= AV_SAMPLE_FMT_DBLP) { // planar audio is not supported (ffmpeg crashed) m_in_avsf_used = AV_SAMPLE_FMT_FLT; // convert to float } else { m_in_avsf_used = in_avsf; } int ret = 0; // Set options av_opt_set_int(m_pAVRCxt, "in_sample_fmt", m_in_avsf_used, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_rate", in_samplerate, 0); av_opt_set_int(m_pAVRCxt, "out_sample_rate", out_samplerate, 0); // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); m_matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*m_matrix_dbl)); // expand stereo if (in_layout == AV_CH_LAYOUT_STEREO && (out_layout == AV_CH_LAYOUT_QUAD || out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1)) { m_matrix_dbl[0] = 1.0; m_matrix_dbl[1] = 0.0; m_matrix_dbl[2] = 0.0; m_matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { m_matrix_dbl[4] = 0.6666; m_matrix_dbl[5] = (-0.2222); m_matrix_dbl[6] = (-0.2222); m_matrix_dbl[7] = 0.6666; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[4] = 0.5; m_matrix_dbl[5] = 0.5; m_matrix_dbl[6] = 0.0; m_matrix_dbl[7] = 0.0; m_matrix_dbl[8] = 0.6666; m_matrix_dbl[9] = (-0.2222); m_matrix_dbl[10] = (-0.2222); m_matrix_dbl[11] = 0.6666; if (out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[12] = 0.6666; m_matrix_dbl[13] = (-0.2222); m_matrix_dbl[14] = (-0.2222); m_matrix_dbl[15] = 0.6666; } } } else { const double center_mix_level = M_SQRT1_2; const double surround_mix_level = M_SQRT1_2; const double lfe_mix_level = M_SQRT1_2; const int normalize = 0; ret = avresample_build_matrix(in_layout, out_layout, center_mix_level, surround_mix_level, lfe_mix_level, normalize, m_matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(m_matrix_dbl); return; } } #ifdef _DEBUG CString matrix_str; for (int j = 0; j < out_ch; j++) { matrix_str.AppendFormat(_T("%d:"), j + 1); for (int i = 0; i < in_ch; i++) { double k = m_matrix_dbl[j * in_ch + i]; matrix_str.AppendFormat(_T(" %.4f"), k); } matrix_str += _T("\n"); } TRACE(matrix_str); #endif // Set Matrix on the context ret = avresample_set_matrix(m_pAVRCxt, m_matrix_dbl, in_ch); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); av_free(m_matrix_dbl); return; } m_in_avsf = in_avsf; m_in_layout = in_layout; m_out_layout = out_layout; m_in_samplerate = in_samplerate; m_out_samplerate = out_samplerate; }