1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
2152c34cf11927193c0b29ddf2545e392e603aa82bjornv@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11aa30bb7ef5b02c9026dc2c036a0bed9999ae4cf2pbos@webrtc.org#include "webrtc/common_audio/vad/include/webrtc_vad.h"
12b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org
13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <stdlib.h>
14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <string.h>
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
16aa30bb7ef5b02c9026dc2c036a0bed9999ae4cf2pbos@webrtc.org#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
17aa30bb7ef5b02c9026dc2c036a0bed9999ae4cf2pbos@webrtc.org#include "webrtc/common_audio/vad/vad_core.h"
18aa30bb7ef5b02c9026dc2c036a0bed9999ae4cf2pbos@webrtc.org#include "webrtc/typedefs.h"
19470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comstatic const int kInitCheck = 42;
21ef433579cb8319e93f75a27bde4b348c87537278tina.legrand@webrtc.orgstatic const int kValidRates[] = { 8000, 16000, 32000, 48000 };
22b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.orgstatic const size_t kRatesSize = sizeof(kValidRates) / sizeof(*kValidRates);
23b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.orgstatic const int kMaxFrameLengthMs = 30;
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
25de4703c5d1290da22feeb708fe915179884e210fBjorn VolckerVadInst* WebRtcVad_Create() {
26de4703c5d1290da22feeb708fe915179884e210fBjorn Volcker  VadInstT* self = (VadInstT*)malloc(sizeof(VadInstT));
27470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
28ac4d70de04acabec539753eef6e1252cb2dd1fbckma@webrtc.org  WebRtcSpl_Init();
2926e8a58130160ca2be411ed7ea2097a1d0252090bjornv@webrtc.org  self->init_flag = 0;
30470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
31de4703c5d1290da22feeb708fe915179884e210fBjorn Volcker  return (VadInst*)self;
32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
342a796720f8b2b4e6fbcbf58e687781e412e4dc38bjornv@webrtc.orgvoid WebRtcVad_Free(VadInst* handle) {
3526e8a58130160ca2be411ed7ea2097a1d0252090bjornv@webrtc.org  free(handle);
36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
38ed700db014a5dc533a7dc7b70630863847956792bjornv@webrtc.org// TODO(bjornv): Move WebRtcVad_InitCore() code here.
392a4dcd7d156c0ace8addb9d6256872e141f4b7bcbjornv@webrtc.orgint WebRtcVad_Init(VadInst* handle) {
402a4dcd7d156c0ace8addb9d6256872e141f4b7bcbjornv@webrtc.org  // Initialize the core VAD component.
412a4dcd7d156c0ace8addb9d6256872e141f4b7bcbjornv@webrtc.org  return WebRtcVad_InitCore((VadInstT*) handle);
42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4478f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org// TODO(bjornv): Move WebRtcVad_set_mode_core() code here.
4578f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.orgint WebRtcVad_set_mode(VadInst* handle, int mode) {
4678f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org  VadInstT* self = (VadInstT*) handle;
47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4878f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org  if (handle == NULL) {
4978f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org    return -1;
5078f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org  }
5178f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org  if (self->init_flag != kInitCheck) {
5278f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org    return -1;
5378f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org  }
54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5578f0cdc1911a18b2c64f9a5815226be2c8dea6bfbjornv@webrtc.org  return WebRtcVad_set_mode_core(self, mode);
56470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
57470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5865f933899b815b6c09f8ca7beefeace09ee3ae70andrew@webrtc.orgint WebRtcVad_Process(VadInst* handle, int fs, const int16_t* audio_frame,
59dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                      size_t frame_length) {
60b38fca1ec2807c10c76f0a0f6998183f39dc4293bjornv@webrtc.org  int vad = -1;
61b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  VadInstT* self = (VadInstT*) handle;
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
63b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  if (handle == NULL) {
64b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    return -1;
65b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  }
66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
67b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  if (self->init_flag != kInitCheck) {
68b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    return -1;
69b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  }
70b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  if (audio_frame == NULL) {
71b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    return -1;
72b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  }
73b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  if (WebRtcVad_ValidRateAndFrameLength(fs, frame_length) != 0) {
74b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    return -1;
75b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  }
76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
77ef433579cb8319e93f75a27bde4b348c87537278tina.legrand@webrtc.org  if (fs == 48000) {
78ef433579cb8319e93f75a27bde4b348c87537278tina.legrand@webrtc.org      vad = WebRtcVad_CalcVad48khz(self, audio_frame, frame_length);
79ef433579cb8319e93f75a27bde4b348c87537278tina.legrand@webrtc.org  } else if (fs == 32000) {
80b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    vad = WebRtcVad_CalcVad32khz(self, audio_frame, frame_length);
81b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  } else if (fs == 16000) {
82b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    vad = WebRtcVad_CalcVad16khz(self, audio_frame, frame_length);
83b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  } else if (fs == 8000) {
84b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    vad = WebRtcVad_CalcVad8khz(self, audio_frame, frame_length);
85b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  }
86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
87b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  if (vad > 0) {
88b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    vad = 1;
89b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  }
90b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  return vad;
91b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org}
92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
93dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingint WebRtcVad_ValidRateAndFrameLength(int rate, size_t frame_length) {
94b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  int return_value = -1;
95b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  size_t i;
96b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  int valid_length_ms;
97dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t valid_length;
98b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org
99b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  // We only allow 10, 20 or 30 ms frames. Loop through valid frame rates and
100b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  // see if we have a matching pair.
101b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  for (i = 0; i < kRatesSize; i++) {
102b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org    if (kValidRates[i] == rate) {
103b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org      for (valid_length_ms = 10; valid_length_ms <= kMaxFrameLengthMs;
104b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org          valid_length_ms += 10) {
105dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        valid_length = (size_t)(kValidRates[i] / 1000 * valid_length_ms);
106b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org        if (frame_length == valid_length) {
107b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org          return_value = 0;
108b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org          break;
109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
110b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org      }
111b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org      break;
112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
113b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  }
114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
115b1c3276f5a64741a09fd28f063a5ca34ed9473cfbjornv@webrtc.org  return return_value;
116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
117