webrtcのnativeビルドのaudioProcessingを使ってみる

# 概要

webrtcの内部には魅力的な動作がいくつかある。
個別に取り出して自作のアプリとかに入れることができると、高いクオリティのアプリを作ることができる。
(と思ってる)

今回はaudioProcessingの部分を取り出して利用してみようと思う。

# ちょうどいい具合のプロジェクトがあった。

https://github.com/freedesktop/pulseaudio-webrtc-audio-processing
ただ、linuxでのbuildはできるみたいですが、僕が使ってるOSXではうまくbuildできないみたいなので
改良してみた

https://github.com/taktod/pulseaudio-webrtc-audio-processing
autogen.shの中身変更しただけ。

# c++で利用してみる

cで利用してもいいんですが、webrtcのコードは基本c++で書かれていて、namespaceとか使っているため、c++で書くほうが作りやすいため、c++で書いてみることにする。

できたコードはこんな感じ。

https://github.com/taktod/pulseaudio-webrtc-audio-processing/tree/master/test

使い方は・・・

```
$ git clone https://github.com/taktod/pulseaudio-webrtc-audio-processing.git
$ cd pulseaudio-webrtc-audio-processing
$ ./autogen.sh
$ make
$ cd test
$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./webrtcInitializeTest
```

pulseaudio-webrtc-audio-processingを作ってから
testのディレクトリに移動してtestのコードをmakeして利用

コードはこんな感じ

```initializeTest.cpp
#include <iostream>

#include <modules/audio_processing/include/audio_processing.h>
#include <modules/interface/module_common_types.h>

using namespace std;
using namespace webrtc;

int main() {
  cout << "try to use webrtc audio processing." << endl;
  AudioFrame frame;
  int16_t buf[480];
  for(int i = 0;i < 480;++ i) {
    buf[i] = i;
  }
  frame.UpdateFrame(
    0, // id
    0, // timestamp
    buf, // data
    480, // sample per channel
    48000, // sample_rate
    AudioFrame::kNormalSpeech, // speech type
    AudioFrame::kVadActive); // vad activity
  AudioProcessing* apm = AudioProcessing::Create();
  apm->Initialize(
    48000, // input samplerate
    48000, // output samplerate
    48000, // reverse samplerate
    AudioProcessing::ChannelLayout::kMono, // input channel layout
    AudioProcessing::ChannelLayout::kMono, // output channel layout
    AudioProcessing::ChannelLayout::kMono  // reverse channel layout
  );
  apm->high_pass_filter()->Enable(true);
  apm->echo_cancellation()->enable_drift_compensation(false);
  apm->echo_cancellation()->Enable(true);

  apm->noise_suppression()->set_level(NoiseSuppression::Level::kHigh);
  apm->noise_suppression()->Enable(true);

  apm->gain_control()->set_analog_level_limits(0, 255);
  apm->gain_control()->set_mode(GainControl::Mode::kAdaptiveDigital);
  apm->gain_control()->Enable(true);

  for(int i = 0;i < 4;++ i) {
    apm->ProcessReverseStream(&frame);
    apm->set_stream_delay_ms(10);
    int err = apm->ProcessStream(&frame);
    cout << "result:" << err << endl;
    int16_t *buf = (int16_t *)frame.data_;
    for(int i = 0;i < 16;++ i) {
      cout << buf[i] << endl;
    }
  }
  delete apm;
  return 0;
}
```

とりあえず使えてはいるみたいですね。

1. 適当にAudioFrameオブジェクトを作る
UpdateFrameでpcmデータを登録する。16bit整数で入れれば良い模様
2. AudioProcessingのオブジェクト作って初期化
3. ProcessReverseStreamで外からやってきた音(スピーカーから鳴らしたい音)をapmに入れる
4. stream delayを適当に設定する
5. ProcessStreamでマイクで録音したデータをapmに入れると入れたframeの内容が結果に書き換えられる

という動作な模様

AudioProcessingはCreateすると内部でnewしているみたいなので、最後にdeleteで解放しておく必要がある模様

# コンパイル方法

使い方は簡単、コンパイルするのが面倒だった。

```CMakeLists.txt
cmake_minimum_required(VERSION 2.8)

add_definitions("-Wall -std=c++11")
add_definitions(-D__DIR__="${PROJECT_SOURCE_DIR}")
add_definitions(-DWEBRTC_POSIX)
add_definitions(-DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD)

include_directories(${PROJECT_SOURCE_DIR}/../webrtc)
include_directories(${PROJECT_SOURCE_DIR}/../)
link_directories(${PROJECT_SOURCE_DIR}/../webrtc/modules/audio_processing/.libs/)
add_executable(webrtcInitializeTest initializeTest.cpp)

target_link_libraries(webrtcInitializeTest
  webrtc_audio_processing
  )
```

c++11を使わないとwebrtcの定義周りがうまく使えない模様

WEBRTC_POSIXを定義しないとwebrtcで利用する環境の指定が入らず、エラーになる。

WEBRTC_AUDIO_PROCESSING_ONLY_BUILDを定義しないとvideo周りのコードが存在しないためエラーになる。
(このライブラリはaudioの部分だけ抜き出してある)

妙なところにありますがpulseaudio-webrtc-audio-processing/webrtc/modules/audio_processing/.libs/に目的のライブラリが出来上がるみたいですね。

# 今後学習していきたい

c++で実装利用できたので、iOSやandroidでも利用可能みたいですね。
まだ勉強不足で動作の効果がよくわかってないです。