WebRTCオーディオサンプリングアルゴリズムは完全なC++サンプルコードを添付する
18002 ワード
以前はオーディオサンプリングに関する考え方を大まかに紹介したが,詳細は「簡潔明瞭な補間オーディオ再サンプリングアルゴリズムの例(完全なCコード付き)」を参照した.
オーディオに関するオープンソースプロジェクトはたくさんあります.
最も有名なのはグーグルオープンソースのWebRTCです.
オーディオモジュールには
AGCオートゲイン補正(Automatic Gain Control)は、マイクの収音量を自動調整し、参加者に一定の音量レベルを与え、発言者とマイクの距離が変わることなく、音が大きくなったり小さくなったりする欠点がある.
ANSバックグラウンドノイズ抑制(Automatic Noise Suppression)はバックグラウンド固定周波数の雑音を検出し、バックグラウンドノイズを除去する.
AECは、音響消去器(Acoustic Echo Canceller)がスピーカ信号とそれによって生成されたマルチパスエコーとの相関を基礎として、遠隔信号の音声モデルを構築し、それを利用して音響を推定し、フィルタの係数を絶えず修正し、推定値をよりリアルなエコーに近づける.そして、エコー推定値を受話器の入力信号から減算してエコーを除去する目的を達成し、AECはまた、受話器の入力をスピーカの過去の値と比較して、遅延した複数回反射した音響エコーを除去する.メモリに格納されている過去のスピーカの出力値の多少に基づいて、AECは各種の遅延したエコーを除去することができる.
「オーディオゲイン響度解析ReplayGain付属完全Cコード例」にも言及した.
しかし,本論文では,この3つのアルゴリズムに重点を置くのではなく,まずサンプリングアルゴリズムから来た.
もちろん興味のある方は、WebRTCでsignalとprocessing_library関連の操作アルゴリズム.
多くの最適化の構想が学ぶことができる.
ここも広がりません.
サンプリングは単純な補間でシミュレーション処理が可能であり,精度の要求が高くない場合には,前述した.
しかし精度が要求される場合は別とする.
幸いなことに、前人は穴を踏んで、後人は歩いています.
WebRTCにはオーディオサンプラのクラスがあり、一定の使用制限がありますが、多くのアプリケーションシーンでは十分です.
WebRTCのコードはとてもきれいで、どのようにして、各ヘッダファイルの間の依存、本当に混乱しています.
しかし、少し辛抱強く、コードを七七八八にすることができます.
少し時間をかけて、みんなに幸せをもたらしました.
WebRTCのサンプラコードを個別に抽出し、
C++サンプルコードを作成しました.
完全なサンプルコード:
プロジェクトのアドレス:https://github.com/cpuimage/WebRTC_Resampler
サンプラのコードは簡単です.詳細はresamplerを参照してください.cpp
例の具体的なプロセスは次のとおりです.
wavのロード(wavファイルを実行可能ファイルにドラッグ&ドロップ)->再サンプリング->保存先_out.wavファイル
例は比較的簡単で、cmakeでサンプルコードをコンパイルすることができ、詳細はCMakeListsを参照する.txt.
その他の関連問題や需要があれば、メールで私に連絡して検討してもいいです.
メールアドレスは次のとおりです[email protected]
転載先:https://www.cnblogs.com/cpuimage/p/8886729.html
オーディオに関するオープンソースプロジェクトはたくさんあります.
最も有名なのはグーグルオープンソースのWebRTCです.
オーディオモジュールには
AGCオートゲイン補正(Automatic Gain Control)は、マイクの収音量を自動調整し、参加者に一定の音量レベルを与え、発言者とマイクの距離が変わることなく、音が大きくなったり小さくなったりする欠点がある.
ANSバックグラウンドノイズ抑制(Automatic Noise Suppression)はバックグラウンド固定周波数の雑音を検出し、バックグラウンドノイズを除去する.
AECは、音響消去器(Acoustic Echo Canceller)がスピーカ信号とそれによって生成されたマルチパスエコーとの相関を基礎として、遠隔信号の音声モデルを構築し、それを利用して音響を推定し、フィルタの係数を絶えず修正し、推定値をよりリアルなエコーに近づける.そして、エコー推定値を受話器の入力信号から減算してエコーを除去する目的を達成し、AECはまた、受話器の入力をスピーカの過去の値と比較して、遅延した複数回反射した音響エコーを除去する.メモリに格納されている過去のスピーカの出力値の多少に基づいて、AECは各種の遅延したエコーを除去することができる.
「オーディオゲイン響度解析ReplayGain付属完全Cコード例」にも言及した.
しかし,本論文では,この3つのアルゴリズムに重点を置くのではなく,まずサンプリングアルゴリズムから来た.
もちろん興味のある方は、WebRTCでsignalとprocessing_library関連の操作アルゴリズム.
多くの最適化の構想が学ぶことができる.
ここも広がりません.
サンプリングは単純な補間でシミュレーション処理が可能であり,精度の要求が高くない場合には,前述した.
しかし精度が要求される場合は別とする.
幸いなことに、前人は穴を踏んで、後人は歩いています.
WebRTCにはオーディオサンプラのクラスがあり、一定の使用制限がありますが、多くのアプリケーションシーンでは十分です.
WebRTCのコードはとてもきれいで、どのようにして、各ヘッダファイルの間の依存、本当に混乱しています.
しかし、少し辛抱強く、コードを七七八八にすることができます.
少し時間をかけて、みんなに幸せをもたらしました.
WebRTCのサンプラコードを個別に抽出し、
C++サンプルコードを作成しました.
完全なサンプルコード:
#include
#include
#include
// https://github.com/mackron/dr_libs/blob/master/dr_wav.h
#define DR_WAV_IMPLEMENTATION
#include "dr_wav.h"
#include "resampler.h"
// wav
void wavWrite_int16(char *filename, int16_t *buffer, size_t sampleRate, size_t totalSampleCount) {
drwav_data_format format = {};
format.container = drwav_container_riff; //
format.format = DR_WAVE_FORMAT_PCM; //
format.channels = 1;
format.sampleRate = (drwav_uint32) sampleRate;
format.bitsPerSample = 16;
drwav *pWav = drwav_open_file_write(filename, &format);
if (pWav) {
drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);
drwav_uninit(pWav);
if (samplesWritten != totalSampleCount) {
fprintf(stderr, "ERROR
");
exit(1);
}
}
}
// wav
int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint64_t *totalSampleCount) {
unsigned int channels;
int16_t *buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount);
if (buffer == nullptr) {
printf(" wav .");
}
//
if (channels != 1) {
drwav_free(buffer);
buffer = nullptr;
*sampleRate = 0;
*totalSampleCount = 0;
}
return buffer;
}
//
void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {
const char *end;
const char *p;
const char *s;
if (path[0] && path[1] == ':') {
if (drv) {
*drv++ = *path++;
*drv++ = *path++;
*drv = '\0';
}
} else if (drv)
*drv = '\0';
for (end = path; *end && *end != ':';)
end++;
for (p = end; p > path && *--p != '\\' && *p != '/';)
if (*p == '.') {
end = p;
break;
}
if (ext)
for (s = end; (*ext = *s++);)
ext++;
for (p = end; p > path;)
if (*--p == '\\' || *p == '/') {
p++;
break;
}
if (name) {
for (s = p; s < end;)
*name++ = *s++;
*name = '\0';
}
if (dir) {
for (s = path; s < p;)
*dir++ = *s++;
*dir = '\0';
}
}
int16_t *resampler(int16_t *data_in, size_t totalSampleCount, size_t in_sample_rate, size_t out_sample_rate) {
if (data_in == nullptr)
return nullptr;
if (in_sample_rate == 0) return nullptr;
size_t lengthIn = in_sample_rate / 100;
size_t maxLen = out_sample_rate / 100;
const int channels = 1;
Resampler rs;
if (rs.Reset(in_sample_rate, out_sample_rate, channels) == -1)
return nullptr;
size_t outLen = (size_t) (totalSampleCount * out_sample_rate / in_sample_rate);
int16_t *data_out = (int16_t *) malloc(outLen * sizeof(int16_t));
if (data_out == nullptr) return nullptr;
size_t nCount = (totalSampleCount / lengthIn);
size_t nLast = totalSampleCount - (lengthIn * nCount);
int16_t *samplesIn = data_in;
int16_t *samplesOut = data_out;
outLen = 0;
for (int i = 0; i < nCount; i++) {
rs.Push(samplesIn, lengthIn, samplesOut, maxLen, outLen);
samplesIn += lengthIn;
samplesOut += outLen;
}
if (nLast != 0) {
const int max_samples = 1920;
int16_t samplePatchIn[max_samples] = {0};
int16_t samplePatchOut[max_samples] = {0};
memcpy(samplePatchIn, samplesIn, nLast * sizeof(int16_t));
rs.Push(samplesIn, nLast, samplePatchOut, maxLen, outLen);
memcpy(samplesOut, samplePatchOut, (nLast * out_sample_rate / in_sample_rate) * sizeof(int16_t));
}
return data_out;
}
void ResampleTo(char *in_file, char *out_file, size_t out_sample_rate = 16000) {
//
uint32_t sampleRate = 0;
//
uint64_t inSampleCount = 0;
int16_t *inBuffer = wavRead_int16(in_file, &sampleRate, &inSampleCount);
//
if (inBuffer != nullptr) {
int16_t *outBuffer = resampler(inBuffer, (size_t) inSampleCount, sampleRate, out_sample_rate);
if (outBuffer != nullptr) {
size_t outSampleCount = (size_t) (inSampleCount * (out_sample_rate * 1.0f / sampleRate));
wavWrite_int16(out_file, outBuffer, out_sample_rate, outSampleCount);
free(outBuffer);
}
free(inBuffer);
}
}
int main(int argc, char *argv[]) {
printf("WebRtc Resampler
");
printf(" :http://cpuimage.cnblogs.com/
");
printf("
");
printf(" : 8k、16k、32k、48k、96k
");
if (argc < 2)
return -1;
char *in_file = argv[1];
char drive[3];
char dir[256];
char fname[256];
char ext[256];
char out_file[1024];
splitpath(in_file, drive, dir, fname, ext);
sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);
ResampleTo(in_file, out_file, 64000);
printf("
");
getchar();
return 0;
}
プロジェクトのアドレス:https://github.com/cpuimage/WebRTC_Resampler
サンプラのコードは簡単です.詳細はresamplerを参照してください.cpp
例の具体的なプロセスは次のとおりです.
wavのロード(wavファイルを実行可能ファイルにドラッグ&ドロップ)->再サンプリング->保存先_out.wavファイル
例は比較的簡単で、cmakeでサンプルコードをコンパイルすることができ、詳細はCMakeListsを参照する.txt.
その他の関連問題や需要があれば、メールで私に連絡して検討してもいいです.
メールアドレスは次のとおりです[email protected]
転載先:https://www.cnblogs.com/cpuimage/p/8886729.html