Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}