Initial commit

This commit is contained in:
Thastertyn committed 2024-06-07 00:47:07 +02:00
commit 262601edb8
2025 files changed
+218754

No files matched your search

+271
View File
@@ -0,0 +1,271 @@
//
// File.cs: Provides tagging and properties support for WavPack files.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Original Source:
// wvfile.cpp from libtunepimp
//
// Copyright (C) 2006-2007 Brian Nickel
// Copyright (C) 2006 by Lukáš Lalinský (Original Implementation)
// Copyright (C) 2004 by Allan Sandfeld Jensen (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
namespace TagLib.WavPack
{
/// <summary>
/// This class extends <see cref="TagLib.NonContainer.File" /> to
/// provide tagging and properties support for WavPack files.
/// </summary>
/// <remarks>
/// A <see cref="TagLib.Ape.Tag" /> will be added automatically to
/// any file that doesn't contain one. This change does not effect
/// the file and can be reversed using the following method:
/// <code>file.RemoveTags (file.TagTypes &amp; ~file.TagTypesOnDisk);</code>
/// </remarks>
[SupportedMimeType ("taglib/wv", "wv")]
[SupportedMimeType ("audio/x-wavpack")]
public class File : TagLib.NonContainer.File
{
#region Private Fields
/// <summary>
/// Contains the block with the audio header.
/// </summary>
ByteVector header_block;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local file
/// system and specified read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path, ReadStyle propertiesStyle)
: base (path, propertiesStyle)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local file
/// system with an average read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path)
: base (path)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified file abstraction and
/// specified read style.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
/// reading from and writing to the file.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public File (IFileAbstraction abstraction, ReadStyle propertiesStyle)
: base (abstraction, propertiesStyle)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified file abstraction with an
/// average read style.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
/// reading from and writing to the file.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public File (IFileAbstraction abstraction)
: base (abstraction)
{
}
#endregion
#region Public Methods
/// <summary>
/// Gets a tag of a specified type from the current instance,
/// optionally creating a new tag if possible.
/// </summary>
/// <param name="type">
/// A <see cref="TagLib.TagTypes" /> value indicating the
/// type of tag to read.
/// </param>
/// <param name="create">
/// A <see cref="bool" /> value specifying whether or not to
/// try and create the tag if one is not found.
/// </param>
/// <returns>
/// A <see cref="Tag" /> object containing the tag that was
/// found in or added to the current instance. If no
/// matching tag was found and none was created, <see
/// langword="null" /> is returned.
/// </returns>
/// <remarks>
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
/// current instance, it will be placed at the start of the
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
/// the file. All other tag types will be ignored.
/// </remarks>
public override Tag GetTag (TagTypes type, bool create)
{
Tag t = (Tag as TagLib.NonContainer.Tag).GetTag (type);
if (t != null || !create)
return t;
switch (type) {
case TagTypes.Id3v1:
return EndTag.AddTag (type, Tag);
case TagTypes.Id3v2:
return StartTag.AddTag (type, Tag);
case TagTypes.Ape:
return EndTag.AddTag (type, Tag);
default:
return null;
}
}
#endregion
#region Protected Methods
/// <summary>
/// Reads format specific information at the start of the
/// file.
/// </summary>
/// <param name="start">
/// A <see cref="long" /> value containing the seek position
/// at which the tags end and the media data begins.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
protected override void ReadStart (long start, ReadStyle propertiesStyle)
{
if (header_block != null &&
(propertiesStyle & ReadStyle.Average) == 0)
return;
Seek (start);
header_block = ReadBlock ((int)StreamHeader.Size);
}
/// <summary>
/// Reads format specific information at the end of the
/// file.
/// </summary>
/// <param name="end">
/// A <see cref="long" /> value containing the seek position
/// at which the media data ends and the tags begin.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
protected override void ReadEnd (long end, ReadStyle propertiesStyle)
{
// Make sure we have an APE tag.
GetTag (TagTypes.Ape, true);
}
/// <summary>
/// Reads the audio properties from the file represented by
/// the current instance.
/// </summary>
/// <param name="start">
/// A <see cref="long" /> value containing the seek position
/// at which the tags end and the media data begins.
/// </param>
/// <param name="end">
/// A <see cref="long" /> value containing the seek position
/// at which the media data ends and the tags begin.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <returns>
/// A <see cref="TagLib.Properties" /> object describing the
/// media properties of the file represented by the current
/// instance.
/// </returns>
protected override Properties ReadProperties (long start, long end, ReadStyle propertiesStyle)
{
var header = new StreamHeader (header_block, end - start);
return new Properties (TimeSpan.Zero, header);
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6eebeb3ba6e5197978bd617d19e032cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+358
View File
@@ -0,0 +1,358 @@
//
// StreamHeader.cs: Provides support for reading WavPack audio properties.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Original Source:
// wvproperties.cpp from libtunepimp
//
// Copyright (C) 2006-2007 Brian Nickel
// Copyright (C) 2006 by Lukáš Lalinský (Original Implementation)
// Copyright (C) 2004 by Allan Sandfeld Jensen (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
using System.Globalization;
namespace TagLib.WavPack
{
/// <summary>
/// This struct implements <see cref="IAudioCodec" /> to provide
/// support for reading WavPack audio properties.
/// </summary>
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec, IEquatable<StreamHeader>
{
#region Constants
static readonly uint[] sample_rates = new uint[] {
6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
32000, 44100, 48000, 64000, 88200, 96000, 192000};
const int BYTES_STORED = 3;
const int MONO_FLAG = 4;
const int SHIFT_LSB = 13;
const long SHIFT_MASK = (0x1fL << SHIFT_LSB);
const int SRATE_LSB = 23;
const long SRATE_MASK = (0xfL << SRATE_LSB);
#endregion
#region Private Fields
/// <summary>
/// Contains the number of bytes in the stream.
/// </summary>
readonly long stream_length;
/// <summary>
/// Contains the WavPack version.
/// </summary>
readonly ushort version;
/// <summary>
/// Contains the flags.
/// </summary>
readonly uint flags;
/// <summary>
/// Contains the sample count.
/// </summary>
readonly uint samples;
#endregion
#region Public Static Fields
/// <summary>
/// The size of a WavPack header.
/// </summary>
public const uint Size = 32;
/// <summary>
/// The identifier used to recognize a WavPack file.
/// </summary>
/// <value>
/// "wvpk"
/// </value>
public static readonly ReadOnlyByteVector FileIdentifier = "wvpk";
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="StreamHeader" /> for a specified header block and
/// stream length.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the stream
/// header data.
/// </param>
/// <param name="streamLength">
/// A <see cref="long" /> value containing the length of the
/// WavPack stream in bytes.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> does not begin with <see
/// cref="FileIdentifier" /> or is less than <see cref="Size"
/// /> bytes long.
/// </exception>
public StreamHeader (ByteVector data, long streamLength)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (!data.StartsWith (FileIdentifier))
throw new CorruptFileException ("Data does not begin with identifier.");
if (data.Count < Size)
throw new CorruptFileException ("Insufficient data in stream header");
stream_length = streamLength;
version = data.Mid (8, 2).ToUShort (false);
flags = data.Mid (24, 4).ToUInt (false);
samples = data.Mid (12, 4).ToUInt (false);
}
#endregion
#region Public Properties
/// <summary>
/// Gets the duration of the media represented by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="TimeSpan" /> containing the duration of the
/// media represented by the current instance.
/// </value>
public TimeSpan Duration {
get {
return AudioSampleRate > 0 ?
TimeSpan.FromSeconds (samples / (double)AudioSampleRate + 0.5) : TimeSpan.Zero;
}
}
/// <summary>
/// Gets the types of media represented by the current
/// instance.
/// </summary>
/// <value>
/// Always <see cref="MediaTypes.Audio" />.
/// </value>
public MediaTypes MediaTypes {
get { return MediaTypes.Audio; }
}
/// <summary>
/// Gets a text description of the media represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing a description
/// of the media represented by the current instance.
/// </value>
public string Description {
get {
return string.Format (CultureInfo.InvariantCulture, "WavPack Version {0} Audio", Version);
}
}
/// <summary>
/// Gets the bitrate of the audio represented by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing a bitrate of the
/// audio represented by the current instance.
/// </value>
public int AudioBitrate {
get {
return (int)(Duration > TimeSpan.Zero ? ((stream_length * 8L) / Duration.TotalSeconds) / 1000 : 0);
}
}
/// <summary>
/// Gets the sample rate of the audio represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing the sample rate of
/// the audio represented by the current instance.
/// </value>
public int AudioSampleRate {
get {
return (int)(sample_rates[(flags & SRATE_MASK) >> SRATE_LSB]);
}
}
/// <summary>
/// Gets the number of channels in the audio represented by
/// the current instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing the number of
/// channels in the audio represented by the current
/// instance.
/// </value>
public int AudioChannels {
get { return ((flags & MONO_FLAG) != 0) ? 1 : 2; }
}
/// <summary>
/// Gets the WavPack version of the audio represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing the WavPack version
/// of the audio represented by the current instance.
/// </value>
public int Version {
get { return version; }
}
/// <summary>
/// Gets the number of bits per sample in the audio
/// represented by the current instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing the number of bits
/// per sample in the audio represented by the current
/// instance.
/// </value>
public int BitsPerSample {
get {
return (int)(((flags & BYTES_STORED) + 1) * 8 - ((flags & SHIFT_MASK) >> SHIFT_LSB));
}
}
#endregion
#region IEquatable
/// <summary>
/// Generates a hash code for the current instance.
/// </summary>
/// <returns>
/// A <see cref="int" /> value containing the hash code for
/// the current instance.
/// </returns>
public override int GetHashCode ()
{
unchecked {
return (int)(flags ^ samples ^ version);
}
}
/// <summary>
/// Checks whether or not the current instance is equal to
/// another object.
/// </summary>
/// <param name="other">
/// A <see cref="object" /> to compare to the current
/// instance.
/// </param>
/// <returns>
/// A <see cref="bool" /> value indicating whether or not the
/// current instance is equal to <paramref name="other" />.
/// </returns>
/// <seealso cref="M:System.IEquatable`1.Equals" />
public override bool Equals (object other)
{
if (!(other is StreamHeader))
return false;
return Equals ((StreamHeader)other);
}
/// <summary>
/// Checks whether or not the current instance is equal to
/// another instance of <see cref="StreamHeader" />.
/// </summary>
/// <param name="other">
/// A <see cref="StreamHeader" /> object to compare to the
/// current instance.
/// </param>
/// <returns>
/// A <see cref="bool" /> value indicating whether or not the
/// current instance is equal to <paramref name="other" />.
/// </returns>
/// <seealso cref="M:System.IEquatable`1.Equals" />
public bool Equals (StreamHeader other)
{
return flags == other.flags &&
samples == other.samples &&
version == other.version;
}
/// <summary>
/// Gets whether or not two instances of <see
/// cref="StreamHeader" /> are equal to eachother.
/// </summary>
/// <param name="first">
/// The first <see cref="StreamHeader" /> object to compare.
/// </param>
/// <param name="second">
/// The second <see cref="StreamHeader" /> object to compare.
/// </param>
/// <returns>
/// <see langword="true" /> if <paramref name="first" /> is
/// equal to <paramref name="second" />. Otherwise, <see
/// langword="false" />.
/// </returns>
public static bool operator == (StreamHeader first, StreamHeader second)
{
return first.Equals (second);
}
/// <summary>
/// Gets whether or not two instances of <see
/// cref="StreamHeader" /> are unequal to eachother.
/// </summary>
/// <param name="first">
/// The first <see cref="StreamHeader" /> object to compare.
/// </param>
/// <param name="second">
/// The second <see cref="StreamHeader" /> object to compare.
/// </param>
/// <returns>
/// <see langword="true" /> if <paramref name="first" /> is
/// unequal to <paramref name="second" />. Otherwise, <see
/// langword="false" />.
/// </returns>
public static bool operator != (StreamHeader first, StreamHeader second)
{
return !first.Equals (second);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d72dc2a9c5da35782929ef6eadf5d622
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: