opusコーデックの使用
4749 ワード
opusの概要と利点:
Opusは損失のある音声符号化のフォーマットで、Xiph.Org財団が開発した後、インターネットエンジニアリングタスクグループ(IETF)によって標準化され、SPeexとVorbisの代わりに単一のフォーマットで音声と音声を含むことが望ましいことを目標とし、ネットワーク上の低遅延のインスタント音声伝送に適用され、標準フォーマットはRFC 6716ファイルに定義されている.Opusフォーマットはオープンフォーマットであり、使用上特許や制限はありません.Opusは,音声符号化を指向したSILKと低遅延CELTの2つの音声符号化技術を統合した.Opusは高低ビットレートをシームレスに調整できる.エンコーダ内部では、より低いビットレートで線形予測符号化を用い、高いビットレートでは変換符号化を用いる(高低ビットレート境界でも両者を組み合わせた符号化方式を用いる).Opusは非常に低いアルゴリズム遅延(デフォルト22.5 ms)を有し、ネットワーク上のインスタント音声ストリーム、インスタント同期音声ナレーションなどの低遅延音声通話の符号化に非常に適している.また、Opusは符号化ビットレートを低減することによって、より低いアルゴリズム遅延を達成することができ、最低5 msまで可能である.複数の聴覚盲検では、OpusはMP 3、AAC、HE−ACなどの一般的なフォーマットよりも低く、より低い遅延とより良い音声圧縮率を有する.
decodeステップと踏んだ穴を使用します。
手順:
1.opusデコーダの作成:
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
opus_int32 Fs,// , 8000, 12000, 16000, 24000, 48000.
int channels,// ,
int *error// , 0
);
2.復号化:
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
OpusDecoder *st, //
const unsigned char *data,//
opus_int32 len, //
opus_int16 *pcm, // , 16
int frame_size, // pcm
int decode_fec // fec, 0 ,1
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
3.復号データを文字配列に入れる
//大端着信であることに注意//注:frameSizeは、前のステップの戻り値、すなわち、各チャネルで返される2バイト単位の配列長//pcmは復号後のデータ、すなわち、前のステップのパラメータ4
char *pcmData = new char[frameSize * channels * sizeof(opus_int16)];
for (int i = 0; i < channels * frameSize; ++i)
{
pcmData[i * 2] = pcm[i] & 0xFF;
pcmData[i * 2 + 1] = (pcm[i] >> 8) & 0xFF;
}
4.デコーダを解放する
OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
踏んだ穴:
1.連続した音声の場合、必ず1つのデコーダしか使用できない(作成後に解放してからデコーダを作成することはできない)
2.fecを使用する場合は、seqを自分でチェックして紛失を確認してからfecを使用し、パケットごとにfecを使用すると、それぞれが復号されます。
demo、およびdecodeを使用してまとめます
demo
class HandlerOpusImpl
{
public:
//
HandlerOpusImpl() : _perSecNum(0)
{
int sampleRate = 48000;
int channels = 1;
int err;
_decoder = opus_decoder_create(sampleRate, channels, &err);
}
// srcData, string result
bool DecodeData(std::string srcData, std::string &result)
{
int frameSize;
int channels = CHANNELS;
int sampleRate = SAMPLE_RATE;
opus_int16 *out;
char *pcmData;
out = new opus_int16[SAMPLE_RATE / 50 * CHANNELS];
// , frameSize 0,
frameSize = opus_decode(_decoder, (const unsigned char *)srcData.data(), srcData.size(), out, SAMPLE_RATE / 50 * CHANNELS, 0);
if (frameSize <= 0)
{
return false;
}
pcmData = new char[frameSize * channels * sizeof(opus_int16)];
++_perSecNum;
for (int i = 0; i < channels * frameSize; ++i)
{
pcmData[i * 2] = out[i] & 0xFF;
pcmData[i * 2 + 1] = (out[i] >> 8) & 0xFF;
}
// result
std::string(pcmData, sizeof(opus_int16) * channels * frameSize).swap(result);
delete[]out;
delete[]pcmData;
return true;
}
// fec , , fec 1
bool HandleLosePack(std::string srcData, std::string &result)
{
int frameSize;
int channels = CHANNELS;
int sampleRate = SAMPLE_RATE;
opus_int16 *out;
char *pcmData;
out = new opus_int16[SAMPLE_RATE / 50 * CHANNELS];
frameSize = opus_decode(_decoder, NULL, 0, out, SAMPLE_RATE / 50 * CHANNELS, 1);
if (frameSize <= 0)
{
return false;
}
pcmData = new char[frameSize * channels * sizeof(opus_int16)];
++_perSecNum;
for (int i = 0; i < channels * frameSize; ++i)
{
pcmData[i * 2] = out[i] & 0xFF;
pcmData[i * 2 + 1] = (out[i] >> 8) & 0xFF;
}
std::string(pcmData, sizeof(opus_int16) * channels * frameSize).swap(result);
delete[]out;
delete[]pcmData;
return true;
}
void DeleteCodec()
{
opus_decoder_destroy(_decoder);
_decoder = NULL;
}
private:
int _perSecNum;
OpusDecoder *_decoder;
};
まとめ:
opusの使用は複雑ではありませんが、ネット上の資料は限られています.お兄さんたちが前に書いたコードで少し理解しました.皆さんに助けてほしいです.上のコードはプログラムの一部で、直接使うことはできません.