/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJMEDIA_SILENCE_DET_H__
#define __PJMEDIA_SILENCE_DET_H__


/**
 * @file silencedet.h
 * @brief Adaptive silence detector.
 */
#include <pjmedia/types.h>


/**
 * @defgroup PJMEDIA_SILENCEDET Adaptive Silence Detection
 * @ingroup PJMEDIA_FRAME_OP
 * @brief Adaptive Silence Detector
 * @{
 */


PJ_BEGIN_DECL


/**
 * Opaque declaration for silence detector.
 */
typedef struct pjmedia_silence_det pjmedia_silence_det;



/**
 * Create voice activity detector with default settings. The default settings
 * are set to adaptive silence detection with the default threshold.
 *
 * @param pool              Pool for allocating the structure.
 * @param clock_rate        Clock rate.
 * @param samples_per_frame Number of samples per frame. The clock_rate and
 *                          samples_per_frame is only used to calculate the
 *                          frame time, from which some timing parameters
 *                          are calculated from.
 * @param p_sd              Pointer to receive the silence detector instance.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool,
                                                 unsigned clock_rate,
                                                 unsigned samples_per_frame,
                                                 pjmedia_silence_det **p_sd );


/**
 * Set silence detector name to identify the particular silence detector
 * instance in the log.
 *
 * @param sd                The silence detector.
 * @param name              Name.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_silence_det_set_name(pjmedia_silence_det *sd,
                                                  const char *name);


/**
 * Set the sd to operate in fixed threshold mode. With fixed threshold mode,
 * the threshold will not be changed adaptively.
 *
 * @param sd                The silence detector
 * @param threshold         The silence threshold, or -1 to use default
 *                          threshold.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_silence_det_set_fixed( pjmedia_silence_det *sd,
                                                    int threshold );

/**
 * Set the sd to operate in adaptive mode. This is the default mode
 * when the silence detector is created.
 *
 * @param sd                The silence detector
 * @param threshold         Initial threshold to be set, or -1 to use default
 *                          threshold.
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_silence_det_set_adaptive(pjmedia_silence_det *sd,
                                                      int threshold);

/**
 * Set other silence detector parameters.
 *
 * @param sd                The silence detector
 * @param before_silence    Minimum duration of silence (in msec) before
 *                          silence is reported. If -1 is specified, then
 *                          the default value will be used. The default is
 *                          400 msec.
 * @param recalc_time1      The interval (in msec) to recalculate threshold
 *                          in non-silence condition when adaptive silence
 *                          detection is set. If -1 is specified, then the
 *                          default value will be used. The default is 4000
 *                          (msec).
 * @param recalc_time2      The interval (in msec) to recalculate threshold
 *                          in silence condition when adaptive silence detection
 *                          is set. If -1 is specified, then the default value
 *                          will be used. The default value is 2000 (msec).
 *
 * @return                  PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_silence_det_set_params( pjmedia_silence_det *sd,
                                                     int before_silence,
                                                     int recalc_time1,
                                                     int recalc_time2);


/**
 * Parameters for #pjmedia_silence_det_set_params2(). Use
 * #pjmedia_silence_det_param_default() to initialize with default values,
 * then override specific fields as needed.
 */
typedef struct pjmedia_silence_det_param
{
    /**
     * Minimum duration of silence (in msec) before silence is reported.
     * Specify -1 for default (400 ms).
     */
    int     before_silence;

    /**
     * The interval (in msec) to recalculate threshold in non-silence
     * (voiced) condition. Specify -1 for default (4000 ms).
     */
    int     recalc_on_voiced;

    /**
     * The interval (in msec) to recalculate threshold in silence condition.
     * Specify -1 for default (2000 ms).
     */
    int     recalc_on_silence;

    /**
     * Minimum threshold for adaptive mode. The adaptive threshold will
     * never drop below this value, preventing false voice detection in
     * very quiet environments. Specify -1 for default (20). Set to 0
     * to disable.
     */
    int     min_threshold;

} pjmedia_silence_det_param;


/**
 * Initialize silence detector parameters with default values.
 *
 * @param p     The parameter structure to initialize.
 */
PJ_INLINE(void) pjmedia_silence_det_param_default(
                                        pjmedia_silence_det_param *p)
{
    p->before_silence = -1;
    p->recalc_on_voiced = -1;
    p->recalc_on_silence = -1;
    p->min_threshold = -1;
}


/**
 * Set silence detector parameters using a parameter structure. This is an
 * extended version of #pjmedia_silence_det_set_params() that supports
 * additional settings such as minimum adaptive threshold.
 *
 * @param sd    The silence detector.
 * @param p     The parameter structure.
 *
 * @return      PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_silence_det_set_params2(
                                        pjmedia_silence_det *sd,
                                        const pjmedia_silence_det_param *p);


/**
 * Disable the silence detector.
 *
 * @param sd            The silence detector
 *
 * @return              PJ_SUCCESS on success.
 */
PJ_DECL(pj_status_t) pjmedia_silence_det_disable( pjmedia_silence_det *sd );


/**
 * Perform voice activity detection on the given input samples. This
 * function uses #pjmedia_calc_avg_signal() and #pjmedia_silence_det_apply()
 * for its calculation.
 *
 * @param sd            The silence detector instance.
 * @param samples       Pointer to 16-bit PCM input samples.
 * @param count         Number of samples in the input.
 * @param p_level       Optional pointer to receive average signal level
 *                      of the input samples.
 *
 * @return              Non zero if signal is silence.
 */
PJ_DECL(pj_bool_t) pjmedia_silence_det_detect( pjmedia_silence_det *sd,
                                               const pj_int16_t samples[],
                                               pj_size_t count,
                                               pj_int32_t *p_level);


/**
 * Calculate average signal level for the given samples.
 *
 * @param samples       Pointer to 16-bit PCM samples.
 * @param count         Number of samples in the input.
 *
 * @return              The average signal level, which simply is total level
 *                      divided by number of samples.
 */
PJ_DECL(pj_int32_t) pjmedia_calc_avg_signal( const pj_int16_t samples[],
                                             pj_size_t count );



/**
 * Perform voice activity detection, given the specified average signal
 * level.
 *
 * @param sd            The silence detector instance.
 * @param level         Signal level.
 *
 * @return              Non zero if signal is silence.
 */
PJ_DECL(pj_bool_t) pjmedia_silence_det_apply( pjmedia_silence_det *sd,
                                              pj_uint32_t level);



PJ_END_DECL


/**
 * @}
 */


#endif  /* __PJMEDIA_SILENCE_DET_H__ */

