### Installation Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Install the TagLibSharp2 package using the .NET CLI. ```bash dotnet add package TagLibSharp2 ``` -------------------------------- ### Adding Album Art Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Add album art to an MP3 file. ```csharp using TagLibSharp2.Id3.Id3v2.Frames; var result = Mp3File.ReadFromFile("song.mp3"); if (result.IsSuccess) { var mp3 = result.File!; var imageBytes = File.ReadAllBytes("cover.jpg"); var picture = new PictureFrame( "image/jpeg", PictureType.FrontCover, "Album Cover", imageBytes); mp3.Id3v2Tag?.AddPicture(picture); mp3.SaveToFile("song.mp3", File.ReadAllBytes("song.mp3")); } ``` -------------------------------- ### Reading Album Art Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Read album art from an MP3 file. ```csharp var result = Mp3File.ReadFromFile("song.mp3"); if (result.IsSuccess && result.File!.Pictures.Length > 0) { var picture = result.File.Pictures[0]; Console.WriteLine($"Type: {picture.PictureType}"); Console.WriteLine($"MIME: {picture.MimeType}"); // Save to file File.WriteAllBytes("cover.jpg", picture.PictureData.ToArray()); } ``` -------------------------------- ### Batch Processing Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Process multiple files in parallel. ```csharp using TagLibSharp2.Core; var files = Directory.GetFiles("music/", "*.mp3"); var results = await BatchProcessor.ProcessAsync( files, async (path, ct) => { var result = await Mp3File.ReadFromFileAsync(path, ct: ct); return result.IsSuccess ? result.File!.Title : null; }, maxDegreeOfParallelism: 4, progress: new Progress(p => Console.WriteLine($"Progress: {p.PercentComplete:F1}%")) ); // Filter results var successful = results.WhereSucceeded().ToList(); var failed = results.WhereFailed().ToList(); Console.WriteLine($"Processed {successful.Count} files, {failed.Count} failed"); ``` -------------------------------- ### Quick Start Example Source: https://github.com/decriptor/taglibsharp2/blob/main/src/TagLibSharp2/README.md Demonstrates reading and modifying MP3 tags, reading FLAC tags, and using asynchronous operations. ```csharp using TagLibSharp2.Mpeg; using TagLibSharp2.Xiph; // Read MP3 tags var result = Mp3File.ReadFromFile("song.mp3"); if (result.IsSuccess) { var mp3 = result.File!; Console.WriteLine($"{mp3.Title} by {mp3.Artist}"); Console.WriteLine($"Duration: {mp3.Duration}"); // Modify tags mp3.Title = "New Title"; mp3.Artist = "New Artist"; mp3.SaveToFile("song.mp3", File.ReadAllBytes("song.mp3")); } // Read FLAC tags var flacResult = FlacFile.ReadFromFile("song.flac"); if (flacResult.IsSuccess) { var flac = flacResult.File!; Console.WriteLine($"{flac.Title} - {flac.Properties.Duration}"); } // Async support var asyncResult = await Mp3File.ReadFromFileAsync("song.mp3"); ``` -------------------------------- ### Tag Validation Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Check tags for common issues. ```csharp using TagLibSharp2.Core; var result = Mp3File.ReadFromFile("song.mp3"); if (result.IsSuccess) { var tag = result.File!.Id3v2Tag; var validation = tag?.Validate(); if (validation is not null) { foreach (var issue in validation.Issues) { Console.WriteLine($"[{issue.Severity}] {issue.Field}: {issue.Message}"); } } } ``` -------------------------------- ### Copying Tags Between Formats Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Copy tags from one format to another. ```csharp using TagLibSharp2.Core; // Copy from MP3 to FLAC var mp3Result = Mp3File.ReadFromFile("song.mp3"); var flacResult = FlacFile.ReadFromFile("song.flac"); if (mp3Result.IsSuccess && flacResult.IsSuccess) { var sourceTag = mp3Result.File!.Id3v2Tag; var targetTag = flacResult.File!.VorbisComment; if (sourceTag is not null && targetTag is not null) { // Copy all metadata sourceTag.CopyTo(targetTag); // Or copy selectively sourceTag.CopyTo(targetTag, TagCopyOptions.Basic | TagCopyOptions.Pictures); flacResult.File.SaveToFile("song.flac", File.ReadAllBytes("song.flac")); } } ``` -------------------------------- ### Async Operations Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Perform file operations asynchronously for better performance. ```csharp var result = await Mp3File.ReadFromFileAsync("song.mp3"); if (result.IsSuccess) { var mp3 = result.File!; mp3.Title = "Updated Title"; var originalData = await File.ReadAllBytesAsync("song.mp3"); await mp3.SaveToFileAsync("song.mp3", originalData); } ``` -------------------------------- ### BasicUsage Running Instructions Source: https://github.com/decriptor/taglibsharp2/blob/main/examples/README.md Instructions to run the BasicUsage example. ```bash cd examples/BasicUsage dotnet run ``` -------------------------------- ### Quick Start Example Source: https://github.com/decriptor/taglibsharp2/blob/main/README.md Demonstrates how to read and modify tags for various audio file formats using TagLibSharp2, including asynchronous operations. ```csharp using TagLibSharp2.Core; using TagLibSharp2.Mpeg; using TagLibSharp2.Xiph; using TagLibSharp2.Ogg; using TagLibSharp2.Riff; using TagLibSharp2.Aiff; using TagLibSharp2.Mp4; // Auto-detect format using MediaFile factory var result = MediaFile.Read("song.m4a"); if (result.IsSuccess) { Console.WriteLine($"Format: {result.Format}"); Console.WriteLine($"{result.Tag?.Title} by {result.Tag?.Artist}"); } // Read MP3 tags (prefers ID3v2, falls back to ID3v1) var mp3Result = Mp3File.ReadFromFile("song.mp3"); if (mp3Result.IsSuccess) { var mp3 = mp3Result.File!; Console.WriteLine($"{mp3.Title} by {mp3.Artist}"); // Modify and save mp3.Title = "New Title"; mp3.SaveToFile("song.mp3", File.ReadAllBytes("song.mp3")); } // MP4/M4A files with iTunes metadata var mp4Result = Mp4File.ReadFromFile("song.m4a"); if (mp4Result.IsSuccess) { var mp4 = mp4Result.File!; Console.WriteLine($"{mp4.Title} - {mp4.Duration}"); Console.WriteLine($"Codec: {mp4.AudioCodec}, {mp4.Properties?.SampleRate}Hz"); } // FLAC and Ogg Vorbis work the same way var flac = FlacFile.ReadFromFile("song.flac").File; var ogg = OggVorbisFile.ReadFromFile("song.ogg").File; // Ogg Opus (RFC 7845) with R128 gain var opusResult = OggOpusFile.ReadFromFile("song.opus"); var opus = opusResult.File; Console.WriteLine($"Opus: {opus?.Properties?.Duration}, R128 gain: {opus?.Properties?.OutputGain}dB"); // WAV files support both RIFF INFO and ID3v2 tags WavFile.TryRead(new BinaryData(File.ReadAllBytes("song.wav")), out var wav); Console.WriteLine($"WAV: {wav.Title} - {wav.AudioProperties?.Duration}"); // AIFF files (read and write, includes audio properties) AiffFile.TryRead(new BinaryData(File.ReadAllBytes("song.aiff")), out var aiff); Console.WriteLine($"AIFF: {aiff.AudioProperties?.SampleRate}Hz"); aiff.Tag = new Id3v2Tag { Title = "Updated Title" }; aiff.SaveToFile("song.aiff"); // Async support for high-throughput scenarios var asyncResult = await Mp4File.ReadFromFileAsync("song.m4a"); ``` -------------------------------- ### Error Handling Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md TagLibSharp2 uses result types instead of exceptions for error handling. ```csharp var result = Mp3File.ReadFromFile("nonexistent.mp3"); if (!result.IsSuccess) { // Handle error gracefully Console.WriteLine($"Failed to read file: {result.Error}"); return; } // Safe to use result.File here var mp3 = result.File!; ``` -------------------------------- ### Test Builder Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/NEW-FORMAT-CHECKLIST.md Example of a programmatic file builder for tests. ```csharp public static class {Format}TestBuilder { public static byte[] CreateMinimal{Format}(string? title = null, string? artist = null); public static byte[] CreateWithMetadata(/* params */); public static byte[] CreateWithAudioProperties(uint sampleRate, ushort channels, ...); // Helper methods for building format-specific structures } ``` -------------------------------- ### TagOperations Running Instructions Source: https://github.com/decriptor/taglibsharp2/blob/main/examples/README.md Instructions to run the TagOperations example. ```bash cd examples/TagOperations dotnet run ``` -------------------------------- ### File Operations Example Source: https://github.com/decriptor/taglibsharp2/blob/main/examples/README.md Example demonstrating file operations for MP3, FLAC, and Ogg Vorbis files. ```csharp // Read MP3 with unified ID3v1/ID3v2 access var mp3 = Mp3File.ReadFromFile("song.mp3"); if (mp3.IsSuccess) { Console.WriteLine($"Title: {mp3.File!.Title}"); mp3.File.Title = "New Title"; mp3.File.SaveToFile("song.mp3", File.ReadAllBytes("song.mp3")); } // Read FLAC var flac = FlacFile.ReadFromFile("song.flac"); if (flac.IsSuccess) { Console.WriteLine($"Title: {flac.File!.Title}"); } // Read Ogg Vorbis var ogg = OggVorbisFile.ReadFromFile("song.ogg"); if (ogg.IsSuccess) { Console.WriteLine($"Title: {ogg.File!.Title}"); } ``` -------------------------------- ### Verify .NET SDK Installation Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/BUILDING.md Command to list installed .NET SDK versions to verify installation. ```bash dotnet --list-sdks ``` -------------------------------- ### Reading Tags - Any Supported Format (Auto-Detect) Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Read tags from any supported audio file format using MediaFile.Read, which auto-detects the format. ```csharp using TagLibSharp2.Core; var result = MediaFile.Read("music.mp3"); // Also works with .flac, .ogg, .m4a, .opus if (result.IsSuccess) { Console.WriteLine($"Title: {result.Tag?.Title}"); Console.WriteLine($"Artist: {result.Tag?.Artist}"); Console.WriteLine($"Album: {result.Tag?.Album}"); Console.WriteLine($"Year: {result.Tag?.Year}"); Console.WriteLine($"Format: {result.Format}"); // Mp3, Flac, OggVorbis, OggOpus, or Mp4 } else { Console.WriteLine($"Error: {result.Error}"); } ``` -------------------------------- ### Benchmarking Example Source: https://github.com/decriptor/taglibsharp2/blob/main/CONTRIBUTING.md Example of a benchmark test structure. ```csharp [MemoryDiagnoser] public class BinaryDataBenchmarks { [Benchmark] public void ParseHeader_1KB () { ... } } ``` -------------------------------- ### Test Categories Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/NEW-FORMAT-CHECKLIST.md Example of adding test categories. ```csharp [TestClass] [TestCategory("Unit")] [TestCategory("{Format}")] public class {Format}FileTests { } ``` -------------------------------- ### Commit Message Format Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/NEW-FORMAT-CHECKLIST.md Example of the recommended commit message format. ```text Add {Format} format support - Implement {Format}File with read/write support - Parse audio properties (duration, bitrate, sample rate, channels) - Support {TagType} tags for metadata - Add comprehensive test coverage - Integrate with MediaFile factory for auto-detection Specification: {URL} ``` -------------------------------- ### Code Style Example Source: https://github.com/decriptor/taglibsharp2/blob/main/CONTRIBUTING.md Example demonstrating correct code formatting conventions. ```csharp // Correct public void ProcessData (byte[] data) { if (data is null) throw new ArgumentNullException (nameof (data)); foreach (var item in data) { Process (item); } } ``` -------------------------------- ### Reading Tags - Format-Specific Access Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Access tags for specific audio file formats like MP3, FLAC, Ogg Vorbis, Ogg Opus, MP4/M4A, DSF, and APE. ```csharp using TagLibSharp2.Mpeg; using TagLibSharp2.Xiph; using TagLibSharp2.Ogg; // MP3 files var mp3 = Mp3File.ReadFromFile("song.mp3"); if (mp3.IsSuccess) { var file = mp3.File!; Console.WriteLine($"Title: {file.Title}"); // Access specific tag types var id3v2 = file.Id3v2Tag; // ID3v2 tag (if present) var id3v1 = file.Id3v1Tag; // ID3v1 tag (if present) } // FLAC files var flac = FlacFile.ReadFromFile("song.flac"); if (flac.IsSuccess) { var file = flac.File!; var vorbis = file.VorbisComment; // Vorbis Comment tag Console.WriteLine($"Title: {vorbis?.Title}"); } // Ogg Vorbis files var ogg = OggVorbisFile.ReadFromFile("song.ogg"); if (ogg.IsSuccess) { var file = ogg.File!; Console.WriteLine($"Title: {file.VorbisComment?.Title}"); } // Ogg Opus files (RFC 7845) var opus = OggOpusFile.ReadFromFile("song.opus"); if (opus.IsSuccess) { var file = opus.File!; Console.WriteLine($"Title: {file.VorbisComment?.Title}"); Console.WriteLine($"R128 Gain: {file.Properties?.OutputGain}dB"); } // MP4/M4A files using TagLibSharp2.Mp4; var mp4 = Mp4File.ReadFromFile("song.m4a"); if (mp4.IsSuccess) { var file = mp4.File!; Console.WriteLine($"Title: {file.Title}"); Console.WriteLine($"Duration: {file.Duration}"); Console.WriteLine($"Codec: {file.AudioCodec}"); // Aac, Alac, or Unknown } // DSF files (DSD high-resolution audio) using TagLibSharp2.Dsf; var dsf = DsfFile.ReadFromFile("song.dsf"); if (dsf.IsSuccess) { var file = dsf.File!; Console.WriteLine($"Title: {file.Id3v2Tag?.Title}"); Console.WriteLine($"Sample Rate: {file.Properties?.SampleRate}"); // DSD64=2822400, DSD128=5644800 Console.WriteLine($"Channel Type: {file.Properties?.ChannelType}"); // Mono, Stereo, or Surround } // APE tagged files (MP3 with APEv2) using TagLibSharp2.Ape; var result = Mp3File.ReadFromFile("song.mp3"); if (result.IsSuccess && result.File!.ApeTag is { } ape) { Console.WriteLine($"Title: {ape.Title}"); Console.WriteLine($"ReplayGain: {ape.ReplayGainTrackGain}"); } ``` -------------------------------- ### Writing Tests Example Source: https://github.com/decriptor/taglibsharp2/blob/main/CONTRIBUTING.md Example of a unit test using MSTest. ```csharp [TestMethod] public void AddUInt32BE_WritesCorrectBytes () { var builder = new BinaryDataBuilder (); builder.AddUInt32BE (0x12345678); Assert.AreEqual (4, builder.Length); Assert.AreEqual ((byte)0x12, builder[0]); Assert.AreEqual ((byte)0x78, builder[3]); } ``` -------------------------------- ### Quick Start Build and Test Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/BUILDING.md Commands to clone the repository, build the project, and run tests. ```bash git clone https://github.com/decriptor/TagLibSharp2.git cd tagsharp dotnet build dotnet test ``` -------------------------------- ### Writing Tags - MP3 Files Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Write tags to MP3 files by modifying the properties of an Mp3File object and saving the changes. ```csharp var result = Mp3File.ReadFromFile("song.mp3"); if (result.IsSuccess) { var mp3 = result.File!; // Modify tags mp3.Title = "My Song"; mp3.Artist = "My Artist"; mp3.Album = "My Album"; mp3.Year = "2024"; mp3.Track = 1; mp3.TotalTracks = 12; // Save changes var originalData = File.ReadAllBytes("song.mp3"); mp3.SaveToFile("song.mp3", originalData); } ``` -------------------------------- ### iTunSMPB Format Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/MP4_COMPREHENSIVE_SPECIFICATION_ROADMAP.md Example of the iTunSMPB (iTunes Specific Metadata for Precise Sample Counts) format, used for gapless playback information. ```text ----:com.apple.iTunes:iTunSMPB Value: "00000000 00000840 000001C0 0000000000B3B000 00000000 00000000 00000000 00000000" [padding] [delay] [padding][total_samples] [reserved...] ``` -------------------------------- ### AudioProperties Direct Creation Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/CORE-TYPES.md Example of directly creating an AudioProperties instance. ```csharp // Create directly var props = new AudioProperties( Duration: TimeSpan.FromMinutes(3.5), Bitrate: 320, SampleRate: 44100, BitsPerSample: 16, Channels: 2, Codec: "MP3"); // Check validity if (props.IsValid) Console.WriteLine($"Duration: {props.Duration:mm\\:ss}"); // Create for FLAC var flacProps = AudioProperties.FromFlac( totalSamples: 10584000, sampleRate: 44100, bitsPerSample: 16, channels: 2); ``` -------------------------------- ### Track and Disc Numbers Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/MP4_COMPREHENSIVE_SPECIFICATION_ROADMAP.md Examples illustrating the byte representation for track and disc numbers. ```text - Track 3 of 12: 00 00 00 03 00 0C 00 00 - Disc 1 of 2: 00 00 00 01 00 02 00 00 ``` -------------------------------- ### Test Coverage Expectations Examples Source: https://github.com/decriptor/taglibsharp2/blob/main/CONTRIBUTING.md Examples illustrating tests for happy path, boundary conditions, and error conditions. ```csharp // Happy path [TestMethod] public void AddUInt24BE_WritesCorrectBytes () { ... } // Boundary [TestMethod] public void AddUInt24BE_MaxValue_WritesCorrectBytes () { ... } [TestMethod] public void AddUInt24BE_ZeroValue_WritesCorrectBytes () { ... } // Error condition [TestMethod] public void AddUInt24BE_ExceedsMax_ThrowsArgumentOutOfRange () { ... } ``` -------------------------------- ### Conditional Compilation Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/BUILDING.md C# code demonstrating conditional compilation for framework-specific optimizations. ```csharp #if NETSTANDARD2_0 // Fallback for older frameworks encoding.GetBytes(value, 0, value.Length, _buffer, _length); #else // Modern API encoding.GetBytes(value, _buffer.AsSpan(_length)); #endif ``` -------------------------------- ### VideoProperties Usage Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/CORE-TYPES.md Example of creating and using a VideoProperties object. ```csharp var video = new VideoProperties( Duration: TimeSpan.FromMinutes(90), Width: 1920, Height: 1080, Bitrate: 5000, FrameRate: 23.976, Codec: "H.264"); Console.WriteLine($"Resolution: {video.Width}x{video.Height}"); Console.WriteLine($"Frame rate: {video.FrameRate:F2} fps"); ``` -------------------------------- ### Builder Pattern Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/ARCHITECTURE.md Demonstrates the use of the Builder pattern to construct immutable BinaryData objects. ```csharp // Construction (mutable) var header = new BinaryDataBuilder() .Add(0x49, 0x44, 0x33) // "ID3" .Add(0x04, 0x00) // Version 2.4.0 .Add(0x00) // Flags .AddSyncSafeUInt32(size) // Size .ToBinaryData(); // Immutable result (allocates copy) // Use (immutable) var version = header[3]; var tagSize = header.ToSyncSafeUInt32(6); ``` -------------------------------- ### Writing Tags - FLAC Files Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Write tags to FLAC files by modifying the VorbisComment properties and saving the changes. ```csharp var result = FlacFile.ReadFromFile("song.flac"); if (result.IsSuccess) { var flac = result.File!; var vorbis = flac.VorbisComment ?? new VorbisComment(); vorbis.Title = "My Song"; vorbis.Artist = "My Artist"; var originalData = File.ReadAllBytes("song.flac"); flac.SaveToFile("song.flac", originalData); } ``` -------------------------------- ### Writing Tags - MP4/M4A Files Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/QuickStart.md Write tags to MP4/M4A files by modifying the properties of an Mp4File object and saving the changes. ```csharp using TagLibSharp2.Mp4; var result = Mp4File.ReadFromFile("song.m4a"); if (result.IsSuccess) { var mp4 = result.File!; // Modify tags mp4.Title = "My Song"; mp4.Artist = "My Artist"; mp4.Album = "My Album"; mp4.Year = 2024; mp4.Track = 1; mp4.TotalTracks = 12; // Save changes (reads original data from SourcePath) mp4.SaveToFile(); } ``` -------------------------------- ### Run tests Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/NEW-FORMAT-CHECKLIST.md Command to run all tests for the project. ```bash dotnet test ``` -------------------------------- ### TagLibSharp2 User-Defined Frame Access Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/MIGRATION-FROM-TAGLIB.md Example of getting and setting user-defined ID3v2 frames (TXXX) by description in TagLibSharp2. ```csharp string? gain = id3v2?.GetUserText("REPLAYGAIN_TRACK_GAIN"); id3v2?.SetUserText("REPLAYGAIN_TRACK_GAIN", "-6.5 dB"); ``` -------------------------------- ### Creating NuGet Packages Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/BUILDING.md Commands to create a Release NuGet package and locate it. ```bash # Create NuGet package dotnet pack -c Release # Package location ls src/TagLibSharp2/bin/Release/*.nupkg ``` -------------------------------- ### Directory Structure Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/NEW-FORMAT-CHECKLIST.md Recommended directory structure for a new format implementation within the TagLibSharp2 project. ```text src/TagLibSharp2/{Format}/ ├── {Format}File.cs # Main file class (extends MediaFile) ├── {Format}FileReadResult.cs # Result type (if complex) ├── {Format}Tag.cs # Tag implementation (if format-specific) ├── {Format}AudioProperties.cs # Audio properties (if format-specific) └── {Format}Constants.cs # Magic bytes, GUIDs, etc. (if needed) tests/TagLibSharp2.Tests/{Format}/ ├── {Format}FileTests.cs # Core parsing/rendering tests ├── {Format}TagTests.cs # Tag-specific tests ├── {Format}RoundTripTests.cs # Read-modify-write tests ├── {Format}TestBuilder.cs # Programmatic file creation helper └── {Format}EdgeCaseTests.cs # Edge cases, large files, etc. ``` -------------------------------- ### Testable Code with IFileSystem Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/Cookbook.md Demonstrates how to make code testable by injecting IFileSystem, allowing for the use of mock file systems during testing. ```csharp // Production code uses default file system public class TagService { readonly IFileSystem _fileSystem; public TagService(IFileSystem? fileSystem = null) { _fileSystem = fileSystem ?? DefaultFileSystem.Instance; } public async Task GetTitleAsync(string path) { var result = await Mp3File.ReadFromFileAsync(path, _fileSystem); return result.IsSuccess ? result.File!.Title : null; } } // Test code uses mock [TestMethod] public async Task GetTitle_ValidFile_ReturnsTitle() { var mockFs = new MockFileSystem(); mockFs.AddFile("test.mp3", CreateTestMp3("Test Title")); var service = new TagService(mockFs); var title = await service.GetTitleAsync("test.mp3"); Assert.AreEqual("Test Title", title); } ``` -------------------------------- ### Traditional Language Code Encoding Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/MP4_COMPREHENSIVE_SPECIFICATION_ROADMAP.md Example demonstrating the packing of ISO 639-2/T language codes into a 3x5-bit packed uint16 value. ```plaintext "eng" = 'e'=101, 'n'=110, 'g'=103 Packed: (101-96)<<10 | (110-96)<<5 | (103-96) = 0x15C7 ``` -------------------------------- ### Project Structure Overview Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/BUILDING.md Directory structure of the TagLibSharp2 project. ```bash tagsharp/ ├── Directory.Build.props # Shared build settings ├── Directory.Packages.props # Central package management ├── TagLibSharp2.slnx # Solution file ├── src/ │ └── TagLibSharp2/ │ ├── TagLibSharp2.csproj # Library project │ └── Core/ # Source files └── tests/ └── TagLibSharp2.Tests/ ├── TagLibSharp2.Tests.csproj └── Core/ # Test files ``` -------------------------------- ### AsfGuid Struct Source: https://github.com/decriptor/taglibsharp2/blob/main/tests/TagLibSharp2.Tests/PublicApi/Snapshots/TagLibSharp2.PublicApi.verified.txt Represents an ASF GUID. ```csharp public const int Size = 16; ``` ```csharp public bool Equals(TagLibSharp2.Asf.AsfGuid other) { } ``` ```csharp public override bool Equals(object? obj) { } ``` ```csharp public override int GetHashCode() { } ``` ```csharp public TagLibSharp2.Core.BinaryData Render() { } ``` ```csharp public static TagLibSharp2.Asf.AsfGuidParseResult Parse(System.ReadOnlySpan data) { } ``` ```csharp public static bool operator !=(TagLibSharp2.Asf.AsfGuid left, TagLibSharp2.Asf.AsfGuid right) { } ``` ```csharp public static bool operator ==(TagLibSharp2.Asf.AsfGuid left, TagLibSharp2.Asf.AsfGuid right) { } ``` -------------------------------- ### ImageProperties Usage Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/CORE-TYPES.md Example of creating and using an ImageProperties object. ```csharp var image = new ImageProperties( Width: 3000, Height: 3000, ColorDepth: 24, Format: "JPEG"); Console.WriteLine($"Size: {image.Width}x{image.Height}"); Console.WriteLine($"Color depth: {image.ColorDepth} bpp"); ``` -------------------------------- ### Artwork Structure Example Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/MP4_COMPREHENSIVE_SPECIFICATION_ROADMAP.md Illustrates the hierarchical structure of the 'covr' atom for cover art, showing how multiple data atoms can be included. ```text covr ├── data (type=13, JPEG image bytes) └── data (type=14, PNG image bytes) ``` -------------------------------- ### WMA/ASF Format Support Implementation Files Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/ROADMAP.md List of files created for implementing WMA/ASF format support, including container parsing, tag implementation, and attribute handling. ```csharp src/TagLibSharp2/Asf/ ├── AsfFile.cs # Container parser ├── AsfTag.cs # Tag implementation ├── AsfGuid.cs # 128-bit GUID struct ├── AsfGuids.cs # Well-known GUID constants ├── AsfDescriptor.cs # Typed attribute values ├── AsfContentDescription.cs # 5 fixed fields ├── AsfExtendedContentDescription.cs # Key-value attributes ├── AsfFileProperties.cs # Duration, bitrate └── AsfStreamProperties.cs # Audio codec info ``` -------------------------------- ### AsfGuids Class Source: https://github.com/decriptor/taglibsharp2/blob/main/tests/TagLibSharp2.Tests/PublicApi/Snapshots/TagLibSharp2.PublicApi.verified.txt Contains predefined ASF GUID constants. ```csharp public static readonly TagLibSharp2.Asf.AsfGuid AudioMediaType; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid AudioSpread; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid CodecListObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid ContentDescriptionObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid DataObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid ExtendedContentDescriptionObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid ExtendedStreamPropertiesObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid FilePropertiesObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid HeaderExtensionObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid HeaderObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid LanguageListObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid MetadataLibraryObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid MetadataObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid NoErrorCorrection; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid PaddingObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid SimpleIndexObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid StreamBitratePropertiesObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid StreamPropertiesObject; ``` ```csharp public static readonly TagLibSharp2.Asf.AsfGuid VideoMediaType; ``` -------------------------------- ### Write ReplayGain and R128 Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/Cookbook.md Demonstrates writing ReplayGain and R128 loudness information to an ID3v2 tag. ```csharp var tag = mp3.Id3v2Tag!; // ReplayGain (decibel strings) tag.ReplayGainTrackGain = "-6.50 dB"; tag.ReplayGainTrackPeak = "0.988547"; tag.ReplayGainAlbumGain = "-5.20 dB"; tag.ReplayGainAlbumPeak = "1.000000"; // R128 (Q7.8 format integers) tag.R128TrackGain = "-512"; // -2 dB tag.R128AlbumGain = "256"; // +1 dB ``` -------------------------------- ### MediaTypes Enum Usage Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/CORE-TYPES.md Example of using the MediaTypes enum with HasFlag. ```csharp MediaTypes types = file.MediaTypes; if (types.HasFlag(MediaTypes.Audio)) Console.WriteLine("Has audio"); if (types.HasFlag(MediaTypes.Video)) Console.WriteLine("Has video"); // Check for multiple types if (types == (MediaTypes.Audio | MediaTypes.Video)) Console.WriteLine("Audio+Video container"); ``` -------------------------------- ### ASF/WMA File Handling Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/MIGRATION-FROM-TAGLIB.md Demonstrates reading, accessing audio properties, content description, extended content description, modifying metadata, and saving ASF/WMA files. ```csharp var result = AsfFile.ReadFromFile("audio.wma"); if (result.IsSuccess) { var wma = result.File!; // Audio properties Console.WriteLine($"Duration: {wma.Duration}"); Console.WriteLine($"Sample Rate: {wma.SampleRate}"); Console.WriteLine($"Bitrate: {wma.Bitrate} kbps"); Console.WriteLine($"Channels: {wma.Channels}"); // Content Description (Title, Artist, Copyright) Console.WriteLine($"Title: {wma.Title}"); Console.WriteLine($"Artist: {wma.Artist}"); // Extended Content Description (Album, Year, Genre, etc.) Console.WriteLine($"Album: {wma.Album}"); Console.WriteLine($"Year: {wma.Tag.Year}"); Console.WriteLine($"Genre: {wma.Tag.Genre}"); Console.WriteLine($"Track: {wma.Tag.Track}"); // Modify metadata wma.Title = "New Title"; wma.Artist = "New Artist"; wma.Album = "New Album"; wma.Tag.Year = "2026"; wma.Tag.Genre = "Rock"; wma.SaveToFile("audio.wma"); } ``` -------------------------------- ### Build TagLibSharp2 from source Source: https://github.com/decriptor/taglibsharp2/blob/main/README.md Clone the repository and build the library locally. ```bash git clone https://github.com/decriptor/TagLibSharp2.git cd tagsharp dotnet build ``` -------------------------------- ### IMediaProperties Usage Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/CORE-TYPES.md Example of accessing audio properties through the IMediaFile interface. ```csharp // Access through IMediaFile interface IMediaFile file = MediaFile.Open("song.flac"); IMediaProperties? props = file.AudioProperties; if (props is not null) { Console.WriteLine($"Duration: {props.Duration}"); Console.WriteLine($"Sample Rate: {props.SampleRate} Hz"); Console.WriteLine($"Bitrate: {props.Bitrate} kbps"); Console.WriteLine($"Codec: {props.Codec}"); } ``` -------------------------------- ### Create and Write APE Tags Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/Cookbook.md Shows how to create a new APE tag, set standard and custom fields, and render it to binary data. ```csharp using TagLibSharp2.Ape; // Create a new APE tag var ape = new ApeTag(); // Set standard fields ape.Title = "My Song"; ape.Artist = "My Artist"; ape.Album = "My Album"; ape.Year = "2024"; ape.Track = 1; ape.Genre = "Rock"; // Set ReplayGain values ape.ReplayGainTrackGain = "-6.50 dB"; ape.ReplayGainTrackPeak = "0.988547"; ape.ReplayGainAlbumGain = "-5.20 dB"; ape.ReplayGainAlbumPeak = "0.995123"; // Set custom fields ape.SetValue("CATALOG", "ABC-12345"); ape.SetValue("ENCODER", "My Encoder v1.0"); // Render to binary (with optional header) var tagData = ape.RenderWithOptions(includeHeader: true); ``` -------------------------------- ### AsfGuidParseResult Struct Source: https://github.com/decriptor/taglibsharp2/blob/main/tests/TagLibSharp2.Tests/PublicApi/Snapshots/TagLibSharp2.PublicApi.verified.txt Defines the structure for results when parsing Asf GUIDs. ```csharp public int BytesConsumed { get; } ``` ```csharp public string? Error { get; } ``` ```csharp public bool IsSuccess { get; } ``` ```csharp public TagLibSharp2.Asf.AsfGuid Value { get; } ``` ```csharp public bool Equals(TagLibSharp2.Asf.AsfGuidParseResult other) { } ``` ```csharp public override bool Equals(object? obj) { } ``` ```csharp public override int GetHashCode() { } ``` ```csharp public static TagLibSharp2.Asf.AsfGuidParseResult Failure(string error) { } ``` ```csharp public static TagLibSharp2.Asf.AsfGuidParseResult Success(TagLibSharp2.Asf.AsfGuid value, int bytesConsumed) { } ``` ```csharp public static bool operator !=(TagLibSharp2.Asf.AsfGuidParseResult left, TagLibSharp2.Asf.AsfGuidParseResult right) { } ``` ```csharp public static bool operator ==(TagLibSharp2.Asf.AsfGuidParseResult left, TagLibSharp2.Asf.AsfGuidParseResult right) { } ``` -------------------------------- ### IMediaFile Interface Usage Source: https://github.com/decriptor/taglibsharp2/blob/main/docs/CORE-TYPES.md Example of opening a media file and accessing its properties. ```csharp using IMediaFile file = MediaFile.Open("song.flac"); // Access tag metadata if (file.Tag is not null) { Console.WriteLine($"Title: {file.Tag.Title}"); Console.WriteLine($"Artist: {file.Tag.Artist}"); } // Check media types if (file.MediaTypes.HasFlag(MediaTypes.Audio)) { var props = file.AudioProperties; if (props is not null) Console.WriteLine($"Duration: {props.Duration:mm\\:ss}"); } // Format detection Console.WriteLine($"Format: {file.Format}"); ```