/**
   * Decode.
   *
   * @param nbComp the nb comp
   * @param threshold the threshold
   * @param clusterSet the cluster set
   * @param featureSet the feature set
   * @param parameter the parameter
   * @return the cluster set
   * @throws Exception the exception
   */
  public ClusterSet decode(
      int nbComp,
      double threshold,
      ClusterSet clusterSet,
      AudioFeatureSet featureSet,
      Parameter parameter)
      throws Exception {
    String mask = parameter.getParameterSegmentationOutputFile().getMask();
    String oldModelKind = parameter.getParameterModel().getModelKindAsString();
    int oldNumberOfComponent = parameter.getParameterModel().getNumberOfComponents();

    // ** Train GMM for each cluster.
    // ** GMM is a 8 component gaussian with diagonal covariance matrix
    // ** one GMM = one speaker = one cluster
    // ** initialization of the GMMs :
    // ** - same global covariance for each gaussian,
    // ** - 1/8 for the weight,
    // ** - means are initialized with the mean of 10 successive vectors taken
    parameter.getParameterModel().setModelKind("DIAG");
    parameter.getParameterModel().setNumberOfComponents(nbComp);
    GMMArrayList gmmInitVect = new GMMArrayList(clusterSet.clusterGetSize());
    MTrainInit.make(featureSet, clusterSet, gmmInitVect, parameter);
    // ** EM training of the initialized GMM
    GMMArrayList gmmVect = new GMMArrayList(clusterSet.clusterGetSize());
    MTrainEM.make(featureSet, clusterSet, gmmInitVect, gmmVect, parameter);

    // ** set the penalty to move from the state i to the state j, penalty to move from i to i is
    // equal to 0
    parameter.getParameterDecoder().setDecoderPenalty(String.valueOf(threshold));
    // ** make Viterbi decoding using the 8-GMM set
    // ** one state = one GMM = one speaker = one cluster
    ClusterSet clustersDClust = MDecode.make(featureSet, clusterSet, gmmVect, parameter);
    if (parameter.getParameterDiarization().isSaveAllStep()) {
      parameter.getParameterSegmentationOutputFile().setMask(mask + ".d.seg");
      MainTools.writeClusterSet(parameter, clustersDClust, false);
    }
    // ** move the boundaries of the segment in low energy part of the signal
    ClusterSet clustersAdjClust = SAdjSeg.make(featureSet, clustersDClust, parameter);
    if (parameter.getParameterDiarization().isSaveAllStep()) {
      parameter.getParameterSegmentationOutputFile().setMask(mask + ".adj.seg");
      MainTools.writeClusterSet(parameter, clustersAdjClust, false);
    }

    parameter.getParameterSegmentationOutputFile().setMask(mask);
    parameter.getParameterModel().setNumberOfComponents(oldNumberOfComponent);
    parameter.getParameterModel().setModelKind(oldModelKind);
    return clustersAdjClust;
  }
  /**
   * Speech.
   *
   * @param threshold the threshold
   * @param clustersSetBase the clusters set base
   * @param clustersSegInit the clusters seg init
   * @param clustersDClust the clusters d clust
   * @param featureSet the feature set
   * @param parameter the parameter
   * @return the cluster set
   * @throws Exception the exception
   */
  public ClusterSet speech(
      String threshold,
      ClusterSet clustersSetBase,
      ClusterSet clustersSegInit,
      ClusterSet clustersDClust,
      AudioFeatureSet featureSet,
      Parameter parameter)
      throws Exception {
    String mask = parameter.getParameterSegmentationOutputFile().getMask();
    String oldDecoderPenalty = parameter.getParameterDecoder().getDecoderPenaltyAsString();

    // ** Reload MFCC, remove energy and add delta
    String FeatureFormat = "featureSetTransformation";
    AudioFeatureSet featureSet2 =
        loadFeature(
            featureSet, parameter, clustersSetBase, FeatureFormat + ",1:3:2:0:0:0,13,0:0:0:0");
    String dir = "ester2";
    // ** load the model : 8 GMMs with 64 diagonal components
    InputStream pmsInputStream = getClass().getResourceAsStream(dir + "/sms.gmms");
    GMMArrayList pmsVect =
        MainTools.readGMMContainer(pmsInputStream, parameter.getParameterModel());
    // ** set penalties for the i to j states
    // ** 10 for the first and second model corresponding to boad/narrowband silence
    // ** 50 for the other jingle speech (f0 f2 f3 fx), jingle and music

    parameter.getParameterDecoder().setDecoderPenalty(threshold);
    ClusterSet clustersPMSClust = MDecode.make(featureSet2, clustersSegInit, pmsVect, parameter);
    if (parameter.getParameterDiarization().isSaveAllStep()) {
      parameter.getParameterSegmentationOutputFile().setMask(mask + ".sms.seg");
      MainTools.writeClusterSet(parameter, clustersPMSClust, false);
    }

    parameter.getParameterSegmentationOutputFile().setMask(mask);
    parameter.getParameterDecoder().setDecoderPenalty(oldDecoderPenalty);

    // ** Filter the segmentation adj acoording the sms segmentation
    // ** add 25 frames to all speech segments
    // ** remove silence part if silence segment is less than 25 frames
    // ** if a speech segment is less than 150 frames, it will be merge to the left or right closest
    // segments

    int oldSegmentPadding = parameter.getParameterFilter().getSegmentPadding();
    int oldSilenceMinimumLength = parameter.getParameterFilter().getSilenceMinimumLength();
    int oldSpeechMinimumLength = parameter.getParameterFilter().getSpeechMinimumLength();
    String oldSegmentationFilterFile =
        parameter.getParameterSegmentationFilterFile().getClusterFilterName();
    parameter.getParameterFilter().setSegmentPadding(25);
    parameter.getParameterFilter().setSilenceMinimumLength(25);
    parameter.getParameterFilter().setSpeechMinimumLength(150);

    ClusterSet clustersFltClust = SFilter.make(clustersDClust, clustersPMSClust, parameter);
    if (parameter.getParameterDiarization().isSaveAllStep()) {
      parameter.getParameterSegmentationOutputFile().setMask(mask + ".flt.seg");
      MainTools.writeClusterSet(parameter, clustersFltClust, false);
      parameter.getParameterSegmentationOutputFile().setMask(mask);
    }

    // ** segments of more than 20s are split according of silence present in the pms or using a gmm
    // silence detector
    InputStream silenceInputStream = getClass().getResourceAsStream(dir + "/s.gmms");
    GMMArrayList sVect =
        MainTools.readGMMContainer(silenceInputStream, parameter.getParameterModel());
    parameter.getParameterSegmentationFilterFile().setClusterFilterName("iS,iT,j");
    ClusterSet clustersSplitClust =
        SSplitSeg.make(featureSet2, clustersFltClust, sVect, clustersPMSClust, parameter);
    if (parameter.getParameterDiarization().isSaveAllStep()) {
      parameter.getParameterSegmentationOutputFile().setMask(mask + ".spl.seg");
      MainTools.writeClusterSet(parameter, clustersSplitClust, false);
      parameter.getParameterSegmentationOutputFile().setMask(mask);
    }

    parameter.getParameterSegmentationFilterFile().setClusterFilterName(oldSegmentationFilterFile);
    parameter.getParameterFilter().setSegmentPadding(oldSegmentPadding);
    parameter.getParameterFilter().setSilenceMinimumLength(oldSilenceMinimumLength);
    parameter.getParameterFilter().setSpeechMinimumLength(oldSpeechMinimumLength);

    return clustersSplitClust;
  }