# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.

"""Extraction of annotations from audio files.
"""

from __future__ import division
import logging
import os
import shutil
import struct
import subprocess
import sys
import tempfile

try:
  import numpy as np
except ImportError:
  logging.critical('Cannot import the third-party Python package numpy')
  sys.exit(1)

from . import exceptions
from . import signal_processing


class AudioAnnotationsExtractor(object):
  """Extracts annotations from audio files.
  """

  # TODO(aleloi): change to enum.IntEnum when py 3.6 is available.
  class VadType(object):
    ENERGY_THRESHOLD = 1  # TODO(alessiob): Consider switching to P56 standard.
    WEBRTC_COMMON_AUDIO = 2  # common_audio/vad/include/vad.h
    WEBRTC_APM = 4  # modules/audio_processing/vad/vad.h

    def __init__(self, value):
      if (not isinstance(value, int)) or not 0 <= value <= 7:
        raise exceptions.InitializationException(
            'Invalid vad type: ' + value)
      self._value = value

    def Contains(self, vad_type):
      return self._value | vad_type == self._value

    def __str__(self):
      vads = []
      if self.Contains(self.ENERGY_THRESHOLD):
        vads.append("energy")
      if self.Contains(self.WEBRTC_COMMON_AUDIO):
        vads.append("common_audio")
      if self.Contains(self.WEBRTC_APM):
        vads.append("apm")
      return "VadType({})".format(", ".join(vads))

  _OUTPUT_FILENAME = 'annotations.npz'

  # Level estimation params.
  _ONE_DB_REDUCTION = np.power(10.0, -1.0 / 20.0)
  _LEVEL_FRAME_SIZE_MS = 1.0
  # The time constants in ms indicate the time it takes for the level estimate
  # to go down/up by 1 db if the signal is zero.
  _LEVEL_ATTACK_MS = 5.0
  _LEVEL_DECAY_MS = 20.0

  # VAD params.
  _VAD_THRESHOLD = 1
  _VAD_WEBRTC_PATH = os.path.join(os.path.dirname(
      os.path.abspath(__file__)), os.pardir, os.pardir)
  _VAD_WEBRTC_COMMON_AUDIO_PATH = os.path.join(_VAD_WEBRTC_PATH, 'vad')

  _VAD_WEBRTC_APM_PATH = os.path.join(
      _VAD_WEBRTC_PATH, 'apm_vad')

  def __init__(self, vad_type):
    self._signal = None
    self._level = None
    self._level_frame_size = None
    self._common_audio_vad = None
    self._energy_vad = None
    self._apm_vad_probs = None
    self._apm_vad_rms = None
    self._vad_frame_size = None
    self._vad_frame_size_ms = None
    self._c_attack = None
    self._c_decay = None

    self._vad_type = self.VadType(vad_type)
    logging.info('VADs used for annotations: ' + str(self._vad_type))

    assert os.path.exists(self._VAD_WEBRTC_COMMON_AUDIO_PATH), \
      self._VAD_WEBRTC_COMMON_AUDIO_PATH
    assert os.path.exists(self._VAD_WEBRTC_APM_PATH), \
      self._VAD_WEBRTC_APM_PATH

  @classmethod
  def GetOutputFileName(cls):
    return cls._OUTPUT_FILENAME

  def GetLevel(self):
    return self._level

  def GetLevelFrameSize(self):
    return self._level_frame_size

  @classmethod
  def GetLevelFrameSizeMs(cls):
    return cls._LEVEL_FRAME_SIZE_MS

  def GetVadOutput(self, vad_type):
    if vad_type == self.VadType.ENERGY_THRESHOLD:
      return (self._energy_vad, )
    elif vad_type == self.VadType.WEBRTC_COMMON_AUDIO:
      return (self._common_audio_vad, )
    elif vad_type == self.VadType.WEBRTC_APM:
      return (self._apm_vad_probs, self._apm_vad_rms)
    else:
      raise exceptions.InitializationException(
            'Invalid vad type: ' + vad_type)

  def GetVadFrameSize(self):
    return self._vad_frame_size

  def GetVadFrameSizeMs(self):
    return self._vad_frame_size_ms

  def Extract(self, filepath):
    # Load signal.
    self._signal = signal_processing.SignalProcessingUtils.LoadWav(filepath)
    if self._signal.channels != 1:
      raise NotImplementedError('multiple-channel annotations not implemented')

    # Level estimation params.
    self._level_frame_size = int(self._signal.frame_rate / 1000 * (
        self._LEVEL_FRAME_SIZE_MS))
    self._c_attack = 0.0 if self._LEVEL_ATTACK_MS == 0 else (
        self._ONE_DB_REDUCTION ** (
            self._LEVEL_FRAME_SIZE_MS / self._LEVEL_ATTACK_MS))
    self._c_decay = 0.0 if self._LEVEL_DECAY_MS == 0 else (
        self._ONE_DB_REDUCTION ** (
            self._LEVEL_FRAME_SIZE_MS / self._LEVEL_DECAY_MS))

    # Compute level.
    self._LevelEstimation()

    # Ideal VAD output, it requires clean speech with high SNR as input.
    if self._vad_type.Contains(self.VadType.ENERGY_THRESHOLD):
      # Naive VAD based on level thresholding.
      vad_threshold = np.percentile(self._level, self._VAD_THRESHOLD)
      self._energy_vad = np.uint8(self._level > vad_threshold)
      self._vad_frame_size = self._level_frame_size
      self._vad_frame_size_ms = self._LEVEL_FRAME_SIZE_MS
    if self._vad_type.Contains(self.VadType.WEBRTC_COMMON_AUDIO):
      # WebRTC common_audio/ VAD.
      self._RunWebRtcCommonAudioVad(filepath, self._signal.frame_rate)
    if self._vad_type.Contains(self.VadType.WEBRTC_APM):
      # WebRTC modules/audio_processing/ VAD.
      self._RunWebRtcApmVad(filepath)

  def Save(self, output_path):
    np.savez_compressed(
        file=os.path.join(output_path, self._OUTPUT_FILENAME),
        level=self._level,
        level_frame_size=self._level_frame_size,
        level_frame_size_ms=self._LEVEL_FRAME_SIZE_MS,
        vad_output=self._common_audio_vad,
        vad_energy_output=self._energy_vad,
        vad_frame_size=self._vad_frame_size,
        vad_frame_size_ms=self._vad_frame_size_ms,
        vad_probs=self._apm_vad_probs,
        vad_rms=self._apm_vad_rms
    )

  def _LevelEstimation(self):
    # Read samples.
    samples = signal_processing.SignalProcessingUtils.AudioSegmentToRawData(
        self._signal).astype(np.float32) / 32768.0
    num_frames = len(samples) // self._level_frame_size
    num_samples = num_frames * self._level_frame_size

    # Envelope.
    self._level = np.max(np.reshape(np.abs(samples[:num_samples]), (
        num_frames, self._level_frame_size)), axis=1)
    assert len(self._level) == num_frames

    # Envelope smoothing.
    smooth = lambda curr, prev, k: (1 - k) * curr  + k * prev
    self._level[0] = smooth(self._level[0], 0.0, self._c_attack)
    for i in range(1, num_frames):
      self._level[i] = smooth(
          self._level[i], self._level[i - 1], self._c_attack if (
              self._level[i] > self._level[i - 1]) else self._c_decay)

  def _RunWebRtcCommonAudioVad(self, wav_file_path, sample_rate):
    self._common_audio_vad = None
    self._vad_frame_size = None

    # Create temporary output path.
    tmp_path = tempfile.mkdtemp()
    output_file_path = os.path.join(
        tmp_path, os.path.split(wav_file_path)[1] + '_vad.tmp')

    # Call WebRTC VAD.
    try:
      subprocess.call([
          self._VAD_WEBRTC_COMMON_AUDIO_PATH,
          '-i', wav_file_path,
          '-o', output_file_path
      ], cwd=self._VAD_WEBRTC_PATH)

      # Read bytes.
      with open(output_file_path, 'rb') as f:
        raw_data = f.read()

      # Parse side information.
      self._vad_frame_size_ms = struct.unpack('B', raw_data[0])[0]
      self._vad_frame_size = self._vad_frame_size_ms * sample_rate / 1000
      assert self._vad_frame_size_ms in [10, 20, 30]
      extra_bits = struct.unpack('B', raw_data[-1])[0]
      assert 0 <= extra_bits <= 8

      # Init VAD vector.
      num_bytes = len(raw_data)
      num_frames = 8 * (num_bytes - 2) - extra_bits  # 8 frames for each byte.
      self._common_audio_vad = np.zeros(num_frames, np.uint8)

      # Read VAD decisions.
      for i, byte in enumerate(raw_data[1:-1]):
        byte = struct.unpack('B', byte)[0]
        for j in range(8 if i < num_bytes - 3 else (8 - extra_bits)):
          self._common_audio_vad[i * 8 + j] = int(byte & 1)
          byte = byte >> 1
    except Exception as e:
      logging.error('Error while running the WebRTC VAD (' + e.message + ')')
    finally:
      if os.path.exists(tmp_path):
        shutil.rmtree(tmp_path)

  def _RunWebRtcApmVad(self, wav_file_path):
    # Create temporary output path.
    tmp_path = tempfile.mkdtemp()
    output_file_path_probs = os.path.join(
        tmp_path, os.path.split(wav_file_path)[1] + '_vad_probs.tmp')
    output_file_path_rms = os.path.join(
        tmp_path, os.path.split(wav_file_path)[1] + '_vad_rms.tmp')

    # Call WebRTC VAD.
    try:
      subprocess.call([
          self._VAD_WEBRTC_APM_PATH,
          '-i', wav_file_path,
          '-o_probs', output_file_path_probs,
          '-o_rms', output_file_path_rms
      ], cwd=self._VAD_WEBRTC_PATH)

      # Parse annotations.
      self._apm_vad_probs = np.fromfile(output_file_path_probs, np.double)
      self._apm_vad_rms = np.fromfile(output_file_path_rms, np.double)
      assert len(self._apm_vad_rms) == len(self._apm_vad_probs)

    except Exception as e:
      logging.error('Error while running the WebRTC APM VAD (' +
                    e.message + ')')
    finally:
      if os.path.exists(tmp_path):
        shutil.rmtree(tmp_path)
