FFmpeg: オーディオのリサンプリング

1. リサンプリング

1.1 リサンプリングとは

いわゆるリサンプリングとは、オーディオのサンプリング レート、サンプル形式、チャンネル数、その他のパラメーターを変更して、期待されるパラメーターに従って出力されるようにすることです。

1.2 リサンプリングを行う理由

なぜ再サンプリングするのでしょうか? もちろん、元のオーディオパラメータはニーズを満たしません。たとえば、FFmpeg でオーディオをデコードする場合、オーディオソースが異なればフォーマットやサンプリングレートなどが異なり、デコードされたデータのパラメータも異なります。 FFmpeg はオーディオをデコードします。オーディオ形式は AV_SAMPLE_FMT_FLTP です。このパラメーターは一貫している必要があります)。デコードされたオーディオ データを他の操作に使用する必要がある場合、これらのパラメーターの不一致により、多くの追加作業が発生します。直接リサンプリングして、定式化したオーディオパラメータを取得する方がはるかに便利です。

もう 1 つの例は、SDL でオーディオを再生する場合です。現在の SDL2.0 は平面形式も浮動小数点タイプもサポートしていないため、最新の FFMPEG 16 はオーディオを AV_SAMPLE_FMT_FLTP 形式にデコードします。そのため、この時点で、次のことを行う必要があります。 SDL2.0で再生できるようにリサンプリングしてください。

2. 対応パラメータ分析

2.1 サンプリングレート

サンプリング デバイスが 1 秒あたりにサンプルを抽出する回数

2.2 サンプリング形式と量子化精度(ビット幅)

音声フォーマットごとに量子化精度(ビット幅)が異なり、ビット数が多いほど表現値が正確になり、より正確なサウンドパフォーマンスが得られます。FFMpeg には次のオーディオ形式があり、各形式には占有バイト数に関する情報が含まれています (libavutil/samplefmt.h)。

enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16, ///< signed 16 bits
    AV_SAMPLE_FMT_S32, ///< signed 32 bits
    AV_SAMPLE_FMT_FLT, ///< float
    AV_SAMPLE_FMT_DBL, ///< double
    AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP, ///< float, planar
    AV_SAMPLE_FMT_DBLP, ///< double, planar
    AV_SAMPLE_FMT_S64, ///< signed 64 bits
    AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar
    AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
};

2.3 フラグメンテーション(平面)とパッケージ化(パック化)

2チャンネルを例にとると、P(プレーン)のデータフォーマットを格納する場合、左チャンネルと右チャンネルのデータが別々に格納され、左チャンネルのデータはdata[0]に格納され、右チャネルのデータ データは data[1] に格納され、各チャネルが占めるバイト数は linesize[0] と linesize[1] です。

data[0]にはPのない音声データ(パック)がLRLRLR…の形式で交互に格納され、linesize[0]は総データ量を示します。

2.4チャンネル配信(channel_layout)

チャンネルの分配はFFmpeg\libavutil\channel_layout.hで定義されており、一般的にはAV_CH_LAYOUT_STEREO(2チャンネル)とAV_CH_LAYOUT_SURROUND(3チャンネル)がよく使われ、これら2つの定義は以下の通りです。

#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER)

2.5 オーディオフレームのデータ量の計算

オーディオのフレームのデータ量 (バイト) = チャンネル数 * nb_samples サンプル数 * 各サンプルが占めるバイト数

オーディオ フレームが 1024 サンプル、2 チャネルを含む FLTP 形式の PCM データである場合、オーディオ フレームに含まれるオーディオ データの量は 2 1024 4 = 8192バイトになります。

AV_SAMPLE_FMT_DBL : 210248 = 16384

2.6 オーディオ再生時間の計算

サンプリングレート44100Hzで計算すると、1秒あたり44100サンプル、通常のフレームは1024サンプルとなり、各フレームの再生時間/1024=1000ms/44100となり、各フレームの再生時間=1024となることが分かります。 *1000/44100=23.2ms (正確には 23.21995464852608)。

1 フレームの再生時間 (ミリ秒) = nb_samples*1000 / サンプリング レート =

(1) 1024*1000/44100=23.21995464852608ms -> 23.2ms にほぼ等しく、精度の損失は 0.011995464852608ms、累積 100,000 フレームの場合、誤差は 1199ms を超え、ビデオが一緒に存在する場合、オーディオとビデオの同期が発生します。問題。23.2 に従ってポイント (0 23.2 46.4 ) を計算すると、累積誤差が生じます。

(2)1024*1000/48000=21.33333333333333ms

[学習アドレス]: FFmpeg/WebRTC/RTMP/NDK/Android オーディオおよびビデオ ストリーミング メディアの高度な開発
[記事の特典]: より多くのオーディオおよびビデオ学習教材パッケージ、Dachang インタビューの質問、技術ビデオ、および学習ロードマップを無料で受け取ります。 C/C++、Linux、FFmpeg webRTC rtmp hls rtsp ffplay srs など) 必要な場合は、 1079654574 をクリックしてグループに参加して受信できます~

3. FFmpeg リサンプリング API

オーディオリサンプリングのコンテキストを割り当てる

struct SwrContext *swr_alloc(void);

関連するパラメータを設定した後、この関数を使用して SwrContext 構造体を初期化します。

int swr_init(struct SwrContext *s);

SwrContext を割り当て、よく使用されるパラメータを設定/リセットします。

struct SwrContext* swr_alloc_set_opts(struct SwrContext* s, // ⾳频重采样上下⽂
    int64_t out_ch_layout, // 输出的layout, 如:5.1声道
    enum AVSampleFormat out_sample_fmt, // 输出的采样格式。Float, S16,⼀般选⽤是s16 绝⼤部分声卡⽀持
    int out_sample_rate, //输出采样率
    int64_t in_ch_layout, // 输⼊的layout
    enum AVSampleFormat in_sample_fmt, // 输⼊的采样格式
    int in_sample_rate, // 输⼊的采样率
    int log_offset, // ⽇志相关,不⽤管先,直接为0
    void* log_ctx // ⽇志相关,不⽤管先,直接为NULL
);

定義されたパラメータに従って入力音声を変換して出力します

int swr_convert(struct SwrContext* s, // ⾳频重采样的上下⽂
    uint8_t** out, // 输出的指针。传递的输出的数组
    int out_count, //输出的样本数量,不是字节数。单通道的样本数量。
    const uint8_t** in, //输⼊的数组,AVFrame解码出来的DATA
    int in_count // 输⼊的单通道的样本数量。
);

in と in_count を 0 に設定すると、最後の数サンプルを最後にフラッシュできます。

SwrContext 構造体を解放し、この構造体を NULL に設定します。

void swr_free(struct SwrContext **s);

オーディオのリサンプリング、サンプルフォーマット変換、ミキシングライブラリ。lswr との対話は、swr_alloc() または swr_alloc_set_opts() に割り当てられる SwrContext を通じて行われます。これは不透明であるため、すべてのパラメータは AVOptions API を使用して設定する必要があります。lswr を使用するには、まず SwrContext を割り当てる必要があります。これは、swr_alloc() または swr_alloc_set_opts() を使用して実行できます。前者を使用する場合は、AVOptions API を通じてオプションを設定する必要があります。後者の関数は同じ機能を提供しますが、同じステートメント内でいくつかの共通オプションを設定できます。

たとえば、次のコードは、平面浮動小数点サンプル形式からインターリーブ符号付き 16 ビット整数への変換、48kHz から 44.1kHz へのダウンサンプリング、および 5.1 チャンネルからステレオへのダウンミックス (デフォルトのミキシング マトリックスを使用) を設定します。これは swr_alloc() 関数を使用します。

SwrContext * swr = swr_alloc();
av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0);
av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(swr, "in_sample_rate", 48000, 0);
av_opt_set_int(swr, "out_sample_rate", 44100, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);

同じことが swr_alloc_set_opts() でも機能します。

SwrContext * swr = swr_alloc_set_opts(NULL, // we're allocating a new context
    AV_CH_LAYOUT_STEREO, // out_ch_layout
    AV_SAMPLE_FMT_S16, // out_sample_fmt
    44100, // out_sample_rate
    AV_CH_LAYOUT_5POINT1, // in_ch_layout
    AV_SAMPLE_FMT_FLTP, // in_sample_fmt
    48000, // in_sample_rate
    0, // log_offset
    NULL); // log_ctx

すべての値を設定したら、swr_init() で初期化する必要があります。変換パラメータを変更する必要がある場合は、上記の最初の例で説明したように AVOptions を使用してパラメータを変更することも、swr_alloc_set_opts() を使用することもできますが、最初のパラメータは割り当てのコンテキストです。swr_init() を再度呼び出す必要があります。すべての値を設定したら、swr_init() で初期化する必要があります。変換パラメータを変更する必要がある場合は、上記の最初の例で説明したように AVOptions を使用してパラメータを変更することも、swr_alloc_set_opts() を使用することもできますが、最初のパラメータは割り当てのコンテキストです。swr_init() を再度呼び出す必要があります。変換自体は、swr_convert() を繰り返し呼び出すことで行われます。出力スペースが不十分な場合、またはサンプルレート変換が完了した後、「将来の」サンプルが必要となる場合、サンプルは SWR にバッファされる可能性があることに注意してください。将来の入力を必要としないサンプルは、swr_convert() を使用していつでも取得できます (in_count を 0 に設定できます)。変換の最後に、incount と incount に NULL を指定して swr_convert() を呼び出すことで、リサンプリング バッファをフラッシュできます。

4. コードを実行する

「moonfdd/ffmpeg-go」を参照してください。

元のリンク:オーディオとビデオのステレオタイプ化エッセイ (11) -- ffmpeg audio resampling- Nuggets

おすすめ

転載: blog.csdn.net/irainsa/article/details/130661846