diff --git a/FileTypeChecker.Tests/FileTypeChecker.Tests.csproj b/FileTypeChecker.Tests/FileTypeChecker.Tests.csproj
index f7ca308..828f8a8 100644
--- a/FileTypeChecker.Tests/FileTypeChecker.Tests.csproj
+++ b/FileTypeChecker.Tests/FileTypeChecker.Tests.csproj
@@ -131,5 +131,14 @@
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
diff --git a/FileTypeChecker.Tests/FileTypeValidatorAsyncTests.cs b/FileTypeChecker.Tests/FileTypeValidatorAsyncTests.cs
index d424829..fa7d383 100644
--- a/FileTypeChecker.Tests/FileTypeValidatorAsyncTests.cs
+++ b/FileTypeChecker.Tests/FileTypeValidatorAsyncTests.cs
@@ -59,6 +59,9 @@ public async Task IsTypeRecognizableAsync_ShouldReturnFalseIfFormatIsUnknown()
[TestCase("test.mp4")]
[TestCase("file_example_AVI_480_750kB.avi")]
[TestCase("file_example_WAV_1MG.wav")]
+ [TestCase("test.m4a")]
+ [TestCase("test.flac")]
+ [TestCase("test.ogg")]
public async Task IsTypeRecognizableAsync_ShouldReturnTrueIfFileIsRecognized(string fileName)
{
await using var fileStream = File.OpenRead(Path.Combine(FilesPath, fileName));
@@ -104,6 +107,9 @@ public void GetFileTypeAsync_ShouldThrowTypeNotFoundExceptionWhenTypeIsNotRegist
[TestCase("test-issue-41.xlsx", typeof(MicrosoftOffice365Document))]
[TestCase("file_example_AVI_480_750kB.avi", typeof(AudioVideoInterleaveVideoFormat))]
[TestCase("file_example_WAV_1MG.wav", typeof(WaveformAudioFileFormat))]
+ [TestCase("test.m4a", typeof(M4a))]
+ [TestCase("test.flac", typeof(Flac))]
+ [TestCase("test.ogg", typeof(Ogg))]
public async Task GetFileTypeAsync_ShouldReturnAccurateType(string fileName, Type expectedType)
{
await using var fileStream = File.OpenRead(Path.Combine(FilesPath, fileName));
diff --git a/FileTypeChecker.Tests/FileTypeValidatorTests.cs b/FileTypeChecker.Tests/FileTypeValidatorTests.cs
index be7acec..4fe82e6 100644
--- a/FileTypeChecker.Tests/FileTypeValidatorTests.cs
+++ b/FileTypeChecker.Tests/FileTypeValidatorTests.cs
@@ -60,6 +60,9 @@ public void IsTypeRecognizable_ShouldReturnFalseIfFormatIsUnknown()
[TestCase("test.mp4")]
[TestCase("file_example_AVI_480_750kB.avi")]
[TestCase("file_example_WAV_1MG.wav")]
+ [TestCase("test.m4a")]
+ [TestCase("test.flac")]
+ [TestCase("test.ogg")]
public void IsTypeRecognizable_ShouldReturnTrueIfFileIsRecognized(string filePath)
{
using var fileStream = File.OpenRead(Path.Combine(FilesPath, filePath));
@@ -95,6 +98,9 @@ public void IsTypeRecognizable_ShouldReturnTrueIfFileIsRecognized(string filePat
[TestCase("FileTypeCheckerLogo-150.heic", HighEfficiencyImageFile.TypeMimeType)]
[TestCase("file_example_AVI_480_750kB.avi", AudioVideoInterleaveVideoFormat.TypeMimeType)]
[TestCase("file_example_WAV_1MG.wav", WaveformAudioFileFormat.TypeMimeType)]
+ [TestCase("test.m4a", M4a.TypeMimeType)]
+ [TestCase("test.flac", Flac.TypeMimeType)]
+ [TestCase("test.ogg", Ogg.TypeMimeType)]
public void GetFileType_ShouldReturnFileMimeType(string filePath, string expectedFileExtension)
{
using var fileStream = File.OpenRead(Path.Combine(FilesPath, filePath));
@@ -128,6 +134,9 @@ public void GetFileType_ShouldReturnFileMimeType(string filePath, string expecte
[TestCase("FileTypeCheckerLogo-150.heic", HighEfficiencyImageFile.TypeMimeType)]
[TestCase("file_example_AVI_480_750kB.avi", AudioVideoInterleaveVideoFormat.TypeMimeType)]
[TestCase("file_example_WAV_1MG.wav", WaveformAudioFileFormat.TypeMimeType)]
+ [TestCase("test.m4a", M4a.TypeMimeType)]
+ [TestCase("test.flac", Flac.TypeMimeType)]
+ [TestCase("test.ogg", Ogg.TypeMimeType)]
public void TryGetFileType_ShouldReturnFileMimeType(string filePath, string expectedFileExtension)
{
using var fileStream = File.OpenRead(Path.Combine(FilesPath, filePath));
@@ -160,6 +169,9 @@ public void TryGetFileType_ShouldReturnFileMimeType(string filePath, string expe
[TestCase("FileTypeCheckerLogo-150.heic", HighEfficiencyImageFile.TypeExtension)]
[TestCase("file_example_AVI_480_750kB.avi", AudioVideoInterleaveVideoFormat.TypeExtension)]
[TestCase("file_example_WAV_1MG.wav", WaveformAudioFileFormat.TypeExtension)]
+ [TestCase("test.m4a", M4a.TypeExtension)]
+ [TestCase("test.flac", Flac.TypeExtension)]
+ [TestCase("test.ogg", Ogg.TypeExtension)]
public void GetFileType_ShouldReturnFileExtension(string filePath, string expectedFileExtension)
{
using var fileStream = File.OpenRead(Path.Combine(FilesPath, filePath));
@@ -194,6 +206,9 @@ public void GetFileType_ShouldReturnFileExtension(string filePath, string expect
[TestCase("test-offset.mp4", M4V.TypeExtension)]
[TestCase("file_example_AVI_480_750kB.avi", AudioVideoInterleaveVideoFormat.TypeExtension)]
[TestCase("file_example_WAV_1MG.wav", WaveformAudioFileFormat.TypeExtension)]
+ [TestCase("test.m4a", M4a.TypeExtension)]
+ [TestCase("test.flac", Flac.TypeExtension)]
+ [TestCase("test.ogg", Ogg.TypeExtension)]
public void TryGetFileType_ShouldReturnFileExtension(string filePath, string expectedFileExtension)
{
using var fileStream = File.OpenRead(Path.Combine(FilesPath, filePath));
@@ -274,6 +289,9 @@ public void TryGetFileType_TypeShouldBeNullWhenNotMatching()
[TestCase("FileTypeCheckerLogo-150.heic", HighEfficiencyImageFile.TypeName)]
[TestCase("file_example_AVI_480_750kB.avi", AudioVideoInterleaveVideoFormat.TypeName)]
[TestCase("file_example_WAV_1MG.wav", WaveformAudioFileFormat.TypeName)]
+ [TestCase("test.m4a", M4a.TypeName)]
+ [TestCase("test.flac", Flac.TypeName)]
+ [TestCase("test.ogg", Ogg.TypeName)]
public void GetFileType_ShouldReturnFileName(string filePath, string expectedFileTypeName)
{
using var fileStream = File.OpenRead(Path.Combine(FilesPath, filePath));
@@ -342,6 +360,9 @@ public void Is_ShouldReturnFalseIfTypesDidNotMatch()
[TestCase("test-issue-41.xlsx", typeof(MicrosoftOffice365Document))]
[TestCase("file_example_AVI_480_750kB.avi", typeof(AudioVideoInterleaveVideoFormat))]
[TestCase("file_example_WAV_1MG.wav", typeof(WaveformAudioFileFormat))]
+ [TestCase("test.m4a", typeof(M4a))]
+ [TestCase("test.flac", typeof(Flac))]
+ [TestCase("test.ogg", typeof(Ogg))]
public void GetFileType_ShouldReturnAccurateTypeWhenUsingBytes(string fileName, Type expectedType)
{
var buffer = GetFileBytes(fileName);
diff --git a/FileTypeChecker.Tests/files/test.flac b/FileTypeChecker.Tests/files/test.flac
new file mode 100644
index 0000000..b71f09e
Binary files /dev/null and b/FileTypeChecker.Tests/files/test.flac differ
diff --git a/FileTypeChecker.Tests/files/test.m4a b/FileTypeChecker.Tests/files/test.m4a
new file mode 100644
index 0000000..f48d494
Binary files /dev/null and b/FileTypeChecker.Tests/files/test.m4a differ
diff --git a/FileTypeChecker.Tests/files/test.ogg b/FileTypeChecker.Tests/files/test.ogg
new file mode 100644
index 0000000..335f7e8
Binary files /dev/null and b/FileTypeChecker.Tests/files/test.ogg differ
diff --git a/FileTypeChecker/Extensions/ByteExtensions.cs b/FileTypeChecker/Extensions/ByteExtensions.cs
index 275cd90..f08688b 100644
--- a/FileTypeChecker/Extensions/ByteExtensions.cs
+++ b/FileTypeChecker/Extensions/ByteExtensions.cs
@@ -97,6 +97,20 @@ public static bool IsArchive(this byte[] content)
|| content.Is()
|| content.Is();
+ ///
+ /// Validates that the current file is an audio file.
+ ///
+ /// File content as byte array.
+ /// Returns true if the provided file is an audio file otherwise returns false. Supported audio types are: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static bool IsAudio(this byte[] content)
+ => content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is();
+
///
/// Validates that the current file is executable or executable and linkable.
///
@@ -173,6 +187,21 @@ public static bool IsArchive(this ReadOnlySpan content)
|| content.Is()
|| content.Is();
+ ///
+ /// Validates that the current file is an audio file using high-performance ReadOnlySpan.
+ /// This overload avoids memory allocations and provides optimal performance.
+ ///
+ /// File content as ReadOnlySpan of bytes.
+ /// Returns true if the provided file is an audio file otherwise returns false. Supported audio types are: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static bool IsAudio(this ReadOnlySpan content)
+ => content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is()
+ || content.Is();
+
///
/// Validates that the current file is executable or executable and linkable using high-performance ReadOnlySpan.
/// This overload avoids memory allocations and provides optimal performance.
diff --git a/FileTypeChecker/Extensions/StreamExtensions.cs b/FileTypeChecker/Extensions/StreamExtensions.cs
index 5923e04..4b27ebe 100644
--- a/FileTypeChecker/Extensions/StreamExtensions.cs
+++ b/FileTypeChecker/Extensions/StreamExtensions.cs
@@ -59,6 +59,20 @@ public static bool IsArchive(this Stream fileContent)
|| fileContent.Is()
|| fileContent.Is();
+ ///
+ /// Validates that the current file is an audio file.
+ ///
+ /// File to check as a stream.
+ /// True if the provided file is an audio file; otherwise, false. Supported audio types include: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static bool IsAudio(this Stream fileContent)
+ => fileContent.Is()
+ || fileContent.Is()
+ || fileContent.Is()
+ || fileContent.Is()
+ || fileContent.Is()
+ || fileContent.Is()
+ || fileContent.Is();
+
///
/// Validates that the current file is an executable.
///
@@ -139,6 +153,23 @@ public static async Task IsArchiveAsync(this Stream fileContent, Cancellat
|| await fileContent.IsAsync(cancellationToken).ConfigureAwait(false);
}
+ ///
+ /// Asynchronously validates that the current file is an audio file.
+ ///
+ /// File to check as a stream.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains true if the provided file is an audio file; otherwise, false. Supported audio types include: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static async Task IsAudioAsync(this Stream fileContent, CancellationToken cancellationToken = default)
+ {
+ return await fileContent.IsAsync(cancellationToken).ConfigureAwait(false)
+ || await fileContent.IsAsync(cancellationToken).ConfigureAwait(false)
+ || await fileContent.IsAsync(cancellationToken).ConfigureAwait(false)
+ || await fileContent.IsAsync(cancellationToken).ConfigureAwait(false)
+ || await fileContent.IsAsync(cancellationToken).ConfigureAwait(false)
+ || await fileContent.IsAsync(cancellationToken).ConfigureAwait(false)
+ || await fileContent.IsAsync(cancellationToken).ConfigureAwait(false);
+ }
+
///
/// Asynchronously validates that the current file is an executable.
///
diff --git a/FileTypeChecker/FileTypeValidator.cs b/FileTypeChecker/FileTypeValidator.cs
index 9e089e0..99e4fe0 100644
--- a/FileTypeChecker/FileTypeValidator.cs
+++ b/FileTypeChecker/FileTypeValidator.cs
@@ -156,6 +156,14 @@ public static void RegisterCustomTypes(params Assembly[] assemblies)
public static bool Is(Stream fileContent) where T : FileType, IFileType, new()
=> fileContent.Is();
+ ///
+ /// Validates that the current file is an audio file.
+ ///
+ /// File to check as a stream.
+ /// Returns true if the provided file is an audio file otherwise returns false. Supported audio types are: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static bool IsAudio(Stream fileContent)
+ => fileContent.IsAudio();
+
///
/// Validates that the current file is an image.
///
@@ -181,6 +189,14 @@ public static bool IsArchive(Stream fileContent)
public static bool Is(byte[] fileContent) where T : FileType, IFileType, new()
=> fileContent.Is();
+ ///
+ /// Validates that the current file is an audio file.
+ ///
+ /// File bytes.
+ /// Returns true if the provided file is an audio file otherwise returns false. Supported audio types are: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static bool IsAudio(byte[] fileContent)
+ => fileContent.IsAudio();
+
///
/// Validates that the current file is an image.
///
@@ -274,6 +290,15 @@ public static async Task TryGetFileTypeAsync(Stream fileContent, Ca
public static async Task IsAsync(Stream fileContent, CancellationToken cancellationToken = default) where T : FileType, IFileType, new()
=> await fileContent.IsAsync(cancellationToken).ConfigureAwait(false);
+ ///
+ /// Asynchronously validates that the current file is an audio file.
+ ///
+ /// File to check as a stream.
+ /// A cancellation token that can be used to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation. The task result contains true if the provided file is an audio file; otherwise, false. Supported audio types include: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static async Task IsAudioAsync(Stream fileContent, CancellationToken cancellationToken = default)
+ => await fileContent.IsAudioAsync(cancellationToken).ConfigureAwait(false);
+
///
/// Asynchronously validates that the current file is an image.
///
@@ -362,6 +387,15 @@ public static MatchResult TryGetFileType(ReadOnlySpan fileContent)
public static bool Is(ReadOnlySpan fileContent) where T : FileType, IFileType, new()
=> fileContent.Is();
+ ///
+ /// Validates that the current file is an audio file using high-performance ReadOnlySpan.
+ /// This overload avoids memory allocations and provides optimal performance.
+ ///
+ /// File content as ReadOnlySpan of bytes.
+ /// True if the provided file is an audio file; otherwise, false. Supported audio types include: MP3, WAV, FLAC, OGG, M4A, and WMA.
+ public static bool IsAudio(ReadOnlySpan fileContent)
+ => fileContent.IsAudio();
+
///
/// Validates that the current file is an image using high-performance ReadOnlySpan.
/// This overload avoids memory allocations and provides optimal performance.
diff --git a/FileTypeChecker/Types/Flac.cs b/FileTypeChecker/Types/Flac.cs
new file mode 100644
index 0000000..c3c4861
--- /dev/null
+++ b/FileTypeChecker/Types/Flac.cs
@@ -0,0 +1,19 @@
+namespace FileTypeChecker.Types
+{
+ using Abstracts;
+
+ ///
+ /// Free Lossless Audio Codec file. Identified by the fLaC magic marker.
+ ///
+ public class Flac : FileType, IFileType
+ {
+ public const string TypeName = "FLAC audio file";
+ public const string TypeMimeType = "audio/flac";
+ public const string TypeExtension = "flac";
+ private static readonly byte[] MagicBytes = { 0x66, 0x4C, 0x61, 0x43 }; // fLaC
+
+ public Flac() : base(TypeName, TypeMimeType, TypeExtension, MagicBytes)
+ {
+ }
+ }
+}
diff --git a/FileTypeChecker/Types/M4a.cs b/FileTypeChecker/Types/M4a.cs
new file mode 100644
index 0000000..32393e1
--- /dev/null
+++ b/FileTypeChecker/Types/M4a.cs
@@ -0,0 +1,23 @@
+using FileTypeChecker.Abstracts;
+
+namespace FileTypeChecker.Types
+{
+ ///
+ /// MPEG-4 audio file (AAC). Identified by ftyp box with M4A or M4B brand.
+ ///
+ public class M4a : FileType, IFileType
+ {
+ public const string TypeName = "MPEG-4 audio file";
+ public const string TypeMimeType = "audio/mp4";
+ public const string TypeExtension = "m4a";
+ private static readonly MagicSequence[] MagicBytesSequence =
+ {
+ new(new byte[] { 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20 }, 4), // ftypM4A
+ new(new byte[] { 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x42, 0x20 }, 4), // ftypM4B
+ };
+
+ public M4a() : base(TypeName, TypeMimeType, TypeExtension, MagicBytesSequence)
+ {
+ }
+ }
+}
diff --git a/FileTypeChecker/Types/Ogg.cs b/FileTypeChecker/Types/Ogg.cs
new file mode 100644
index 0000000..52895be
--- /dev/null
+++ b/FileTypeChecker/Types/Ogg.cs
@@ -0,0 +1,19 @@
+namespace FileTypeChecker.Types
+{
+ using Abstracts;
+
+ ///
+ /// Ogg container file (Vorbis, Opus, FLAC). Identified by the OggS capture pattern.
+ ///
+ public class Ogg : FileType, IFileType
+ {
+ public const string TypeName = "Ogg audio file";
+ public const string TypeMimeType = "audio/ogg";
+ public const string TypeExtension = "ogg";
+ private static readonly byte[] MagicBytes = { 0x4F, 0x67, 0x67, 0x53 }; // OggS
+
+ public Ogg() : base(TypeName, TypeMimeType, TypeExtension, MagicBytes)
+ {
+ }
+ }
+}