public void Encode()
        {
            if (this.trackGain == null && this.drMeter == null)
            {
                throw new SkipEncodingItemException("Neither ReplayGain nor DynamicRange to calculate.");
            }

            AudioBuffer buffer = new AudioBuffer(audioSource.PCM, FileEncoderBase.BufferSize);

            while (audioSource.Read(buffer, FileEncoderBase.BufferSize) > 0)
            {
                if (this.trackGain != null)
                {
                    DspHelper.AnalyzeSamples(this.trackGain, buffer);
                }
                if (this.drMeter != null)
                {
                    this.drMeter.Feed(buffer.Samples, buffer.Length);
                }

                ProgressChangedEventArgs eventArgs = new ProgressChangedEventArgs((double)this.audioSource.Position / this.audioSource.Length);
                this.OnProgressChanged(eventArgs);
                if (eventArgs.Cancel)
                {
                    this.trackGain = null;
                    this.drMeter = null;
                    return;
                }
            }

            if (this.drMeter != null)
            {
                this.drMeter.Finish();
            }
        }
 private void OnProgressChanged(ProgressChangedEventArgs eventArgs)
 {
     if (this.ProgressChanged != null)
     {
         this.ProgressChanged(this, eventArgs);
     }
 }
        public void Encode()
        {
            while (true)
            {
                if (trackTasks.Any(t => t.Task.Status == EncodeTaskStatus.Cancelled))
                {
                    return;
                }
                else if (trackTasks.Any(t => t.Task.Status == EncodeTaskStatus.Faulted || t.Task.Status == EncodeTaskStatus.FaultedWaiting))
                {
                    throw new Exception("Track faulted");
                }
                else if (trackTasks.Any(t => t.Task.Status == EncodeTaskStatus.Skipped))
                {
                    throw new SkipEncodingItemException("");
                }
                else if (trackTasks.All(t => t.Task.Status == EncodeTaskStatus.Completed))
                {
                    this.ComputeReplayGain();
                    return;
                }

                Thread.Sleep(100);

                ProgressChangedEventArgs e = new ProgressChangedEventArgs(0);
                if (e.Cancel)
                {
                    return;
                }
            }
        }
        public CollectionStatistics ComputeStatistics()
        {
            CollectionStatistics statistics = new CollectionStatistics();

            HashSet<string> albumArtists = new HashSet<string>();
            HashSet<Artist> artists = new HashSet<Artist>();

            Release[] releases = this.collectionManager.Releases.ToArray();

            int processedReleases = 0;
            foreach (Release release in releases)
            {
                statistics.TotalReleases += 1;
                statistics.TotalAlbumArtists += albumArtists.Add(release.JoinedAlbumArtists) ? 1 : 0;
                statistics.TotalArtists += release.Artists.Select(a => artists.Add(a.Artist) ? 1 : 0).Sum();
                statistics.TotalArtists += release.Tracklist.Select(t => t.Artists.Select(a => artists.Add(a.Artist) ? 1 : 0).Sum()).Sum();
                statistics.TotalTracks += release.Tracklist.Count;

                bool isPerfect = this.IsReleasePerfect(release);

                if (isPerfect)
                {
                    statistics.PerfectReleases += 1;
                }

                if (release.Images.Count > 0)
                {
                    statistics.ReleasesWithImages += 1;
                }

                statistics.TotalImages += release.Images.Count;
                statistics.TotalImageBytes += release.Images.Select(i => this.collectionManager.ImageHandler.GetImageByteLength(i)).Sum();
                statistics.TotalAdditionalFiles += release.AdditionalFiles.Count;
                statistics.TotalAdditionalFileBytes += release.AdditionalFiles.Select(f => f.File.Length).Sum();
                statistics.FlaggedReleases += release.IsFlagged ? 1 : 0;

                ++processedReleases;
                ProgressChangedEventArgs eventArgs = new ProgressChangedEventArgs((double)processedReleases / releases.Length);
                this.OnProgressChanged(eventArgs);
                if (eventArgs.Cancel)
                {
                    return null;
                }
            }

            return statistics;
        }
        public void ComputeHashes()
        {
            try
            {
                SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

                this.CRC32 = 0;

                long totalSamples = this.audioSource.Length;
                long processedSamples = 0;

                AudioBuffer buffer = new AudioBuffer(this.audioSource.PCM, 44100);
                while (this.audioSource.Read(buffer, 44100) > 0)
                {
                    byte[] bufferBytes = buffer.Bytes;
                    if (this.audioSource.Position == this.audioSource.Length)
                    {
                        sha1.TransformFinalBlock(bufferBytes, 0, buffer.ByteLength);
                    }
                    else
                    {
                        sha1.TransformBlock(bufferBytes, 0, buffer.ByteLength, null, 0);
                    }
                    this.CRC32 = Crc32.ComputeChecksum(this.CRC32, buffer.Bytes, 0, buffer.ByteLength);

                    processedSamples += buffer.Length;

                    ProgressChangedEventArgs eventArgs = new ProgressChangedEventArgs((double)processedSamples / totalSamples);
                    this.OnProgressChanged(eventArgs);
                    if (eventArgs.Cancel)
                    {
                        return;
                    }
                }

                this.SHA1 = sha1.Hash;
            }
            finally
            {
                this.audioSource.Close();
            }
        }
        public EncodingTargetScanResult Scan()
        {
            Release[] releases = this.collectionManager.Releases.ToArray();

            Dictionary<Release, List<Track>> tracksToEncode = new Dictionary<Release, List<Track>>();
            HashSet<Release> releasesToEncode = new HashSet<Release>(new CallbackEqualityComparer<Release>((r1, r2) => r1.Id == r2.Id));

            Action<Release, Track> addTrack = (Release _release, Track _track) =>
            {
                List<Track> list;
                if (tracksToEncode.TryGetValue(_release, out list))
                {
                    list.Add(_track);
                }
                else
                {
                    list = new List<Track>();
                    list.Add(_track);

                    tracksToEncode[_release] = list;
                    releasesToEncode.Add(_release);
                }
            };

            List<string> filesToDelete = new List<string>();

            HashSet<string> targetFiles = new HashSet<string>();

            int totalReleases = releases.Length;
            int processedReleases = 0;

            foreach (Release release in releases)
            {
                foreach (Track track in release.Tracklist)
                {
                    string targetFilename = Path.Combine(this.encodingTarget.TargetDirectory,
                        Path.ChangeExtension(track.RelativeFilename, this.encodingTarget.Extension));

                    if (File.Exists(targetFilename))
                    {
                        FileInfo original = new FileInfo(Path.Combine(this.collectionManager.Settings.MusicDirectory, track.RelativeFilename));
                        FileInfo encoding = new FileInfo(targetFilename);

                        if (original.LastWriteTime != encoding.LastWriteTime)
                        {
                            addTrack(release, track);
                        }
                    }
                    else
                    {
                        addTrack(release, track);
                    }

                    // This avoids a bug for example with N.O.H.A., as it normalizes the path
                    targetFiles.Add(Path.GetFullPath(targetFilename));
                }

                ++processedReleases;
                ProgressChangedEventArgs eventArgs = new ProgressChangedEventArgs((double)processedReleases / totalReleases);
                this.OnProgressChanged(eventArgs);
                if (eventArgs.Cancel)
                {
                    return null;
                }
            }

            if (Directory.Exists(this.encodingTarget.TargetDirectory))
            {
                string[] targetDirectoryFiles = Directory.GetFiles(this.encodingTarget.TargetDirectory, "*" + this.encodingTarget.Extension, SearchOption.AllDirectories);
                foreach (string file in targetDirectoryFiles)
                {
                    if (!targetFiles.Contains(file))
                    {
                        filesToDelete.Add(file);
                    }
                }
            }

            return new EncodingTargetScanResult()
            {
                TracksToEncode = tracksToEncode,
                ReleasesToEncode = releasesToEncode,
                FilesToDelete = filesToDelete.ToArray()
            };
        }
        public void Encode()
        {
            AudioBuffer buffer = new AudioBuffer(audioSource.PCM, BufferSize);

            this.AudioDest.FinalSampleCount = this.audioSource.Length;

            while (audioSource.Read(buffer, BufferSize) > 0)
            {
                if (this.trackGain != null)
                {
                    DspHelper.AnalyzeSamples(this.trackGain, buffer);
                }
                if (this.drMeter != null)
                {
                    this.drMeter.Feed(buffer.Samples, buffer.Length);
                }

                this.AudioDest.Write(buffer);

                ProgressChangedEventArgs eventArgs = new ProgressChangedEventArgs((double)this.audioSource.Position / this.audioSource.Length);
                this.OnProgressChanged(eventArgs);
                if (eventArgs.Cancel)
                {
                    this.AudioDest.Close();
                    this.AudioDest = null;
                    Utility.TryDeleteFile(this.targetFilename);
                    return;
                }
            }

            if (this.drMeter != null)
            {
                this.drMeter.Finish();
            }

            this.AudioDest.Close();
            this.AudioDest = null;

            if (this.tags != null)
            {
                this.tags.WriteToFile(this.targetFilename);
            }
        }