Commit 636f9e1d authored by Erwan Croze's avatar Erwan Croze 👋🏻

Add WebRTC VAD plugin

parent df80ca50
......@@ -40,6 +40,7 @@ option(ENABLE_AEC "Enable the WebRTC echo canceller support." YES)
option(ENABLE_AECM "Enable the WebRTC echo canceller for mobile support." YES)
option(ENABLE_ISAC "Enable the ISAC audio codec support." YES)
option(ENABLE_ILBC "Build iLBC codec filter" YES)
option(ENABLE_VAD "Build the WebRTC VAD support" YES)
set(ISAC_FLAVOUR "fix" CACHE STRING "ISAC audio codec flavour.")
set_property(CACHE ISAC_FLAVOUR PROPERTY STRINGS "fix" "main")
......@@ -81,6 +82,9 @@ endif()
if(ENABLE_ILBC)
set(BUILD_ILBC 1)
endif()
if(ENABLE_VAD)
set(BUILD_VAD 1)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
set(WEBRTC_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/webrtc")
......@@ -199,7 +203,7 @@ if(ENABLE_AEC)
-DWEBRTC_ARCH_ARM64=1
)
endif()
if(SYSTEM_PROCESSOR MATCHES "^arm.*" OR SYSTEM_PROCESSOR MATCHES "^aarch64.*")
list(APPEND AEC_SRCS
${AEC_SRC_DIR}/aec_core_neon.c
......@@ -368,6 +372,20 @@ if(ENABLE_ILBC)
include_directories(${ILBC_SRC_DIR}/include)
endif()
if(ENABLE_VAD)
set(VAD_SRC_DIR ${WEBRTC_SRC_DIR}/common_audio/vad)
set(VAD_SRCS
vad.cc
${VAD_SRC_DIR}/vad.cc
${VAD_SRC_DIR}/vad_core.c
${VAD_SRC_DIR}/vad_filterbank.c
${VAD_SRC_DIR}/vad_gmm.c
${VAD_SRC_DIR}/vad_sp.c
${VAD_SRC_DIR}/webrtc_vad.c
)
include_directories(${VAD_SRC_DIR}/include)
endif()
set(SOURCE_FILES
mswebrtc.c
${WEBRTC_COMMON_SRCS}
......@@ -385,11 +403,14 @@ endif()
if(ENABLE_ILBC)
list(APPEND SOURCE_FILES ${ILBC_SRCS})
endif()
if(ENABLE_VAD)
list(APPEND SOURCE_FILES ${VAD_SRCS})
endif()
set(LIBS ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES})
if(LIBM)
list(APPEND LIBS ${LIBM})
list(APPEND LIBS ${LIBM})
endif()
if(ENABLE_STATIC)
......@@ -416,8 +437,8 @@ if(ENABLE_SHARED)
set_target_properties(mswebrtc PROPERTIES
FRAMEWORK TRUE
MACOSX_FRAMEWORK_IDENTIFIER org.linphone.mswebrtc
MACOSX_FRAMEWORK_INFO_PLIST Info.plist.in
)
MACOSX_FRAMEWORK_INFO_PLIST Info.plist.in
)
endif()
if(MSVC)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
......
......@@ -35,3 +35,4 @@
#cmakedefine BUILD_AECM
#cmakedefine BUILD_ISAC
#cmakedefine BUILD_ILBC
#cmakedefine BUILD_VAD
......@@ -50,6 +50,9 @@ extern MSFilterDesc ms_webrtc_aecm_desc;
extern MSFilterDesc ms_webrtc_ilbc_enc_desc;
extern MSFilterDesc ms_webrtc_ilbc_dec_desc;
#endif
#ifdef BUILD_VAD
extern MSFilterDesc ms_webrtc_vad_desc;
#endif
#ifndef VERSION
#define VERSION "debug"
......@@ -68,7 +71,7 @@ MS_PLUGIN_DECLARE ( void ) libmswebrtc_init(MSFactory* factory) {
#ifdef BUILD_ILBC
char ilbc_version[20] = "";
#endif
WebRtcSpl_Init();
#ifdef BUILD_ISAC
......@@ -87,6 +90,9 @@ MS_PLUGIN_DECLARE ( void ) libmswebrtc_init(MSFactory* factory) {
ms_factory_register_filter(factory, &ms_webrtc_ilbc_enc_desc);
ms_factory_register_filter(factory, &ms_webrtc_ilbc_dec_desc);
#endif
#ifdef BUILD_VAD
ms_factory_register_filter(factory, &ms_webrtc_vad_desc);
#endif
ms_message("libmswebrtc " VERSION " plugin loaded"
#ifdef BUILD_ISAC
......
/*
vad.cc
Copyright (C) 2018 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "webrtc_vad.h"
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msticker.h"
#define NUMBER_SAMPLE_RATES 4
static const int _sample_rates[NUMBER_SAMPLE_RATES] = {8000, 16000, 32000, 48000};
typedef struct MSWebRTCVAD {
VadInst *instance = nullptr;
int sample_rate = 8000;
int enable = 1; // Disable if the sample rate doesn't match webrtc requirement
int silence_detection_enabled = 0; // silence detection enabled information
uint64_t silence_duration = 0; // silence threshold duration in ms
uint64_t last_voice_detection = 0; // last time voice was detected
int silence_event_send = 0;
} MSWebRTCVAD;
static int check_webrtc_sample_rate(MSFilter *f) {
MSWebRTCVAD *vad = static_cast<MSWebRTCVAD*>(f->data);
for (unsigned int i = 0 ; i < NUMBER_SAMPLE_RATES ; i++) {
if (_sample_rates[i] == vad->sample_rate) return 1;
}
ms_warning("MSWebRTC VAD: VAD disabled, sample rate(%d) doesn't match requirement", vad->sample_rate);
return 0;
}
static int vad_enable_silence_detection(MSFilter *f, void *arg) {
MSWebRTCVAD *vad = static_cast<MSWebRTCVAD*>(f->data);
vad->silence_detection_enabled = *(int*)arg;
return 0;
}
static int vad_set_silence_duration_threshold(MSFilter *f, void *arg) {
MSWebRTCVAD *vad = static_cast<MSWebRTCVAD*>(f->data);
vad->silence_duration = *(unsigned int*)arg;
return 0;
}
static int vad_set_mode(MSFilter *f, void *arg) {
MSWebRTCVAD *vad = static_cast<MSWebRTCVAD*>(f->data);
int mode = *(int*)arg;
if (WebRtcVad_set_mode(vad->instance, mode) == -1) {
ms_warning("MSWebRTC VAD: can't set mode %d", mode);
}
return 0;
}
static int vad_set_sample_rate(MSFilter *f, void *arg) {
MSWebRTCVAD *vad = static_cast<MSWebRTCVAD*>(f->data);
vad->sample_rate = *(int*)arg;
vad->enable = check_webrtc_sample_rate(f);
return 0;
}
static void vad_init(MSFilter *f) {
MSWebRTCVAD *vad = new MSWebRTCVAD();
vad->instance = WebRtcVad_Create();
if (WebRtcVad_Init(vad->instance) == -1) {
vad->instance = nullptr;
}
f->data = vad;
}
static void vad_process(MSFilter *f) {
mblk_t *im;
MSWebRTCVAD *vad = static_cast<MSWebRTCVAD*>(f->data);
while ((im = ms_queue_get(f->inputs[0]))) {
if (vad->enable && vad->instance && vad->silence_duration > 0) {
// Voice detected
if (WebRtcVad_Process(vad->instance, vad->sample_rate, (int16_t*)im->b_rptr, msgdsize(im)/2)) {
if (vad->silence_event_send) {
uint64_t silence_time = f->ticker->time - vad->last_voice_detection;
ms_filter_notify(f, MS_VAD_EVENT_SILENCE_ENDED, (void*)&silence_time);
ms_message("Silence end at %llu with %llu ms of silence", (unsigned long long)f->ticker->time, (unsigned long long)silence_time);
}
vad->last_voice_detection = f->ticker->time;
vad->silence_event_send = 0;
} else if ((vad->last_voice_detection + vad->silence_duration) <= f->ticker->time) {
if (!vad->silence_event_send) {
ms_filter_notify_no_arg(f, MS_VAD_EVENT_SILENCE_DETECTED);
ms_message("Silence begin at %llu", (unsigned long long)f->ticker->time);
}
vad->silence_event_send = 1;
}
}
ms_queue_put(f->outputs[0], im);
}
}
static void vad_uninit(MSFilter *f) {
MSWebRTCVAD *vad = static_cast<MSWebRTCVAD*>(f->data);
if (vad->instance) WebRtcVad_Free(vad->instance);
vad->instance = nullptr;
delete vad;
f->data = nullptr;
}
static MSFilterMethod vad_methods[]={
{ MS_VAD_ENABLE_SILENCE_DETECTION, vad_enable_silence_detection },
{ MS_VAD_SET_SILENCE_DURATION_THRESHOLD, vad_set_silence_duration_threshold},
{ MS_VAD_SET_MODE, vad_set_mode},
{ MS_FILTER_SET_SAMPLE_RATE, vad_set_sample_rate},
{ 0, nullptr }
};
MSFilterDesc ms_webrtc_vad_desc={
MS_FILTER_PLUGIN_ID,
"MSWebRtcVADDec",
"WebRtc's VAD",
MS_FILTER_OTHER,
"VAD",
1, // Inputs
1, // Outputs
vad_init,
nullptr,
vad_process,
nullptr,
vad_uninit,
vad_methods,
MS_FILTER_IS_PUMP
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment