Beispiel #1
0
        /**
         * Calculates the distance between this voice sample and the voice prints previously extracted
         * and returns the closest matches sorted by distance
         * <p>
         * Usage of a closed set is assumed : the speaker's voice print was extracted before and is known to the system.
         * This means you'll always get MatchResults even if the speaker is absolutely unknown to the system.
         * The MatchResult class provides a likelihood ratio in order to help determining the usefulness of the result
         * </p>
         * @param voiceSample the voice sample, values between -1.0 and 1.0
         * @return a list MatchResults sorted by distance
         */
        public IEnumerable <MatchResult <T> > Identify(double[] voiceSample, double maxDistance = 0)
        {
            if (store.Count == 0)
            {
                throw new InvalidOperationException("There is no voice print enrolled in the system yet");
            }

            var voicePrint = new VoicePrint(audioProcessor.ProcessAndExtract(voiceSample));

            var calculator = new EuclideanDistanceCalculator();
            var matches    = new List <MatchResult <T> >(store.Count);

            var distanceFromUniversalModel = voicePrint.GetDistance(calculator, universalModel);

            foreach (var entry in store)
            {
                var distance = entry.Value.GetDistance(calculator, voicePrint);

                if (maxDistance > 0 && distance > maxDistance)
                {
                    continue;
                }

                // likelihood : how close is the given voice sample to the current VoicePrint
                // compared to the total distance between the current VoicePrint and the universal model
                int likelihood = 100 - (int)(distance / (distance + distanceFromUniversalModel) * 100);
                matches.Add(new MatchResult <T>(entry.Key, likelihood, distance));
            }


            return(matches.OrderBy(m => m.Distance));
        }
Beispiel #2
0
        /**
         * Creates a voice print and stores it along with the user key for later comparison with new samples
         * <p>
         * Threading : this method is synchronized to prevent inadvertently erasing an existing user key
         * </p>
         * @param userKey the user key associated with this voice print
         * @param voiceSample the voice sample, values between -1.0 and 1.0
         * @return the voice print extracted from the given sample
         */
        public VoicePrint CreateVoicePrint(T userKey, double[] voiceSample)
        {
            lock (_lock)
            {
                if (userKey == null)
                {
                    throw new ArgumentNullException(nameof(userKey), "The userKey is null");
                }

                if (store.ContainsKey(userKey))
                {
                    throw new ArgumentException("The userKey already exists: [{userKey}");
                }

                double[]   features   = audioProcessor.ProcessAndExtract(voiceSample);
                VoicePrint voicePrint = new VoicePrint(features);

                if (!universalModelWasSetByUser)
                {
                    if (universalModel == null)
                    {
                        universalModel = new VoicePrint(voicePrint);
                    }
                    else
                    {
                        universalModel.Merge(features);
                    }
                }

                store.Add(userKey, voicePrint);

                return(voicePrint);
            }
        }
Beispiel #3
0
 /**
  * Sets the universal model to be used to calculate likelihood ratios
  * Once set, further voice print create / merge operations won't modify this model
  * @param universalModel the universal model to set, may not be null
  */
 public void SetUniversalModel(VoicePrint universalModel)
 {
     lock (_lock)
     {
         this.universalModel        = universalModel ?? throw new ArgumentNullException(nameof(universalModel), "The universal model may not be null");
         universalModelWasSetByUser = false;
     }
 }
Beispiel #4
0
        /**
         * Returns the distance between this voice print and the given one using the calculator.
         * Threading : it is safe to call this method while other threads may merge this voice print instance
         * with another one in the sense that the distance calculation will not happen on half merged voice print.
         * Since this method is read only, it is safe to call it from multiple threads for a single instance
         * @param calculator the distance calculator
         * @param voicePrint the voice print
         * @return the distance
         */
        public double GetDistance(DistanceCalculator calculator, VoicePrint voicePrint)
        {
            rwl.EnterReadLock();

            try
            {
                return(calculator.GetDistance(features, voicePrint.features));
            }
            finally
            {
                rwl.ExitReadLock();
            }
        }
Beispiel #5
0
        /**
         * Constructor taking previously extracted voice prints directly into the system
         * @param sampleRate the sample rate, at least 8000.0 Hz (preferably higher)
         * @param voicePrintsByUserKey a {@code Map} containing user keys and their respective {@code VoicePrint}
         */
        public Recognito(float sampleRate, Dictionary <T, VoicePrint> voicePrintsByUserKey) : this(sampleRate)
        {
            VoicePrint universalModel = null;

            foreach (var item in voicePrintsByUserKey.Values)
            {
                if (universalModel == null)
                {
                    universalModel = new VoicePrint(item);
                    continue;
                }

                universalModel.Merge(item);
            }

            store.AddRange(voicePrintsByUserKey);
        }
Beispiel #6
0
 /**
  * Copy constructor
  * @param print the VoicePrint to copy
  */
 public VoicePrint(VoicePrint print) : this(ArrayHelper.Copy(print.features, print.features.Length))
 {
 }
Beispiel #7
0
 /**
  * Convenience method to merge voice prints
  * @param print the voice print to merge
  * @see VoicePrint#merge(double[])
  */
 public void Merge(VoicePrint print)
 {
     Merge(print.features);
 }