/// <summary> /// Get track samples /// </summary> /// <param name = "track">Track from which to gather samples</param> /// <param name = "proxy">Proxy used in gathering samples</param> /// <param name = "sampleRate">Sample rate used in gathering samples</param> /// <param name = "milliseconds">Milliseconds to gather</param> /// <param name = "startmilliseconds">Starting millisecond</param> /// <returns></returns> public static float[] GetTrackSamples(Track track, IAudioService proxy, int sampleRate, int milliseconds, int startmilliseconds) { if (track == null || track.Path == null) return null; //read 5512 Hz, Mono, PCM, with a specific audioService return proxy.ReadMonoFromFile(track.Path, sampleRate, milliseconds, startmilliseconds); }
/// <summary> /// Create fingerprints out of down sampled samples /// </summary> /// <param name = "samples">Down sampled to 5512 samples </param> /// <param name = "track">Track</param> /// <param name = "stride">Stride</param> /// <param name = "hashTables">Number of hash tables</param> /// <param name = "hashKeys">Number of hash keys</param> public void CreateInsertFingerprints( float[] samples, Track track, IStride stride, int hashTables, int hashKeys) { if (track == null) { return; /*track is not eligible*/ } /*Create fingerprints that will be used as initial fingerprints to be queried*/ List<bool[]> fingerprints = workUnitBuilder.BuildWorkUnit() .On(samples) .WithCustomConfiguration(config => config.Stride = stride) .GetFingerprintsUsingService(service) .Result; storage.InsertTrack(track); /*Insert track into the storage*/ /*Get signature's hash signature, and associate it to a specific track*/ List<HashSignature> creationalsignatures = GetSignatures(fingerprints, track, hashTables, hashKeys); foreach (HashSignature hash in creationalsignatures) { storage.InsertHash(hash, HashType.Creational); /*Set this hashes as also the query hashes*/ storage.InsertHash(hash, HashType.Query); } }
/// <summary> /// Get track info from the filename /// </summary> /// <param name = "mintracklen">Min track length</param> /// <param name = "maxtracklen">Max track length</param> /// <param name = "filename">Filename from which to extract the requested info</param> /// <param name = "audioService">Audio audioService to read tags</param> /// <returns>Track to be analyzed further / null if the track is not eligible</returns> public static Track GetTrackInfo(int mintracklen, int maxtracklen, string filename, BassAudioService audioService) { TAG_INFO tags = audioService.GetTagInfoFromFile(filename); //get file tags string artist, title; double duration; if (tags == null) { /*The song does not contain any tags*/ artist = "Unknown"; title = "Unknown"; duration = 60; } else { /*The song contains related tags*/ artist = tags.artist; title = tags.title; duration = tags.duration; } if (String.IsNullOrEmpty(artist)) /*assign a name to music files that don't have tags*/ artist = "Unknown"; if (String.IsNullOrEmpty(title)) /*assign a title to music files that don't have tags*/ title = "Unknown"; if (duration < mintracklen || duration > maxtracklen) /*check the duration of a music file*/ return null; Track track = new Track { Artist = artist, Title = title, TrackLength = duration, Path = Path.GetFullPath(filename) }; return track; }
/// <summary> /// Constructor /// </summary> /// <param name = "track">Hashed track</param> /// <param name = "signature">Signature of the track</param> public HashSignature(Track track, int[] signature) { Track = track; Signature = signature; lock (LockObject) { _id = _increment++; } }
// ReSharper disable ReturnTypeCanBeEnumerable.Local private List<HashSignature> GetSignatures(IEnumerable<bool[]> fingerprints, Track track, int hashTables, int hashKeys) // ReSharper restore ReturnTypeCanBeEnumerable.Local { List<HashSignature> signatures = new List<HashSignature>(); foreach (bool[] fingerprint in fingerprints) { int[] signature = _hasher.ComputeMinHashSignature(fingerprint); /*Compute min-hash signature out of fingerprint*/ Dictionary<int, long> buckets = _hasher.GroupMinHashToLSHBuckets(signature, hashTables, hashKeys); /*Group Min-Hash signature into LSH buckets*/ int[] hashSignature = new int[buckets.Count]; foreach (KeyValuePair<int, long> bucket in buckets) hashSignature[bucket.Key] = (int) bucket.Value; HashSignature hash = new HashSignature(track, hashSignature); /*associate track to hash-signature*/ signatures.Add(hash); } return signatures; /*Return the signatures*/ }
/// <summary> /// Create fingerprints out of down sampled samples /// </summary> /// <param name = "samples">Down sampled to 5512 samples </param> /// <param name = "track">Track</param> /// <param name = "stride">Stride</param> /// <param name = "hashTables">Number of hash tables</param> /// <param name = "hashKeys">Number of hash keys</param> public void CreateInsertFingerprints(float[] samples, Track track, IStride stride, int hashTables, int hashKeys) { if (track == null) return; /*track is not eligible*/ /*Create fingerprints that will be used as initial fingerprints to be queried*/ List<bool[]> dbFingers = _manager.CreateFingerprints(samples, stride); _storage.InsertTrack(track); /*Insert track into the storage*/ /*Get fingerprint's hash signature, and associate it to a specific track*/ List<HashSignature> creationalsignatures = GetSignatures(dbFingers, track, hashTables, hashKeys); foreach (HashSignature hash in creationalsignatures) { _storage.InsertHash(hash, HashType.Creational); /*Set this hashes as also the query hashes*/ _storage.InsertHash(hash, HashType.Query); } return; }
/// <summary> /// Gets the list of hash signatures that are available in the storage for a specific track /// </summary> /// <param name = "track">Requested track</param> /// <param name = "type">Type of the hashes toe gathered</param> /// <returns>A set of fingerprints (hash signatures) that correspond to a specific track id</returns> public HashSet<HashSignature> GetHashSignatures(Track track, HashType type) { if (_fingerprints.ContainsKey(track)) { switch (type) { case HashType.Creational: return _fingerprints[track].Creational; case HashType.Query: return _fingerprints[track].Query; } } return null; }
/// <summary> /// Remove track from the RAM storage /// </summary> /// <param name = "track"></param> public void RemoveTrack(Track track) { if (_fingerprints.ContainsKey(track)) _fingerprints.Remove(track); }
/// <summary> /// Insert a track into the RAM Storage /// </summary> /// <param name = "track">Track to be inserted</param> public void InsertTrack(Track track) { lock (LockObject) { if (!_fingerprints.ContainsKey(track)) _fingerprints[track] = new Hashes(); } }