public void RecognizeAsync(ISoundSignalReader signal, HiddenMarkovClassifier hmm, Action<string> handleMessage,
            SignalVisitor voiceVisitor = null)
        {
            Action<List<double[]>> action = features =>
            {
                var observations = _codeBook.Quantize(features.Select(item => new Point(item)).ToArray());
                double[] responsabilities;
                var ret = hmm.Compute(observations, out responsabilities);

                var models = hmm.Models;
                var likelyHoodValue = Double.MinValue;

                foreach (var model in models)
                {
                    var val = model.Evaluate(observations);
                    if (val > likelyHoodValue)
                    {
                        likelyHoodValue = val;
                    }
                }

                handleMessage(hmm[ret].Tag.ToString());
            };

            var featureUtility = new FeatureUtility(_engineParameters);
            featureUtility.ExtractFeaturesAsync(signal, action, voiceVisitor);
        }
        public void RecognizeAsync(ISoundSignalReader signal, Action<string> handleMessage,
            SignalVisitor visitor = null)
        {
            Action<List<double[]>> action = features =>
            {
                var observations = _codeBook.Quantize(features.Select(item => new Point(item)).ToArray());
                var likelyHoodValue = Double.MinValue;
                HiddenMarkovModel bestFit = null;
                var modelsToSearchFor = _models.Values.Where(item =>
                {
                    var idProp = (IdentificationProperties) item.Tag;
                    var rateLength = Math.Abs(idProp.MeanFeaturesLength - observations.Length)/idProp.MeanFeaturesLength;
                    return rateLength < 0.1;
                }).ToArray();

                foreach (var model in modelsToSearchFor)
                {
                    var val = model.Evaluate(observations);
                    if (val > likelyHoodValue)
                    {
                        likelyHoodValue = val;
                        bestFit = model;
                    }
                }

                if (bestFit != null)
                {
                    var idProp = (IdentificationProperties)bestFit.Tag;
                    handleMessage(idProp.Label);
                }
            };

            var featureUtility = new FeatureUtility(_engineParameters);
            featureUtility.ExtractFeaturesAsync(signal, action, visitor);
        }