#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using Nuclex.Audio.Metadata; using Nuclex.Support.Tracking; namespace Nuclex.Audio.Verification { /// /// Provides audio file verfication services using the AccurateRip database /// public static class AccurateRip { #region struct TrackInfo /// /// Informations about a track returned by a query to the AccurateRip database /// public struct TrackInfo { /// CRC32 checksum of the uncompressed PCM data of the track public int Crc32; /// /// Confidence (eg. number of people with the same checksum) that this checksum /// indicates a proper rip of the track /// public int Confidence; } #endregion // struct TrackInfo #region struct CdInfo /// /// Informations about a CD returned by a query to the AccurateRip database /// public struct CdInfo { /// Disc ID for the CD calculated using the CDDB disc id algorithm public int CddbDiscId; /// /// Disc ID for the CD calculated using the primary AccurateRip algorithm /// public int DiscId1; /// /// Disc ID for the CD calculated using the secondary AccurateRip algorithm /// public int DiscId2; /// Informations about the individual tracks on this CD public TrackInfo[] TrackInfos; } #endregion // struct CdInfo /// /// Queries the AccurateRip database for the CRCs of the tracks on the specified CD /// /// /// Total length of the CD (from the beginning of the first track to the end of the /// last track) in seconds /// /// /// Offsets of the individual tracks on the CD in seconds /// /// public static Request QueryDatabase( int totalLengthSeconds, int[] trackOffsetsSeconds ) { try { // Calculate the three IDs required by a query to the AccurateRip database. AccurateRip // improves (marginally) on the flawed CDDB disc id by providing two additional ids, // however, this doesn't hurt AccurateRip nearly as much as it would a CDDB service. int discId1 = CalculateDiscId1(trackOffsetsSeconds); int discId2 = CalculateDiscId2(trackOffsetsSeconds); int cddbDiscId = Cddb.CalculateDiscId(totalLengthSeconds, trackOffsetsSeconds); int trackCount = trackOffsetsSeconds.Length; return QueryDatabase(discId1, discId2, cddbDiscId, trackCount); } catch(Exception exception) { return Request.CreateFailedDummy(exception); } } /// /// Queries the AccurateRip database for the CRCs of the tracks on the specified CD /// /// /// Disc id of the CD calculated using AccurateRip's primary algorithm /// /// /// Disc id of the CD calculated using AccurateRip's secondary algorithm /// /// /// Disc id of the CD calculated using the CDDB algorithm /// /// Number of tracks on the CD /// public static Request QueryDatabase( int discId1, int discId2, int cddbDiscId, int trackCount ) { try { // Set up a request to retrieve the checksums from the AccurateRip database Requests.AccurateRipRetrievalRequest retrievalRequest = new Requests.AccurateRipRetrievalRequest( discId1, discId2, cddbDiscId, trackCount ); retrievalRequest.Start(); // No exceptions until this point, the request is now running asynchronously and // the user can either wait for it to finish or register a callback return retrievalRequest; } catch(Exception exception) { return Request.CreateFailedDummy(exception); } } /// Calculates a disc id using AccurateRip's primary id algorithm /// /// Offsets of the individual tracks on the CD in seconds /// /// The disc id calculated using AccurateRip's primary id algorithm public static int CalculateDiscId1(int[] trackOffsetsSeconds) { int discId = 0; for(int trackIndex = 0; trackIndex < trackOffsetsSeconds.Length; ++trackIndex) { discId += trackOffsetsSeconds[trackIndex]; } return discId; } /// Calculates a disc id using AccurateRip's secondary id algorithm /// /// Offsets of the individual tracks on the CD in seconds /// /// The disc id calculated using AccurateRip's secondary id algorithm public static int CalculateDiscId2(int[] trackOffsetsSeconds) { int discId = 0; for(int trackIndex = 0; trackIndex < trackOffsetsSeconds.Length; ++trackIndex) { int trackOffsetSeconds = Math.Max(trackOffsetsSeconds[trackIndex], 1); discId += trackOffsetSeconds * (trackIndex + 1); } return discId; } } } // namespace Nuclex.Audio.Verification