public int Recognize(ISoundSignalReader signal, HiddenMarkovClassifier hmm, out string name,
            SignalVisitor voiceVisitor = null)
        {
            var featureUtility = new FeatureUtility(_engineParameters);
            signal.Reset();
            var features = featureUtility.ExtractFeatures(signal, voiceVisitor).First();
            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;
            name = string.Empty;

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

            return ret;
        }
        public int Recognize(ISoundSignalReader signal, HiddenMarkovModel[] models, out string name,
            SignalVisitor voiceVisitor = null)
        {
            var featureUtility = new FeatureUtility(_engineParameters);
            signal.Reset();
            var features = featureUtility.ExtractFeatures(signal, voiceVisitor).First();
            var observations = _codeBook.Quantize(features.Select(item => new Point(item)).ToArray());

            var likelyHoodValue = Double.MinValue;
            name = string.Empty;
            var index = 0;
            var ret = 0;
            foreach (var model in models)
            {
                var val = model.Evaluate(observations);
                if (val > likelyHoodValue)
                {
                    likelyHoodValue = val;
                    name = model.Tag.ToString();
                    ret = index;
                }
                index++;
            }

            return ret;
        }
        public HiddenMarkovModel BuildModel(IList<ISoundSignalReader> signalReaders, string tag,
            SignalVisitor visitor = null)
        {
            var signals = signalReaders; // signals
            var signalsCount = signals.Count();
            List<List<double[]>> samples = new List<List<double[]>>();
            var featureUtility = new FeatureUtility(_engineParameters);
            var meanFeaturesLength = 0.0;

            for (var signalIndex = 0; signalIndex < signalsCount; signalIndex++)
            {
                var signal = signals[signalIndex];
                signal.Reset();
                var allSignalfeatures = featureUtility.ExtractFeatures(signal, visitor).ToArray();
                samples.AddRange(allSignalfeatures);
            }

            var featuresInput = new double[samples.Count][][];

            for (var index = 0; index < samples.Count; index++)
            {
                featuresInput[index] = samples[index].ToArray();
                meanFeaturesLength += featuresInput[index].Length;
            }
            meanFeaturesLength = meanFeaturesLength/samples.Count;
            var hmm = new HiddenMarkovModel(_numberOfHiddenStates, _codeBook.Size, false);

            List<int[]> observables = new List<int[]>();
            for (var signalIndex = 0; signalIndex < featuresInput.Length; signalIndex++) // foreach word signal
            {
                var points = featuresInput[signalIndex].Select(item => new Point(item)); // convert feature to points

                var codeItems = _codeBook.Quantize(points.ToArray());
                observables.Add(codeItems);
            }

            const int iterations = 20000;
            const double tolerance = 0.0;
            var viterbiLearning = new ViterbiLearning(hmm) {Iterations = iterations, Tolerance = tolerance};

            viterbiLearning.Run(observables.ToArray());
            var idProp = new IdentificationProperties
            {
                Class = ClassType.Word,
                MeanFeaturesLength = meanFeaturesLength,
                Label = tag
            };
            viterbiLearning.Model.Tag = idProp;

            _models[tag] = viterbiLearning.Model;
            return viterbiLearning.Model;
        }
        public static Codebook FromWaves(IList<ISoundSignalReader> sounds, EngineParameters parameters, int codeBookSize = 256)
        {
            var featureUtility = new FeatureUtility(parameters);
            var features = new List<double[][]>();
            foreach (var signal in sounds)
            {
                signal.Reset();
                var items = featureUtility.ExtractFeatures(signal).Select(item => item.ToArray());
                features.AddRange(items);
            }

            var codeBook = new Codebook(features.SelectMany(item => item).Select(item => new Point(item)).ToArray(), codeBookSize);

            return codeBook;
        }
        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 TrainResult TrainAll(Dictionary<string, IList<ISoundSignalReader>> signalsDictionary,
            SignalVisitor voiceVisitor = null)
        {
            var numberOfItems = 0;
            foreach (var item in signalsDictionary)
            {
                numberOfItems += item.Value.Count;
            }

            double[][][][] featuresInput = new Double[signalsDictionary.Count][][][];

            int[] models = new int[numberOfItems];
            var allSignalIndex = 0;
            var modelIndex = 0;

            var featureUtility = new FeatureUtility(_engineParameters);

            foreach (var item in signalsDictionary)
            {
                var signals = item.Value; // signals
                var signalsCount = signals.Count();

                featuresInput[modelIndex] = new double[signalsCount][][];

                for (var signalIndex = 0; signalIndex < signalsCount; signalIndex++)
                {
                    var signal = signals[signalIndex];
                    List<Double[]> features = featureUtility.ExtractFeatures(signal, voiceVisitor).First();

                    featuresInput[modelIndex][signalIndex] = features.ToArray();
                    models[allSignalIndex] = modelIndex;
                    allSignalIndex++;
                }
                modelIndex++;
            }

            List<int[]> observables = new List<int[]>();

            for (int wordIndex = 0; wordIndex < featuresInput.Length; wordIndex++) // foreach word
            {
                for (var signalIndex = 0; signalIndex < featuresInput[wordIndex].Length; signalIndex++)
                    // foreach word signal
                {
                    var points = featuresInput[wordIndex][signalIndex].Select(item => new Point(item));
                        // convert feature to points

                    var codeItems = _codeBook.Quantize(points.ToArray());
                    observables.Add(codeItems);
                }
            }
            //HiddenMarkovModel hmm = new HiddenMarkovModel(5, _codeBook.Size, true);
            //var Bauc

            var hmm = new HiddenMarkovClassifier(signalsDictionary.Count, new Forward(_numberOfHiddenStates),
                _codeBook.Size, signalsDictionary.Keys.ToArray());

            const int iterations = 200;
            const double tolerance = 0;

            var teacher = new HiddenMarkovClassifierLearning(hmm,
                i => new ViterbiLearning(hmm.Models[i]) {Iterations = iterations, Tolerance = tolerance}
                );

            teacher.Run(observables.ToArray(), models);

            return new TrainResult {Catalog = _codeBook, Models = hmm.Models.ToArray()};
        }
        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);
        }
        public int Recognize(ISoundSignalReader signal, out string name,
            SignalVisitor visitor = null)
        {
            var featureUtility = new FeatureUtility(_engineParameters);
            signal.Reset();
            var features = featureUtility.ExtractFeatures(signal, visitor).First();

            var observations = _codeBook.Quantize(features.Select(item => new Point(item)).ToArray());
            var likelyHoodValue = Double.MinValue;
            HiddenMarkovModel bestFit = null;
            var index = 0;
            var ret = 0;
            foreach (var model in _models.Values)
            {
                var val = model.Evaluate(observations);

                if (val > likelyHoodValue)
                {
                    likelyHoodValue = val;
                    bestFit = model;
                    ret = index;
                }
                index++;
            }

            if (bestFit != null)
            {
                var idProp = (IdentificationProperties) bestFit.Tag;
                name = idProp.Label;
            }
            else
                name = string.Empty;

            return ret;
        }