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

+287
View File
@@ -0,0 +1,287 @@
//
// AviHeaderList.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Collections.Generic;
namespace TagLib.Riff
{
/// <summary>
/// This class provides support for reading an AVI header list to
/// extract stream information.
/// </summary>
public class AviHeaderList
{
/// <summary>
/// Contains the AVI codec information.
/// </summary>
readonly List<ICodec> codecs = new List<ICodec> ();
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="AviHeaderList" /> by reading the contents of a raw
/// RIFF list from a specified position in a <see
/// cref="TagLib.File"/>.
/// </summary>
/// <param name="file">
/// A <see cref="TagLib.File" /> object containing the file
/// from which the contents of the new instance is to be
/// read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the list.
/// </param>
/// <param name="length">
/// A <see cref="int" /> value specifying the number of bytes
/// to read.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="position" /> is less than zero or greater
/// than the size of the file.
/// </exception>
/// <exception cref="CorruptFileException">
/// The list does not contain an AVI header or the AVI header
/// is the wrong length.
/// </exception>
public AviHeaderList (TagLib.File file, long position, int length)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
if (length < 0)
throw new ArgumentOutOfRangeException (nameof (length));
if (position < 0 || position > file.Length - length)
throw new ArgumentOutOfRangeException (nameof (position));
List list = new List (file, position, length);
if (!list.ContainsKey ("avih"))
throw new CorruptFileException ("Avi header not found.");
ByteVector header_data = list["avih"][0];
if (header_data.Count != 0x38)
throw new CorruptFileException ("Invalid header length.");
Header = new AviHeader (header_data, 0);
foreach (ByteVector list_data in list["LIST"]) {
if (list_data.StartsWith ("strl")) {
AviStream stream = AviStream.ParseStreamList (list_data);
if (stream != null)
codecs.Add (stream.Codec);
}
}
}
/// <summary>
/// Gets the header for the current instance.
/// </summary>
/// <value>
/// A <see cref="AviHeader" /> object containing the header
/// for the current instance.
/// </value>
public AviHeader Header { get; private set; }
/// <summary>
/// Gets the codecs contained in the current instance.
/// </summary>
/// <value>
/// A <see cref="T:ICodec[]" /> containing the codecs contained
/// in the current instance.
/// </value>
public ICodec[] Codecs {
get { return codecs.ToArray (); }
}
}
/// <summary>
/// This structure provides a representation of a Microsoft
/// AviMainHeader structure, minus the first 8 bytes.
/// </summary>
public struct AviHeader
{
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="AviHeader" /> by reading the raw structure from the
/// beginning of a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 40 bytes.
/// </exception>
[Obsolete ("Use AviHeader(ByteVector,int)")]
public AviHeader (ByteVector data) : this (data, 0)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="AviStreamHeader" /> by reading the raw structure
/// from a specified position in a <see cref="ByteVector" />
/// object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <param name="offset">
/// A <see cref="int" /> value specifying the index in
/// <paramref name="data"/> at which the structure begins.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="offset" /> is less than zero.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 40 bytes at
/// <paramref name="offset" />.
/// </exception>
public AviHeader (ByteVector data, int offset)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (offset < 0)
throw new ArgumentOutOfRangeException (nameof (offset));
if (offset + 40 > data.Count)
throw new CorruptFileException ("Expected 40 bytes.");
MicrosecondsPerFrame = data.Mid (offset, 4).ToUInt (false);
MaxBytesPerSecond = data.Mid (offset + 4, 4).ToUInt (false);
Flags = data.Mid (offset + 12, 4).ToUInt (false);
TotalFrames = data.Mid (offset + 16, 4).ToUInt (false);
InitialFrames = data.Mid (offset + 20, 4).ToUInt (false);
Streams = data.Mid (offset + 24, 4).ToUInt (false);
SuggestedBufferSize = data.Mid (offset + 28, 4).ToUInt (false);
Width = data.Mid (offset + 32, 4).ToUInt (false);
Height = data.Mid (offset + 36, 4).ToUInt (false);
}
/// <summary>
/// Gets the number of microseconds per frame.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying number of
/// microseconds per frame.
/// </value>
public uint MicrosecondsPerFrame { get; private set; }
/// <summary>
/// Gets the maximum number of bytes per second.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying maximum number of
/// bytes per second.
/// </value>
public uint MaxBytesPerSecond { get; private set; }
/// <summary>
/// Gets the file flags.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying file flags.
/// </value>
public uint Flags { get; private set; }
/// <summary>
/// Gets the number of frames in the file.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the number of
/// frames in the file.
/// </value>
public uint TotalFrames { get; private set; }
/// <summary>
/// Gets how far ahead audio is from video.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying how far ahead
/// audio is from video.
/// </value>
public uint InitialFrames { get; private set; }
/// <summary>
/// Gets the number of streams in the file.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the number of
/// streams in the file.
/// </value>
public uint Streams { get; private set; }
/// <summary>
/// Gets the suggested buffer size for the file.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the buffer size.
/// </value>
public uint SuggestedBufferSize { get; private set; }
/// <summary>
/// Gets the width of the video in the file.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the width of the
/// video.
/// </value>
public uint Width { get; private set; }
/// <summary>
/// Gets the height of the video in the file.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the height of the
/// video.
/// </value>
public uint Height { get; private set; }
/// <summary>
/// Gets the duration of the media in the file.
/// </summary>
/// <value>
/// A <see cref="TimeSpan" /> value containing the duration
/// of the file.
/// </value>
public TimeSpan Duration {
get {
return TimeSpan.FromMilliseconds (TotalFrames * (double)MicrosecondsPerFrame / 1000.0);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d6e2f945ab4b69792bad77daa3649ff8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+458
View File
@@ -0,0 +1,458 @@
//
// AviStream.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This abstract class provides basic support for parsing a raw AVI
/// stream list.
/// </summary>
public abstract class AviStream
{
/// <summary>
/// Constructs and intializes a new instance of <see
/// cref="AviStream" /> with a specified stream header.
/// </summary>
/// <param name="header">
/// A <see cref="AviStreamHeader"/> object containing the
/// stream's header.
/// </param>
protected AviStream (AviStreamHeader header)
{
Header = header;
}
/// <summary>
/// Parses a stream list item.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the item's
/// ID.
/// </param>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the item's
/// data.
/// </param>
/// <param name="start">
/// A <see cref="uint" /> value specifying the index in
/// <paramref name="data" /> at which the item data begins.
/// </param>
/// <param name="length">
/// A <see cref="uint" /> value specifying the length of the
/// item.
/// </param>
public virtual void ParseItem (ByteVector id, ByteVector data, int start, int length)
{
}
/// <summary>
/// Gets the stream header.
/// </summary>
/// <value>
/// A <see cref="AviStreamHeader" /> object containing the
/// header information for the stream.
/// </value>
public AviStreamHeader Header { get; private set; }
/// <summary>
/// Gets the codec information.
/// </summary>
/// <value>
/// A <see cref="ICodec" /> object containing the codec
/// information for the stream.
/// </value>
public ICodec Codec { get; protected set; }
/// <summary>
/// Parses a raw AVI stream list and returns the stream
/// information.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing raw stream
/// list.
/// </param>
/// <returns>
/// A <see cref="AviStream" /> object containing stream
/// information.
/// </returns>
public static AviStream ParseStreamList (ByteVector data)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (!data.StartsWith ("strl"))
return null;
AviStream stream = null;
int pos = 4;
while (pos + 8 < data.Count) {
ByteVector id = data.Mid (pos, 4);
int block_length = (int)data.Mid (pos + 4, 4).ToUInt (false);
if (id == "strh" && stream == null) {
var stream_header = new AviStreamHeader (data, pos + 8);
if (stream_header.Type == "vids")
stream = new AviVideoStream (stream_header);
else if (stream_header.Type == "auds")
stream = new AviAudioStream (stream_header);
} else if (stream != null) {
stream.ParseItem (id, data, pos + 8, block_length);
}
pos += block_length + 8;
}
return stream;
}
}
/// <summary>
/// This class extends <see cref="AviStream" /> to provide support
/// for reading audio stream data.
/// </summary>
public class AviAudioStream : AviStream
{
/// <summary>
/// Constructs and intializes a new instance of <see
/// cref="AviAudioStream" /> with a specified stream header.
/// </summary>
/// <param name="header">
/// A <see cref="AviStreamHeader"/> object containing the
/// stream's header.
/// </param>
public AviAudioStream (AviStreamHeader header)
: base (header)
{
}
/// <summary>
/// Parses a stream list item.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the item's
/// ID.
/// </param>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the item's
/// data.
/// </param>
/// <param name="start">
/// A <see cref="uint" /> value specifying the index in
/// <paramref name="data" /> at which the item data begins.
/// </param>
/// <param name="length">
/// A <see cref="uint" /> value specifying the length of the
/// item.
/// </param>
public override void ParseItem (ByteVector id, ByteVector data, int start, int length)
{
if (id == "strf")
Codec = new WaveFormatEx (data, start);
}
}
/// <summary>
/// This class extends <see cref="AviStream" /> to provide support
/// for reading video stream data.
/// </summary>
public class AviVideoStream : AviStream
{
/// <summary>
/// Constructs and intializes a new instance of <see
/// cref="AviVideoStream" /> with a specified stream header.
/// </summary>
/// <param name="header">
/// A <see cref="AviStreamHeader"/> object containing the
/// stream's header.
/// </param>
public AviVideoStream (AviStreamHeader header)
: base (header)
{
}
/// <summary>
/// Parses a stream list item.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the item's
/// ID.
/// </param>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the item's
/// data.
/// </param>
/// <param name="start">
/// A <see cref="uint" /> value specifying the index in
/// <paramref name="data" /> at which the item data begins.
/// </param>
/// <param name="length">
/// A <see cref="uint" /> value specifying the length of the
/// item.
/// </param>
public override void ParseItem (ByteVector id, ByteVector data, int start, int length)
{
if (id == "strf")
Codec = new BitmapInfoHeader (data, start);
}
}
/// <summary>
/// This structure provides a representation of a Microsoft
/// AviStreamHeader structure, minus the first 8 bytes.
/// </summary>
public struct AviStreamHeader
{
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="AviStreamHeader" /> by reading the raw structure
/// from the beginning of a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 56 bytes.
/// </exception>
[Obsolete ("Use WaveFormatEx(ByteVector,int)")]
public AviStreamHeader (ByteVector data) : this (data, 0)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="AviStreamHeader" /> by reading the raw structure
/// from a specified position in a <see cref="ByteVector" />
/// object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <param name="offset">
/// A <see cref="int" /> value specifying the index in
/// <paramref name="data"/> at which the structure begins.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="offset" /> is less than zero.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 56 bytes at
/// <paramref name="offset" />.
/// </exception>
public AviStreamHeader (ByteVector data, int offset)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (offset < 0)
throw new ArgumentOutOfRangeException (nameof (offset));
if (offset + 56 > data.Count)
throw new CorruptFileException ("Expected 56 bytes.");
Type = data.Mid (offset, 4);
Handler = data.Mid (offset + 4, 4);
Flags = data.Mid (offset + 8, 4).ToUInt (false);
Priority = data.Mid (offset + 12, 4).ToUInt (false);
InitialFrames = data.Mid (offset + 16, 4).ToUInt (false);
Scale = data.Mid (offset + 20, 4).ToUInt (false);
Rate = data.Mid (offset + 24, 4).ToUInt (false);
Start = data.Mid (offset + 28, 4).ToUInt (false);
Length = data.Mid (offset + 32, 4).ToUInt (false);
SuggestedBufferSize = data.Mid (offset + 36, 4).ToUInt (false);
Quality = data.Mid (offset + 40, 4).ToUInt (false);
SampleSize = data.Mid (offset + 44, 4).ToUInt (false);
Left = data.Mid (offset + 48, 2).ToUShort (false);
Top = data.Mid (offset + 50, 2).ToUShort (false);
Right = data.Mid (offset + 52, 2).ToUShort (false);
Bottom = data.Mid (offset + 54, 2).ToUShort (false);
}
/// <summary>
/// Gets the stream type.
/// </summary>
/// <value>
/// A four-byte <see cref="ByteVector" /> object specifying
/// stream type.
/// </value>
public ByteVector Type { get; private set; }
/// <summary>
/// Gets the stream handler (codec) ID.
/// </summary>
/// <value>
/// A four-byte <see cref="ByteVector" /> object specifying
/// stream handler ID.
/// </value>
public ByteVector Handler { get; private set; }
/// <summary>
/// Gets the stream flags.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying stream flags.
/// </value>
public uint Flags { get; private set; }
/// <summary>
/// Gets the stream priority.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying stream priority.
/// </value>
public uint Priority { get; private set; }
/// <summary>
/// Gets how far ahead audio is from video.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying how far ahead
/// audio is from video.
/// </value>
public uint InitialFrames { get; private set; }
/// <summary>
/// Gets the scale of the stream.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the scale of the
/// stream.
/// </value>
/// <remarks>
/// Dividing <see cref="Rate"/> by <see cref="Scale" /> gives
/// the number of samples per second.
/// </remarks>
public uint Scale { get; private set; }
/// <summary>
/// Gets the rate of the stream.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the rate of the
/// stream.
/// </value>
/// <remarks>
/// Dividing <see cref="Rate"/> by <see cref="Scale" /> gives
/// the number of samples per second.
/// </remarks>
public uint Rate { get; private set; }
/// <summary>
/// Gets the start delay of the stream.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the start delay of
/// the stream.
/// </value>
public uint Start { get; private set; }
/// <summary>
/// Gets the length of the stream.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the length of the
/// stream.
/// </value>
public uint Length { get; private set; }
/// <summary>
/// Gets the suggested buffer size for the stream.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the buffer size.
/// </value>
public uint SuggestedBufferSize { get; private set; }
/// <summary>
/// Gets the quality of the stream data.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the quality of the
/// stream data between 0 and 10,000.
/// </value>
public uint Quality { get; private set; }
/// <summary>
/// Gets the sample size of the stream data.
/// </summary>
/// <value>
/// A <see cref="uint" /> value specifying the sample size.
/// </value>
public uint SampleSize { get; private set; }
/// <summary>
/// Gets the position at which the left of the video is to
/// be displayed in the rectangle whose width is given in the
/// the file's <see cref="AviHeader"/>.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value specifying the left
/// position.
/// </value>
public ushort Left { get; private set; }
/// <summary>
/// Gets the position at which the top of the video is to be
/// displayed in the rectangle whose height is given in the
/// the file's <see cref="AviHeader"/>.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value specifying the top
/// position.
/// </value>
public ushort Top { get; private set; }
/// <summary>
/// Gets the position at which the right of the video is to
/// be displayed in the rectangle whose width is given in the
/// the file's <see cref="AviHeader"/>.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value specifying the right
/// position.
/// </value>
public ushort Right { get; private set; }
/// <summary>
/// Gets the position at which the bottom of the video is
/// to be displayed in the rectangle whose height is given in
/// the file's <see cref="AviHeader"/>.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value specifying the bottom
/// position.
/// </value>
public ushort Bottom { get; private set; }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eedf8b2276ea9a00a824c1315ce11965
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,783 @@
//
// BitmapInfoHeader.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This structure provides a representation of a Microsoft
/// BitmapInfoHeader structure.
/// </summary>
public struct BitmapInfoHeader : IVideoCodec
{
#region Private Fields
/// <summary>
/// Contains the video width.
/// </summary>
readonly uint width;
/// <summary>
/// Contains the video height.
/// </summary>
readonly uint height;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="BitmapInfoHeader" /> by reading the raw structure
/// from the beginning of a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 40 bytes.
/// </exception>
[Obsolete ("Use BitmapInfoHeader(ByteVector,int)")]
public BitmapInfoHeader (ByteVector data) : this (data, 0)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="BitmapInfoHeader" /> by reading the raw structure
/// from a specified position in a <see cref="ByteVector" />
/// object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <param name="offset">
/// A <see cref="int" /> value specifying the index in
/// <paramref name="data"/> at which the structure begins.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="offset" /> is less than zero.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 16 bytes at
/// <paramref name="offset" />.
/// </exception>
public BitmapInfoHeader (ByteVector data, int offset)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (offset + 40 > data.Count)
throw new CorruptFileException ("Expected 40 bytes.");
if (offset < 0)
throw new ArgumentOutOfRangeException (nameof (offset));
HeaderSize = data.Mid (offset + 0, 4).ToUInt (false);
width = data.Mid (offset + 4, 4).ToUInt (false);
height = data.Mid (offset + 8, 4).ToUInt (false);
Planes = data.Mid (offset + 12, 2).ToUShort (false);
BitCount = data.Mid (offset + 14, 2).ToUShort (false);
CompressionId = data.Mid (offset + 16, 4);
ImageSize = data.Mid (offset + 20, 4).ToUInt (false);
XPixelsPerMeter = data.Mid (offset + 24, 4).ToUInt (false);
YPixelsPerMeter = data.Mid (offset + 28, 4).ToUInt (false);
ColorsUsed = data.Mid (offset + 32, 4).ToUInt (false);
ImportantColors = data.Mid (offset + 36, 4).ToUInt (false);
}
#endregion
#region Public Properties
/// <summary>
/// Gets the size of the structure in bytes.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the number of
/// bytes in the structure.
/// </value>
public uint HeaderSize { get; private set; }
/// <summary>
/// Gets the number of planes in the image.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value containing the number of
/// planes.
/// </value>
public ushort Planes { get; private set; }
/// <summary>
/// Gets the number of bits per pixel.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value containing the number of
/// bits per pixel, equivalent to the log base 2 of the
/// maximum number of colors.
/// </value>
public ushort BitCount { get; private set; }
/// <summary>
/// Gets the compression ID for image.
/// </summary>
/// <value>
/// A four-byte <see cref="ByteVector" /> object containing
/// the ID of the compression system (codec) used by the
/// image.
/// </value>
public ByteVector CompressionId { get; private set; }
/// <summary>
/// Gets the size of the image in bytes.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the number of
/// bytes in the image.
/// </value>
public uint ImageSize { get; private set; }
/// <summary>
/// Gets the horizontal resolution of the target device.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the number of
/// pixels-per-meter in the hoizontal direction for the
/// target device.
/// </value>
public uint XPixelsPerMeter { get; private set; }
/// <summary>
/// Gets the vertical resolution of the target device.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the number of
/// pixels-per-meter in the vertical direction for the
/// target device.
/// </value>
public uint YPixelsPerMeter { get; private set; }
/// <summary>
/// Gets the number of colors in the image.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the number of
/// colors.
/// </value>
public uint ColorsUsed { get; private set; }
/// <summary>
/// Gets the number of colors important in displaying the
/// image.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the number of
/// important colors.
/// </value>
public uint ImportantColors { get; private set; }
#endregion
#region IVideoCodec
/// <summary>
/// Gets the width of the video represented by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing the width of the
/// video represented by the current instance.
/// </value>
public int VideoWidth {
get { return (int)width; }
}
/// <summary>
/// Gets the height of the video represented by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing the height of the
/// video represented by the current instance.
/// </value>
public int VideoHeight {
get { return (int)height; }
}
/// <summary>
/// Gets the types of media represented by the current
/// instance.
/// </summary>
/// <value>
/// Always <see cref="MediaTypes.Video" />.
/// </value>
public MediaTypes MediaTypes {
get { return MediaTypes.Video; }
}
/// <summary>
/// Gets the duration of the media represented by the current
/// instance.
/// </summary>
/// <value>
/// Always <see cref="TimeSpan.Zero" />.
/// </value>
public TimeSpan Duration {
get { return TimeSpan.Zero; }
}
/// <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 {
string id = CompressionId.ToString (StringType.UTF8).ToUpper (CultureInfo.InvariantCulture);
switch (id) {
case "AEMI":
return "Array VideoONE MPEG1-I capture";
case "ALPH":
return "Ziracom Video";
case "AMPG":
return "Array VideoONE capture/compression";
case "ANIM":
return "Intel RDX";
case "AP41":
return "Microsoft Corporation Video";
case "AUR2":
return "AuraVision Aura 2 codec";
case "AURA":
return "AuraVision Aura 1 codec";
case "AUVX":
return "USH GmbH AUVX video codec";
case "BT20":
return "Brooktree MediaStream codec";
case "BTCV":
return "Brooktree composite video codec";
case "CC12":
return "Intel YUV12 codec";
case "CDVC":
return "Canopus DV codec";
case "CGDI":
return "Microsoft CamCorder in Office 97 (screen capture codec)";
case "CHAM":
return "Winnov Caviara Champagne";
case "CM10":
return "CyberLink Corporation MediaShow 1.0";
case "CPLA":
return "Weitek 4:2:0 YUV planar";
case "CT10":
return "CyberLink Corporation TalkingShow 1.0";
case "CVID":
return "Cinepak by SuperMac";
case "CWLT":
return "Microsoft Corporation Video";
case "CYUV":
return "Creative Labs YUV";
case "DIV3":
case "MP43":
return "Microsoft MPEG-4 Version 3 Video";
case "DIV4":
return "Microsoft Corporation Video";
case "DIVX":
return "DivX Video";
case "DJPG":
return "Broadway 101 Motion JPEG codec";
case "DP16":
return "YUV411 with DPCM 6-bit compression";
case "DP18":
return "YUV411 with DPCM 8-bit compression";
case "DP26":
return "YUV422 with DPCM 6-bit compression";
case "DP28":
return "YUV422 with DPCM 8-bit compression";
case "DP96":
return "YVU9 with DPCM 6-bit compression";
case "DP98":
return "YVU9 with DPCM 8-bit compression";
case "DP9L":
return "YVU9 with DPCM 6-bit compression and thinned-out";
case "DUCK":
return "The Duck Corporation TrueMotion 1.0";
case "DV25":
return "SMPTE 314M 25Mb/s compressed";
case "DV50":
return "SMPTE 314M 50Mb/s compressed";
case "DVE2":
return "DVE-2 videoconferencing codec";
case "DVH1":
return "DVC Pro HD";
case "DVHD":
return "DV data as defined in Part 3 of the Specification of Consumer-use Digital VCRs";
case "DVNM":
return "Matsushita Electric Industrial Co., Ltd. Video";
case "DVSD":
return "DV data as defined in Part 2 of the Specification of Consumer-use Digital VCRs";
case "DVSL":
return "DV data as defined in Part 6 of Specification of Consumer-use Digital VCRs";
case "DVX1":
return "Lucent DVX1000SP video decoder.";
case "DVX2":
return "Lucent DVX2000S video decoder";
case "DVX3":
return "Lucent DVX3000S video decoder";
case "DXTC":
return "DirectX texture compression";
case "DX50":
return "DivX Version 5 Video";
case "EMWC":
return "EverAd Marquee WMA codec";
case "ETV1":
case "ETV2":
case "ETVC":
return "eTreppid video codec";
case "FLJP":
return "Field-encoded motion JPEG with LSI bitstream format";
case "FRWA":
return "Softlab-Nsk Ltd. Forward alpha";
case "FRWD":
return "Softlab-Nsk Ltd. Forward JPEG";
case "FRWT":
return "Softlab-Nsk Ltd. Forward JPEG+alpha";
case "FVF1":
return "Iterated Systems, Inc. Fractal video frame";
case "FXT1":
return "3dfx Interactive, Inc. Video";
case "GWLT":
return "Microsoft Corporation Video";
case "H260":
case "H261":
case "H262":
case "H263":
case "H264":
case "H265":
case "H266":
case "H267":
case "H268":
case "H269":
return "Intel " + CompressionId.ToString (StringType.UTF8) + " Conferencing codec";
case "I263":
return "Intel I263";
case "I420":
return "Intel Indeo 4 codec";
case "IAN":
return "Intel RDX";
case "ICLB":
return "InSoft, Inc. CellB videoconferencing codec";
case "IFO9":
return "Intel intermediate YUV9";
case "ILVC":
return "Intel layered Video";
case "ILVR":
return "ITU-T's H.263+ compression standard";
case "IMAC":
return "Intel hardware motion compensation";
case "IPDV":
return "IEEE 1394 digital video control and capture board format";
case "IRAW":
return "Intel YUV uncompressed";
case "ISME":
return "Intel's next-generation video codec";
case "IUYV":
return "UYVY interlaced (even, then odd lines)";
case "IV30":
case "IV31":
case "IV32":
case "IV33":
case "IV34":
case "IV35":
case "IV36":
case "IV37":
case "IV38":
case "IV39":
return "Intel Indeo Video Version 3";
case "IV40":
case "IV41":
case "IV42":
case "IV43":
case "IV44":
case "IV45":
case "IV46":
case "IV47":
case "IV48":
case "IV49":
return "Intel Indeo Video Version 4";
case "IV50":
return "Intel Indeo Video Version 5";
case "IY41":
return "LEAD Technologies, Inc. Y41P interlaced (even, then odd lines)";
case "IYU1":
return "IEEE 1394 Digital Camera 1.04 Specification: mode 2, 12-bit YUV (4:1:1)";
case "IYU2":
return "IEEE 1394 Digital Camera 1.04 Specification: mode 2, 24 bit YUV (4:4:4)";
case "JPEG":
return "Microsoft Corporation Still image JPEG DIB.";
case "LEAD":
return "LEAD Technologies, Inc. Proprietary MCMP compression";
case "LIA1":
return "Liafail";
case "LJPG":
return "LEAD Technologies, Inc. Lossless JPEG compression";
case "LSV0":
return "Infinop Inc. Video";
case "LSVC":
return "Infinop Lightning Strike constant bit rate video codec";
case "LSVW":
return "Infinop Lightning Strike multiple bit rate video codec";
case "M101":
return "Matrox Electronic Systems, Ltd. Uncompressed field-based YUY2";
case "M4S2":
return "Microsoft ISO MPEG-4 video V1.1";
case "MJPG":
return "Motion JPEG";
case "MMES":
return "Matrox MPEG-2 elementary video stream";
case "MMIF":
return "Matrox MPEG-2 elementary I-frame-only video stream";
case "MP2A":
return "Media Excel Inc. MPEG-2 audio";
case "MP2T":
return "Media Excel Inc. MPEG-2 transport";
case "MP2V":
return "Media Excel Inc. MPEG-2 video";
case "MP42":
return "Microsoft MPEG-4 video codec V2";
case "MP4A":
return "Media Excel Inc. MPEG-4 audio";
case "MP4S":
return "Microsoft ISO MPEG-4 video V1.0";
case "MP4T":
return "Media Excel Inc. MPEG-4 transport";
case "MP4V":
return "Media Excel Inc. MPEG-4 video";
case "MPEG":
return "Chromatic Research, Inc. MPEG-1 video, I frame";
case "MPG4":
return "Microsoft MPEG-4 Version 1 Video";
case "MRCA":
return "FAST Multimedia AG Mrcodec";
case "MRLE":
return "Microsoft Run length encoding";
case "MSS1":
return "Microsoft screen codec V1";
case "MSV1":
return "Microsoft video codec V1";
case "MSVC":
return "Microsoft Video 1";
case "MV10":
case "MV11":
case "MV12":
case "MV99":
case "MVC1":
case "MVC2":
case "MVC9":
return "Nokia MVC video codec";
case "NTN1":
return "Nogatech video compression 1";
case "NY12":
return "Nogatech YUV 12 format";
case "NYUV":
return "Nogatech YUV 422 format";
case "PCL2":
return "Pinnacle RL video codec";
case "PCLE":
return "Pinnacle Studio 400 video codec";
case "PHMO":
return "IBM Corporation Photomotion";
case "QPEG":
return "Q-Team QPEG 1.1 format video codec";
case "RGBT":
return "Computer Concepts Ltd. 32-bit support";
case "RIVA":
return "NVIDIA Corporation Swizzled texture format";
case "RLND":
return "Roland Corporation Video";
case "RT21":
return "Intel Indeo 2.1";
case "RVX":
return "Intel RDX";
case "S263":
return "Sorenson Vision H.263";
case "SCCD":
return "Luminositi SoftCam codec";
case "SDCC":
return "Sun Digital Camera codec";
case "SFMC":
return "Crystal Net SFM codec";
case "SMSC":
case "SMSD":
return "Radius Proprietary";
case "SPLC":
return "Splash Studios ACM audio codec";
case "SQZ2":
return "Microsoft VXtreme video codec V2";
case "STVA":
return "ST CMOS Imager Data (Bayer)";
case "STVB":
return "ST CMOS Imager Data (Nudged Bayer)";
case "STVC":
return "ST CMOS Imager Data (Bunched)";
case "SV10":
return "Sorenson Video R1";
case "SV3M":
return "Sorenson SV3 module decoder";
case "TLMS":
case "TLST":
return "TeraLogic motion intraframe codec";
case "TM20":
return "The Duck Corporation TrueMotion 2.0";
case "TMIC":
return "TeraLogic motion intraframe codec";
case "TMOT":
return "TrueMotion video compression algorithm";
case "TR20":
return "The Duck Corporation TrueMotion RT 2.0";
case "ULTI":
return "IBM Corporation Ultimotion";
case "UYVP":
return "Evans & Sutherland YCbCr 4:2:2 extended precision, 10 bits per component (U0Y0V0Y1)";
case "V261":
return "Lucent VX3000S video codec";
case "V422":
return "VITEC Multimedia 24-bit YUV 4:2:2 format (CCIR 601)";
case "V655":
return "VITEC Multimedia 16-bit YUV 4:2:2 format";
case "VCR1":
return "ATI VCR 1.0";
case "VCWV":
return "VideoCon wavelet";
case "VDCT":
return "VITEC Multimedia Video Maker Pro DIB";
case "VIDS":
return "VITEC Multimedia YUV 4:2:2 CCIR 601 for v422";
case "VGPX":
return "Alaris VGPixel video";
case "VIVO":
return "Vivo H.263 video codec";
case "VIXL":
return "miro Computer Products AG";
case "VJPG":
return "Video Communication Systems - A JPEG-based compression scheme for RGB bitmaps";
case "VLV1":
return "VideoLogic Systems VLCAP.DRV";
case "VQC1":
return "ViewQuest Technologies Inc. 0x31435156";
case "VQC2":
return "ViewQuest Technologies Inc. 0x32435156";
case "VQJP":
return "ViewQuest Technologies Inc. VQ630 dual-mode digital camera";
case "VQS4":
return "ViewQuest Technologies Inc. VQ110 digital video camera";
case "VX1K":
return "Lucent VX1000S video codec";
case "VX2K":
return "Lucent VX2000S video codec";
case "VXSP":
return "Lucent VX1000SP video codec9";
case "WBVC":
return "Winbond Electronics Corporation W9960";
case "WINX":
return "Winnov, Inc. Video";
case "WJPG":
return "Winbond motion JPEG bitstream format";
case "WMV1":
return "Microsoft Windows Media Video Version 7";
case "WMV2":
return "Microsoft Windows Media Video Version 8";
case "WMV3":
return "Microsoft Windows Media Video Version 9";
case "WNV1":
case "WPY2":
return "Winnov, Inc. Video";
case "WZCD":
return "CORE Co. Ltd. iScan";
case "WZDC":
return "CORE Co. Ltd. iSnap";
case "XJPG":
return "Xirlink JPEG-like compressor";
case "XLV0":
return "XL video decoder";
case "XVID":
return "XviD Video";
case "YC12":
return "Intel YUV12 Video";
case "YCCK":
return "Uncompressed YCbCr Video with key data";
case "YU92":
return "Intel YUV Video";
case "YUV8":
return "Winnov Caviar YUV8 Video";
case "YUV9":
return "Intel YUV Video";
case "YUYP":
return "Evans & Sutherland YCbCr 4:2:2 extended precision, 10 bits per component Video";
case "YUYV":
return "Canopus YUYV Compressor Video";
case "ZPEG":
return "Metheus Corporation Video Zipper";
case "ZPG1":
case "ZPG2":
case "ZPG3":
case "ZPG4":
return "VoDeo Solutions Video";
default:
return string.Format (
CultureInfo.InvariantCulture,
"Unknown Image ({0})",
CompressionId);
}
}
}
#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)(HeaderSize ^ width ^ height ^ Planes ^
BitCount ^ CompressionId.ToUInt () ^
ImageSize ^ XPixelsPerMeter ^
YPixelsPerMeter ^ ColorsUsed ^
ImportantColors);
}
}
/// <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 BitmapInfoHeader))
return false;
return Equals ((BitmapInfoHeader)other);
}
/// <summary>
/// Checks whether or not the current instance is equal to
/// another instance of <see cref="BitmapInfoHeader" />.
/// </summary>
/// <param name="other">
/// A <see cref="BitmapInfoHeader" /> 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 (BitmapInfoHeader other)
{
return HeaderSize == other.HeaderSize && width == other.width &&
height == other.height && Planes == other.Planes &&
BitCount == other.BitCount &&
CompressionId == other.CompressionId &&
ImageSize == other.ImageSize &&
XPixelsPerMeter == other.XPixelsPerMeter &&
YPixelsPerMeter == other.YPixelsPerMeter &&
ColorsUsed == other.ColorsUsed &&
ImportantColors == other.ImportantColors;
}
/// <summary>
/// Gets whether or not two instances of <see
/// cref="WaveFormatEx" /> are equal to eachother.
/// </summary>
/// <param name="first">
/// A <see cref="BitmapInfoHeader" /> object to compare.
/// </param>
/// <param name="second">
/// A <see cref="BitmapInfoHeader" /> 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 == (BitmapInfoHeader first, BitmapInfoHeader second)
{
return first.Equals (second);
}
/// <summary>
/// Gets whether or not two instances of <see
/// cref="BitmapInfoHeader" /> differ.
/// </summary>
/// <param name="first">
/// A <see cref="BitmapInfoHeader" /> object to compare.
/// </param>
/// <param name="second">
/// A <see cref="BitmapInfoHeader" /> 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 != (BitmapInfoHeader first, BitmapInfoHeader second)
{
return !first.Equals (second);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 47ec323b1e494beffa5994f0535c0f1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+384
View File
@@ -0,0 +1,384 @@
//
// DivXTag.cs: Provide support for reading and writing DivX tags.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Original Source:
// TagLib.Id3v1.Tag
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This class extends <see cref="Tag" /> to provide support for
/// reading and writing tags stored in the DivX format.
/// </summary>
public class DivXTag : Tag
{
#region Private Fields
/// <summary>
/// Contains the title.
/// </summary>
string title;
/// <summary>
/// Contains the semicolon separated performers.
/// </summary>
string artist;
/// <summary>
/// Contains the 4 digit year.
/// </summary>
string year;
/// <summary>
/// Contains a comment on track.
/// </summary>
string comment;
/// <summary>
/// Contains the genre index.
/// </summary>
string genre;
/// <summary>
/// Contains the extra 6 bytes at the end of the tag.
/// </summary>
ByteVector extra_data;
#endregion
#region Public Static Fields
/// <summary>
/// The size of a DivX tag.
/// </summary>
public const uint Size = 128;
/// <summary>
/// The identifier used to recognize a DivX tags.
/// </summary>
/// <value>
/// "DIVXTAG"
/// </value>
public static readonly ReadOnlyByteVector FileIdentifier = "DIVXTAG";
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DivXTag" /> with no contents.
/// </summary>
public DivXTag ()
{
Clear ();
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DivXTag" /> by reading the contents from a
/// specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="File" /> object containing the file from
/// which the contents of the new instance is to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the tag.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="position" /> is less than zero or greater
/// than the size of the file.
/// </exception>
/// <exception cref="CorruptFileException">
/// The file does not contain the file identifier at the
/// correct offset from the given position.
/// </exception>
public DivXTag (File file, long position)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
file.Mode = TagLib.File.AccessMode.Read;
if (position < 0 ||
position > file.Length - Size)
throw new ArgumentOutOfRangeException (nameof (position));
file.Seek (position);
// read the tag -- always 128 bytes
ByteVector data = file.ReadBlock ((int)Size);
// some initial sanity checking
if (!data.EndsWith (FileIdentifier))
throw new CorruptFileException ("DivX tag data does not end with identifier.");
Parse (data);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DivXTag" /> by reading the contents raw tag data
/// stored in a specified <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector"/> containing a raw DivX tag to
/// read into the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// The file does not contain the file identifier at the
/// correct offset from the given position.
/// </exception>
public DivXTag (ByteVector data)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (data.Count < Size)
throw new CorruptFileException ("DivX tag data is less than 128 bytes long.");
if (!data.EndsWith (FileIdentifier))
throw new CorruptFileException ("DivX tag data does not end with identifier.");
Parse (data);
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw DivX tag.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered tag.
/// </returns>
public ByteVector Render ()
{
var data = new ByteVector {
ByteVector.FromString (title, StringType.Latin1).Resize (32, 0x20),
ByteVector.FromString (artist, StringType.Latin1).Resize (28, 0x20),
ByteVector.FromString (year, StringType.Latin1).Resize (4, 0x20),
ByteVector.FromString (comment, StringType.Latin1).Resize (48, 0x20),
ByteVector.FromString (genre, StringType.Latin1).Resize (3, 0x20),
extra_data,
FileIdentifier
};
return data;
}
#endregion
#region Private Methods
/// <summary>
/// Populates the current instance by parsing the contents of
/// a raw DivX tag.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the
/// starting with an DivX tag.
/// </param>
void Parse (ByteVector data)
{
title = data.ToString (StringType.Latin1, 0, 32).Trim ();
artist = data.ToString (StringType.Latin1, 32, 28).Trim ();
year = data.ToString (StringType.Latin1, 60, 4).Trim ();
comment = data.ToString (StringType.Latin1, 64, 48).Trim ();
genre = data.ToString (StringType.Latin1, 112, 3).Trim ();
extra_data = data.Mid (115, 6);
}
#endregion
#region TagLib.Tag
/// <summary>
/// Gets the tag types contained in the current instance.
/// </summary>
/// <value>
/// Always <see cref="TagTypes.Id3v1" />.
/// </value>
public override TagTypes TagTypes {
get { return TagTypes.DivX; }
}
/// <summary>
/// Gets and sets the title for the media described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the title for
/// the media described by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
/// <remarks>
/// When stored on disk, only the first 32 bytes of the
/// Latin-1 encoded value will be stored. This may result in
/// lost data.
/// </remarks>
public override string Title {
get {
return string.IsNullOrEmpty (title) ? null : title;
}
set {
title = value != null ? value.Trim () : string.Empty;
}
}
/// <summary>
/// Gets and sets the performers or artists who performed in
/// the media described by the current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the performers or
/// artists who performed in the media described by the
/// current instance or an empty array if no value is
/// present.
/// </value>
/// <remarks>
/// When stored on disk, only the first 28 bytes of the
/// Latin-1 encoded value will be stored, minus a byte for
/// each additionial performer (i.e. two performers will only
/// have 27 bytes and three performers will only have 26
/// bytes).This may result in lost data.
/// </remarks>
public override string[] Performers {
get {
return string.IsNullOrEmpty (artist) ? new string[0] : artist.Split (';');
}
set {
artist = value != null ? string.Join (";", value) : string.Empty;
}
}
/// <summary>
/// Gets and sets a user comment on the media represented by
/// the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing user comments
/// on the media represented by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
/// <remarks>
/// When stored on disk, only the first 48 bytes of the
/// Latin-1 encoded value will be stored. This may result in
/// lost data.
/// </remarks>
public override string Comment {
get {
return string.IsNullOrEmpty (comment) ? null : comment;
}
set {
comment = value != null ? value.Trim () : string.Empty;
}
}
/// <summary>
/// Gets and sets the genres of the media represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the genres of the
/// media represented by the current instance or an empty
/// array if no value is present.
/// </value>
/// <remarks>
/// Only first genre will be stored and only if it is an
/// exact match for a value appearing in <see
/// cref="TagLib.Genres.Video" />. All other values will
/// result in the property being cleared.
/// </remarks>
public override string[] Genres {
get {
string genre_name = TagLib.Genres.IndexToVideo (genre);
return (genre_name != null) ? new[] { genre_name } : new string[0];
}
set {
genre = (value != null && value.Length > 0) ?
TagLib.Genres.VideoToIndex (value[0].Trim ()).ToString (CultureInfo.InvariantCulture)
: string.Empty;
}
}
/// <summary>
/// Gets and sets the year that the media represented by the
/// current instance was recorded.
/// </summary>
/// <value>
/// A <see cref="uint" /> containing the year that the media
/// represented by the current instance was created or zero
/// if no value is present.
/// </value>
/// <remarks>
/// Only values between 1 and 9999 will be stored, all other
/// values will result in the property being zeroed.
/// </remarks>
public override uint Year {
get {
return uint.TryParse (year, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? value : 0;
}
set {
year = (value > 0 && value < 10000) ? value.ToString (CultureInfo.InvariantCulture) : string.Empty;
}
}
/// <summary>
/// Clears the values stored in the current instance.
/// </summary>
public override void Clear ()
{
title = artist = genre = year = comment = string.Empty;
extra_data = new ByteVector (6);
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 111ed0c7de1644627a867e56300d9623
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+611
View File
@@ -0,0 +1,611 @@
//
// File.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This class extends <see cref="TagLib.File" /> to provide
/// support for reading and writing tags and properties for files
/// using the RIFF file format such as AVI and Wave files.
/// </summary>
[SupportedMimeType ("taglib/avi", "avi")]
[SupportedMimeType ("taglib/wav", "wav")]
[SupportedMimeType ("taglib/divx", "divx")]
[SupportedMimeType ("video/avi")]
[SupportedMimeType ("video/msvideo")]
[SupportedMimeType ("video/x-msvideo")]
[SupportedMimeType ("image/avi")]
[SupportedMimeType ("application/x-troff-msvideo")]
[SupportedMimeType ("audio/avi")]
[SupportedMimeType ("audio/wav")]
[SupportedMimeType ("audio/wave")]
[SupportedMimeType ("audio/x-wav")]
public class File : TagLib.File
{
#region Private Fields
/// <summary>
/// Contains all the tags of the file.
/// </summary>
readonly CombinedTag tag = new CombinedTag ();
/// <summary>
/// Contains the INFO tag.
/// </summary>
InfoTag info_tag;
/// <summary>
/// Contains the MovieID tag.
/// </summary>
MovieIdTag mid_tag;
/// <summary>
/// Contains the DivX tag.
/// </summary>
DivXTag divx_tag;
/// <summary>
/// Contains the Id3v2 tag.
/// </summary>
Id3v2.Tag id32_tag;
/// <summary>
/// Contains the media properties.
/// </summary>
Properties properties;
#endregion
#region Public Static Fields
/// <summary>
/// The identifier used to recognize a RIFF files.
/// </summary>
/// <value>
/// "RIFF"
/// </value>
public static readonly ReadOnlyByteVector FileIdentifier = "RIFF";
#endregion
#region Public 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)
: this (new LocalFileAbstraction (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) : this (path, ReadStyle.Average)
{
}
/// <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)
{
Mode = AccessMode.Read;
try {
Read (true, propertiesStyle, out var riff_size, out var tag_start, out var tag_end);
} finally {
Mode = AccessMode.Closed;
}
TagTypesOnDisk = TagTypes;
GetTag (TagTypes.Id3v2, true);
GetTag (TagTypes.RiffInfo, true);
GetTag (TagTypes.MovieId, true);
GetTag (TagTypes.DivX, true);
}
/// <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)
: this (abstraction, ReadStyle.Average)
{ }
#endregion
#region Public Properties
/// <summary>
/// Gets a abstract representation of all tags stored in the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="TagLib.Tag" /> object representing all tags
/// stored in the current instance.
/// </value>
public override Tag Tag {
get { return tag; }
}
/// <summary>
/// Gets the media properties of the file represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="TagLib.Properties" /> object containing the
/// media properties of the file represented by the current
/// instance.
/// </value>
public override Properties Properties {
get { return properties; }
}
#endregion
#region Public Methods
/// <summary>
/// Saves the changes made in the current instance to the
/// file it represents.
/// </summary>
public override void Save ()
{
// Boilerplate
PreSave ();
Mode = AccessMode.Write;
try {
ByteVector data = new ByteVector ();
// Enclose the Id3v2 tag in an "id3 " item and
// embed it as the first tag.
if (id32_tag != null) {
ByteVector tag_data = id32_tag.Render ();
if (tag_data.Count > 10) {
if (tag_data.Count % 2 == 1)
tag_data.Add (0);
data.Add ("id3 ");
data.Add (ByteVector.FromUInt ((uint)tag_data.Count, false));
data.Add (tag_data);
}
}
// Embed "INFO" as the second tag.
if (info_tag != null)
data.Add (info_tag.RenderEnclosed ());
// Embed "MID " as the third tag.
if (mid_tag != null)
data.Add (mid_tag.RenderEnclosed ());
// Embed the DivX tag in "IDVX and embed it as
// the fourth tag.
if (divx_tag != null && !divx_tag.IsEmpty) {
ByteVector tag_data = divx_tag.Render ();
data.Add ("IDVX");
data.Add (ByteVector.FromUInt ((uint)tag_data.Count, false));
data.Add (tag_data);
}
Read (false, ReadStyle.None, out var riff_size, out var tag_start, out var tag_end);
// If tagging info cannot be found, place it at
// the end of the file.
if (tag_start < 12 || tag_end < tag_start)
tag_start = tag_end = Length;
int length = (int)(tag_end - tag_start);
// If the tag isn't at the end of the file,
// try appending using padding to improve
// write time now or for subsequent writes.
if (tag_end != Length) {
int padding_size = length - data.Count - 8;
if (padding_size < 0)
padding_size = 1024;
data.Add ("JUNK");
data.Add (ByteVector.FromUInt ((uint)padding_size, false));
data.Add (new ByteVector (padding_size));
}
// Insert the tagging data.
Insert (data, tag_start, length);
// If the data size changed, and the tagging
// data is within the RIFF portion of the file,
// update the riff size.
if (data.Count - length != 0 && tag_start <= riff_size)
Insert (ByteVector.FromUInt ((uint)(riff_size + data.Count - length), false), 4, 4);
// Update the tag types.
TagTypesOnDisk = TagTypes;
} finally {
Mode = AccessMode.Closed;
}
}
/// <summary>
/// Removes a set of tag types from the current instance.
/// </summary>
/// <param name="types">
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
/// containing tag types to be removed from the file.
/// </param>
/// <remarks>
/// In order to remove all tags from a file, pass <see
/// cref="TagTypes.AllTags" /> as <paramref name="types" />.
/// </remarks>
public override void RemoveTags (TagTypes types)
{
if ((types & TagTypes.Id3v2) != TagTypes.None)
id32_tag = null;
if ((types & TagTypes.RiffInfo) != TagTypes.None)
info_tag = null;
if ((types & TagTypes.MovieId) != TagTypes.None)
mid_tag = null;
if ((types & TagTypes.DivX) != TagTypes.None)
divx_tag = null;
tag.SetTags (id32_tag, info_tag, mid_tag, divx_tag);
}
/// <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>
public override Tag GetTag (TagTypes type, bool create)
{
Tag tag = null;
switch (type) {
case TagTypes.Id3v2:
if (id32_tag == null && create) {
id32_tag = new Id3v2.Tag ();
id32_tag.Version = 4;
id32_tag.Flags |= Id3v2.HeaderFlags.FooterPresent;
this.tag.CopyTo (id32_tag, true);
}
tag = id32_tag;
break;
case TagTypes.RiffInfo:
if (info_tag == null && create) {
info_tag = new InfoTag ();
this.tag.CopyTo (info_tag, true);
}
tag = info_tag;
break;
case TagTypes.MovieId:
if (mid_tag == null && create) {
mid_tag = new MovieIdTag ();
this.tag.CopyTo (mid_tag, true);
}
tag = mid_tag;
break;
case TagTypes.DivX:
if (divx_tag == null && create) {
divx_tag = new DivXTag ();
this.tag.CopyTo (divx_tag, true);
}
tag = divx_tag;
break;
}
this.tag.SetTags (id32_tag, info_tag, mid_tag, divx_tag);
return tag;
}
#endregion
#region Private Methods
/// <summary>
/// Reads the contents of the current instance determining
/// the size of the riff data, the area the tagging is in,
/// and optionally reading in the tags and media properties.
/// </summary>
/// <param name="read_tags">
/// If <see langword="true" />, any tags found will be read
/// into the current instance.
/// </param>
/// <param name="style">
/// A <see cref="ReadStyle"/> value specifying how the media
/// data is to be read into the current instance.
/// </param>
/// <param name="riff_size">
/// A <see cref="uint"/> value reference to be filled with
/// the size of the RIFF data as read from the file.
/// </param>
/// <param name="tag_start">
/// A <see cref="long" /> value reference to be filled with
/// the absolute seek position at which the tagging data
/// starts.
/// </param>
/// <param name="tag_end">
/// A <see cref="long" /> value reference to be filled with
/// the absolute seek position at which the tagging data
/// ends.
/// </param>
/// <exception cref="CorruptFileException">
/// The file does not begin with <see cref="FileIdentifier"
/// />.
/// </exception>
void Read (bool read_tags, ReadStyle style, out uint riff_size, out long tag_start, out long tag_end)
{
Seek (0);
if (ReadBlock (4) != FileIdentifier)
throw new CorruptFileException ("File does not begin with RIFF identifier");
riff_size = ReadBlock (4).ToUInt (false);
ByteVector stream_format = ReadBlock (4);
tag_start = -1;
tag_end = -1;
long position = 12;
long length = Length;
uint size = 0;
TimeSpan duration = TimeSpan.Zero;
ICodec[] codecs = new ICodec[0];
// Read until there are less than 8 bytes to read.
do {
bool tag_found = false;
// Check if the current position is an odd number and increment it so it is even
// This is done when the previous chunk size was an odd number.
// If this is not done, the chunk being read after the odd chunk will not be read.
if (position > 12 && (position & 1) != 0)
position++;
Seek (position);
string fourcc = ReadBlock (4).ToString (StringType.UTF8);
size = ReadBlock (4).ToUInt (false);
switch (fourcc) {
// "fmt " is used by Wave files to hold the
// WaveFormatEx structure.
case "fmt ":
if (style == ReadStyle.None || stream_format != "WAVE")
break;
Seek (position + 8);
codecs = new ICodec[] {
new WaveFormatEx (ReadBlock (18), 0)
};
break;
// "data" contains the audio data for wave
// files. It's contents represent the invariant
// portion of the file and is used to determine
// the duration of a file. It should always
// appear after "fmt ".
case "data":
if (stream_format != "WAVE")
break;
InvariantStartPosition = position;
InvariantEndPosition = position + size;
if (style == ReadStyle.None ||
codecs.Length != 1 ||
!(codecs[0] is WaveFormatEx))
break;
duration += TimeSpan.FromSeconds (size / (double)((WaveFormatEx)codecs[0]).AverageBytesPerSecond);
break;
// Lists are used to store a variety of data
// collections. Read the type and act on it.
case "LIST": {
switch (ReadBlock (4).ToString (StringType.UTF8)) {
// "hdlr" is used by AVI files to hold
// a media header and BitmapInfoHeader
// and WaveFormatEx structures.
case "hdrl":
if (style == ReadStyle.None || stream_format != "AVI ")
continue;
var header_list = new AviHeaderList (this, position + 12, (int)(size - 4));
duration = header_list.Header.Duration;
codecs = header_list.Codecs;
break;
// "INFO" is a tagging format handled by
// the InfoTag class.
case "INFO":
if (read_tags && info_tag == null)
info_tag = new InfoTag (this, position + 12, (int)(size - 4));
tag_found = true;
break;
// "MID " is a tagging format handled by
// the MovieIdTag class.
case "MID ":
if (read_tags && mid_tag == null)
mid_tag = new MovieIdTag (this, position + 12, (int)(size - 4));
tag_found = true;
break;
// "movi" contains the media data for
// and AVI and its contents represent
// the invariant portion of the file.
case "movi":
if (stream_format != "AVI ")
break;
InvariantStartPosition = position;
InvariantEndPosition = position + size;
break;
}
break;
}
// "ID32" is a custom box for this format that
// contains an ID3v2 tag.
// "ID3 " and "id3 " have become standard (de facto)
case "id3 ":
case "ID3 ":
case "ID32":
if (read_tags && id32_tag == null)
id32_tag = new Id3v2.Tag (this, position + 8, style);
tag_found = true;
break;
// "IDVX" is used by DivX and holds an ID3v1-
// style tag.
case "IDVX":
if (read_tags && divx_tag == null)
divx_tag = new DivXTag (this, position + 8);
tag_found = true;
break;
// "JUNK" is a padding element that could be
// associated with tag data.
case "JUNK":
if (tag_end == position)
tag_end = position + 8 + size;
break;
}
// Determine the region of the file that
// contains tags.
if (tag_found) {
if (tag_start == -1) {
tag_start = position;
tag_end = position + 8 + size;
} else if (tag_end == position) {
tag_end = position + 8 + size;
}
}
// Move to the next item.
} while ((position += 8L + size) + 8 < length);
// If we're reading properties, and one were found,
// throw an exception. Otherwise, create the Properties
// object.
if (style != ReadStyle.None) {
if (codecs.Length == 0)
throw new UnsupportedFormatException ("Unsupported RIFF type.");
properties = new Properties (duration, codecs);
}
// If we're reading tags, update the combined tag.
if (read_tags)
tag.SetTags (id32_tag, info_tag, mid_tag, divx_tag);
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 63abf712dfcf1342c880fca7e562a560
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+392
View File
@@ -0,0 +1,392 @@
//
// InfoTag.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This class extends <see cref="ListTag" /> to provide support for
/// reading and writing standard INFO tags.
/// </summary>
public class InfoTag : ListTag
{
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="InfoTag" /> with no contents.
/// </summary>
public InfoTag ()
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="InfoTag" /> by reading the contents of a raw
/// RIFF list stored in a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector"/> containing a raw RIFF list to
/// read into the new instance.
/// </param>
public InfoTag (ByteVector data) : base (data)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="InfoTag" /> by reading the contents of a raw RIFF
/// list from a specified position in a <see
/// cref="TagLib.File"/>.
/// </summary>
/// <param name="file">
/// A <see cref="TagLib.File" /> object containing the file
/// from which the contents of the new instance is to be
/// read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the list.
/// </param>
/// <param name="length">
/// A <see cref="int" /> value specifying the number of bytes
/// to read.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="position" /> is less than zero or greater
/// than the size of the file.
/// </exception>
public InfoTag (TagLib.File file, long position, int length)
: base (file, position, length)
{
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance enclosed in a "INFO" item.
/// </summary>
/// <returns>
/// A <see cref="ByteVector"/> object containing the rendered
/// version of the current instance.
/// </returns>
public override ByteVector RenderEnclosed ()
{
return RenderEnclosed ("INFO");
}
#endregion
#region TagLib.Tag
/// <summary>
/// Gets the tag types contained in the current instance.
/// </summary>
/// <value>
/// Always <see cref="TagTypes.RiffInfo" />.
/// </value>
public override TagTypes TagTypes {
get { return TagTypes.RiffInfo; }
}
/// <summary>
/// Gets and sets the title for the media described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the title for
/// the media described by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "INAM" item.
/// </remarks>
public override string Title {
get {
foreach (string s in GetValuesAsStrings ("INAM"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("INAM", value); }
}
/// <summary>
/// Gets and sets a short description of the media.
/// For a music, this could be the comment that the artist
/// made of its artwork. For a video, this should be a
/// short summary of the story/plot, but a spoiler. This
/// should give the impression of what to expect in the
/// media.
/// </summary>
/// <value>
/// A <see cref="string" /> containing the subtitle
/// the media represented by the current instance
/// or an empty array if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "ISBJ" item.
/// </remarks>
public override string Description {
get {
foreach (string s in GetValuesAsStrings ("ISBJ"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("ISBJ", value); }
}
/// <summary>
/// Gets and sets the performers or artists who performed in
/// the media described by the current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the performers or
/// artists who performed in the media described by the
/// current instance or an empty array if no value is
/// present.
/// </value>
/// <remarks>
/// This property is implemented using the "ISTR" item.
/// </remarks>
public override string[] Performers {
get { return GetValuesAsStrings ("ISTR"); }
set { SetValue ("ISTR", value); }
}
/// <summary>
/// Gets and sets the band or artist who is credited in the
/// creation of the entire album or collection containing the
/// media described by the current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the band or artist
/// who is credited in the creation of the entire album or
/// collection containing the media described by the current
/// instance or an empty array if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "IART" item.
/// </remarks>
public override string[] AlbumArtists {
get { return GetValuesAsStrings ("IART"); }
set { SetValue ("IART", value); }
}
/// <summary>
/// Gets and sets the composers of the media represented by
/// the current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the composers of the
/// media represented by the current instance or an empty
/// array if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "IWRI" item.
/// </remarks>
public override string[] Composers {
get { return GetValuesAsStrings ("IWRI"); }
set { SetValue ("IWRI", value); }
}
/// <summary>
/// Gets and sets the album of the media represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the album of
/// the media represented by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the non-standard
/// "DIRC" (Directory) item.
/// </remarks>
public override string Album {
get {
foreach (string s in GetValuesAsStrings ("DIRC"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("DIRC", value); }
}
/// <summary>
/// Gets and sets the conductor or director of the media
/// represented by the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the conductor
/// or director of the media represented by the current
/// instance or <see langword="null" /> if no value present.
/// </value>
/// <remarks>
/// This property is implemented using the "ICNM"
/// (Cinematographer) non-standard item.
/// </remarks>
public override string Conductor {
get {
foreach (string s in GetValuesAsStrings ("ICNM"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("ICNM", value); }
}
/// <summary>
/// Gets and sets a user comment on the media represented by
/// the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing user comments
/// on the media represented by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "ICMT" item.
/// </remarks>
public override string Comment {
get {
foreach (string s in GetValuesAsStrings ("ICMT"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("ICMT", value); }
}
/// <summary>
/// Gets and sets the genres of the media represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the genres of the
/// media represented by the current instance or an empty
/// array if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "IGNR" item.
/// </remarks>
public override string[] Genres {
get { return GetValuesAsStrings ("IGNR"); }
set { SetValue ("IGNR", value); }
}
/// <summary>
/// Gets and sets the year that the media represented by the
/// current instance was recorded.
/// </summary>
/// <value>
/// A <see cref="uint" /> containing the year that the media
/// represented by the current instance was created or zero
/// if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "ICRD" item.
/// </remarks>
public override uint Year {
get { return GetValueAsUInt ("ICRD"); }
set { SetValue ("ICRD", value); }
}
/// <summary>
/// Gets and sets the position of the media represented by
/// the current instance in its containing album.
/// </summary>
/// <value>
/// A <see cref="uint" /> containing the position of the
/// media represented by the current instance in its
/// containing album or zero if not specified.
/// </value>
/// <remarks>
/// This property is implemented using the "IPRT" item.
/// </remarks>
public override uint Track {
get { return GetValueAsUInt ("IPRT"); }
set { SetValue ("IPRT", value); }
}
/// <summary>
/// Gets and sets the number of tracks in the album
/// containing the media represented by the current instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> containing the number of tracks in
/// the album containing the media represented by the current
/// instance or zero if not specified.
/// </value>
/// <remarks>
/// This property is implemented using the "IFRM" item.
/// </remarks>
public override uint TrackCount {
get { return GetValueAsUInt ("IFRM"); }
set { SetValue ("IFRM", value); }
}
/// <summary>
/// Gets and sets the copyright information for the media
/// represented by the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the copyright
/// information for the media represented by the current
/// instance or <see langword="null" /> if no value present.
/// </value>
/// <remarks>
/// This property is implemented using the "ICOP" item.
/// </remarks>
public override string Copyright {
get {
foreach (string s in GetValuesAsStrings ("ICOP"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("ICOP", value); }
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9a2882ad50b55517b84bed378740164a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+622
View File
@@ -0,0 +1,622 @@
//
// List.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace TagLib.Riff
{
/// <summary>
/// This class extends <see
/// cref="T:System.Collections.Generic.Dictionary`2" /> to provide
/// support for reading and writing RIFF lists.
/// </summary>
[Serializable]
[ComVisible (false)]
public class List : Dictionary<ByteVector, ByteVectorCollection>
{
#region Private Fields
/// <summary>
/// Contains the <see cref="StringType"/> value used for parsing
/// and rendering the contents of this list.
/// </summary>
StringType string_type = StringType.UTF8;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="List" /> with no contents.
/// </summary>
public List ()
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="List" /> by reading the contents of a raw RIFF
/// list stored in a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector"/> containing a raw RIFF list to
/// read into the new instance.
/// </param>
public List (ByteVector data)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
Parse (data);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="List" /> by reading the contents of a raw RIFF list
/// from a specified position in a <see cref="TagLib.File"/>.
/// </summary>
/// <param name="file">
/// A <see cref="TagLib.File" /> object containing the file
/// from which the contents of the new instance is to be
/// read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the list.
/// </param>
/// <param name="length">
/// A <see cref="int" /> value specifying the number of bytes
/// to read.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="position" /> is less than zero or greater
/// than the size of the file.
/// </exception>
public List (TagLib.File file, long position, int length)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
if (length < 0)
throw new ArgumentOutOfRangeException (nameof (length));
if (position < 0 || position > file.Length - length)
throw new ArgumentOutOfRangeException (nameof (position));
file.Seek (position);
Parse (file.ReadBlock (length));
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="List" /> from a specified serialization info and
/// streaming context.
/// </summary>
/// <param name="info">
/// A <see cref="SerializationInfo" /> object containing the
/// serialized data to be used for the new instance.
/// </param>
/// <param name="context">
/// A <see cref="StreamingContext" /> object containing the
/// streaming context information for the new instance.
/// </param>
/// <remarks>
/// This constructor is implemented because <see
/// cref="List" /> implements the <see cref="ISerializable"
/// /> interface.
/// </remarks>
protected List (SerializationInfo info, StreamingContext context)
: base (info, context)
{
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets the <see cref="StringType"/> value used for parsing
/// and rendering the contents of this list.
/// </summary>
/// <remarks>
/// The value must be StringType.Latin1 or StringType.UTF8.
/// </remarks>
public StringType StringType {
get => string_type;
set {
if (value != StringType.Latin1 && value != StringType.UTF8)
throw new ArgumentException ("Must be Latin1 or UTF8.", nameof(value));
string_type = value;
}
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw RIFF list.
/// </summary>
/// <returns>
/// A <see cref="ByteVector"/> object containing the rendered
/// version of the current instance.
/// </returns>
public ByteVector Render ()
{
ByteVector data = new ByteVector ();
foreach (ByteVector id in Keys)
foreach (ByteVector value in this[id]) {
if (value.Count == 0)
continue;
data.Add (id);
data.Add (ByteVector.FromUInt (
(uint)value.Count, false));
data.Add (value);
if (value.Count % 2 == 1)
data.Add (0);
}
return data;
}
/// <summary>
/// Renders the current instance enclosed in an item with a
/// specified ID.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector"/> object containing the ID of
/// the item to enclose the current instance in.
/// </param>
/// <returns>
/// A <see cref="ByteVector"/> object containing the rendered
/// version of the current instance.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public ByteVector RenderEnclosed (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException (
"ID must be 4 bytes long.", nameof (id));
ByteVector data = Render ();
if (data.Count <= 8)
return new ByteVector ();
var header = new ByteVector ("LIST") {
ByteVector.FromUInt ((uint)(data.Count + 4), false),
id
};
data.Insert (0, header);
return data;
}
/// <summary>
/// Gets the values for a specified item in the current
/// instance as a <see cref="ByteVectorCollection" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="ByteVectorCollection" /> object containing
/// the values of the specified item.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public ByteVectorCollection GetValues (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
return TryGetValue (id, out var value) ? value : new ByteVectorCollection ();
}
/// <summary>
/// Gets the values for a specified item in the current
/// instance as a <see cref="T:string[]" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="T:string[]" /> containing the values of the
/// specified item.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public string[] GetValuesAsStrings (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
ByteVectorCollection values = GetValues (id);
string[] result = new string[values.Count];
for (int i = 0; i < result.Length; i++) {
ByteVector data = values[i];
if (data == null) {
result[i] = string.Empty;
continue;
}
int length = data.Count;
while (length > 0 && data[length - 1] == 0)
length--;
result[i] = data.ToString (StringType, 0, length);
}
return result;
}
/// <summary>
/// Gets the values for a specified item in the current
/// instance as a <see cref="StringCollection" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="StringCollection" /> object containing the
/// values of the specified item.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
[Obsolete ("Use GetValuesAsStrings(ByteVector)")]
public StringCollection GetValuesAsStringCollection (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
return new StringCollection (GetValuesAsStrings (id));
}
/// <summary>
/// Gets the value for a specified item in the current
/// instance as a <see cref="uint"/>.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="uint" /> value containing the first value
/// with the specified ID that could be converted to an
/// integer, or zero if none could be found.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public uint GetValueAsUInt (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
foreach (string text in GetValuesAsStrings (id)) {
if (uint.TryParse (text, out var value))
return value;
}
return 0;
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see
/// cref="T:System.Collections.Generic.IEnumerable`1" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="values">
/// A <see cref="T:System.Collections.Generic.IEnumerable`1"
/// /> containing the <see cref="ByteVector"/> objects to
/// store in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, IEnumerable<ByteVector> values)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
if (values == null)
RemoveValue (id);
else if (ContainsKey (id))
this[id] = new ByteVectorCollection (values);
else
Add (id, new ByteVectorCollection (values));
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see cref="T:ByteVector[]"
/// />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="values">
/// A <see cref="T:ByteVector[]" /> containing the values to
/// store in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, params ByteVector[] values)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
if (values == null || values.Length == 0)
RemoveValue (id);
else
SetValue (id, values as IEnumerable<ByteVector>);
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the value of a <see cref="uint"/>.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="value">
/// A <see cref="uint" /> value to store in the specified
/// item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, uint value)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
if (value == 0)
RemoveValue (id);
else
SetValue (id, value.ToString (CultureInfo.InvariantCulture));
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see
/// cref="T:System.Collections.Generic.IEnumerable`1" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="values">
/// A <see cref="T:System.Collections.Generic.IEnumerable`1"
/// /> containing the <see cref="string"/> objects to store
/// in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, IEnumerable<string> values)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
if (values == null) {
RemoveValue (id);
return;
}
var l = new ByteVectorCollection ();
foreach (string value in values) {
if (string.IsNullOrEmpty (value))
continue;
ByteVector data = ByteVector.FromString (value, StringType);
data.Add (0);
l.Add (data);
}
if (l.Count == 0)
RemoveValue (id);
else
SetValue (id, l);
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see cref="T:string[]" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="values">
/// A <see cref="T:string[]" /> containing the values to store
/// in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, params string[] values)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
if (values == null || values.Length == 0)
RemoveValue (id);
else
SetValue (id, values as IEnumerable<string>);
}
/// <summary>
/// Removes the item with the specified ID from the current
/// instance.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector"/> object containing the ID of
/// the item to remove from the current instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void RemoveValue (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
if (ContainsKey (id))
Remove (id);
}
#endregion
#region Private Methods
/// <summary>
/// Populates the current instance by reading in the contents
/// of a raw RIFF list stored in a <see cref="ByteVector" />
/// object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector"/> containing a raw RIFF list to
/// read into the current instance.
/// </param>
void Parse (ByteVector data)
{
int offset = 0;
while (offset + 8 < data.Count) {
ByteVector id = data.Mid (offset, 4);
int length = (int)data.Mid (offset + 4, 4).ToUInt (false);
if (!ContainsKey (id))
Add (id, new ByteVectorCollection ());
this[id].Add (data.Mid (offset + 8, length));
if (length % 2 == 1)
length++;
offset += 8 + length;
}
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 797e2ca39be1491eca498676dbe168bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+503
View File
@@ -0,0 +1,503 @@
//
// ListTag.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This abstract class extends <see cref="Tag" /> to provide support
/// for reading and writing tags stored in the RIFF list format.
/// </summary>
public abstract class ListTag : Tag
{
#region Private Fields
/// <summary>
/// Contains the <see cref="List" /> object.
/// </summary>
readonly List fields;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ListTag" /> with no contents.
/// </summary>
protected ListTag ()
{
fields = new List ();
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="MovieIdTag" /> using a specified RIFF list.
/// </summary>
/// <param name="fields">
/// A <see cref="List"/> object to use in the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="fields" /> is <see langword="null" />.
/// </exception>
protected ListTag (List fields)
{
if (fields == null)
throw new ArgumentNullException (nameof (fields));
this.fields = fields;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ListTag" /> by reading the contents of a raw
/// RIFF list stored in a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector"/> containing a raw RIFF list to
/// read into the new instance.
/// </param>
protected ListTag (ByteVector data)
{
fields = new List (data);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ListTag" /> by reading the contents of a raw RIFF
/// list from a specified position in a <see
/// cref="TagLib.File" />.
/// </summary>
/// <param name="file">
/// A <see cref="TagLib.File" /> object containing the file
/// from which the contents of the new instance is to be
/// read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the list.
/// </param>
/// <param name="length">
/// A <see cref="int" /> value specifying the number of bytes
/// to read.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="position" /> is less than zero or greater
/// than the size of the file.
/// </exception>
protected ListTag (TagLib.File file, long position, int length)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
if (length < 0)
throw new ArgumentOutOfRangeException (nameof (length));
if (position < 0 || position > file.Length - length)
throw new ArgumentOutOfRangeException (nameof (position));
fields = new List (file, position, length);
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets the <see cref="StringType"/> value used for parsing
/// and rendering the contents of this tag.
/// </summary>
/// <remarks>
/// The value must be StringType.Latin1 or StringType.UTF8.
/// </remarks>
public StringType StringType {
get => fields.StringType;
set => fields.StringType = value;
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance enclosed in the appropriate
/// item.
/// </summary>
/// <returns>
/// A <see cref="ByteVector"/> object containing the rendered
/// version of the current instance.
/// </returns>
public abstract ByteVector RenderEnclosed ();
/// <summary>
/// Renders the current instance enclosed in an item with a
/// specified ID.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector"/> object containing the ID of
/// the item to enclose the current instance in.
/// </param>
/// <returns>
/// A <see cref="ByteVector"/> object containing the rendered
/// version of the current instance.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
protected ByteVector RenderEnclosed (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
return fields.RenderEnclosed (id);
}
/// <summary>
/// Renders the current instance as a raw RIFF list.
/// </summary>
/// <returns>
/// A <see cref="ByteVector"/> object containing the rendered
/// version of the current instance.
/// </returns>
public ByteVector Render ()
{
return fields.Render ();
}
/// <summary>
/// Gets the values for a specified item in the current
/// instance as a <see cref="ByteVectorCollection" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="ByteVectorCollection" /> object containing
/// the values of the specified item.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public ByteVectorCollection GetValues (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
return fields.GetValues (id);
}
/// <summary>
/// Gets the values for a specified item in the current
/// instance as a <see cref="T:string[]" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="T:string[]" /> containing the values of the
/// specified item.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public string[] GetValuesAsStrings (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
return fields.GetValuesAsStrings (id);
}
/// <summary>
/// Gets the values for a specified item in the current
/// instance as a <see cref="StringCollection" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="StringCollection" /> object containing the
/// values of the specified item.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
[Obsolete ("Use GetValuesAsStrings(ByteVector)")]
public StringCollection GetValuesAsStringCollection (ByteVector id)
{
return new StringCollection (
fields.GetValuesAsStrings (id));
}
/// <summary>
/// Gets the value for a specified item in the current
/// instance as a <see cref="uint"/>.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <returns>
/// A <see cref="uint" /> value containing the first value
/// with the specified ID that could be converted to an
/// integer, or zero if none could be found.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public uint GetValueAsUInt (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
return fields.GetValueAsUInt (id);
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see cref="T:ByteVector[]"
/// />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="value">
/// A <see cref="T:ByteVector[]" /> containing the values to
/// store in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, params ByteVector[] value)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
fields.SetValue (id, value);
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see
/// cref="ByteVectorCollection" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="value">
/// A <see cref="ByteVectorCollection" /> object containing
/// the values to store in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, ByteVectorCollection value)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
fields.SetValue (id, value);
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the value of a <see cref="uint"/>.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="value">
/// A <see cref="uint" /> value to store in the specified
/// item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, uint value)
{
fields.SetValue (id, value);
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see
/// cref="StringCollection" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="value">
/// A <see cref="StringCollection" /> object containing the
/// values to store in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
[Obsolete ("Use SetValue(ByteVector,string[])")]
public void SetValue (ByteVector id, StringCollection value)
{
fields.SetValue (id, value);
}
/// <summary>
/// Sets the value for a specified item in the current
/// instance to the contents of a <see cref="T:string[]" />.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector" /> object containing the ID of
/// the item to set.
/// </param>
/// <param name="value">
/// A <see cref="T:string[]" /> containing the values to store
/// in the specified item.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void SetValue (ByteVector id, params string[] value)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
fields.SetValue (id, value);
}
/// <summary>
/// Removes the item with the specified ID from the current
/// instance.
/// </summary>
/// <param name="id">
/// A <see cref="ByteVector"/> object containing the ID of
/// the item to remove from the current instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="id" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="id" /> isn't exactly four bytes long.
/// </exception>
public void RemoveValue (ByteVector id)
{
if (id == null)
throw new ArgumentNullException (nameof (id));
if (id.Count != 4)
throw new ArgumentException ("ID must be 4 bytes long.", nameof (id));
fields.RemoveValue (id);
}
#endregion
#region TagLib.Tag
/// <summary>
/// Gets whether or not the current instance is empty.
/// </summary>
/// <value>
/// <see langword="true" /> if the current instance does not
/// any values. Otherwise <see langword="false" />.
/// </value>
public override bool IsEmpty {
get { return fields.Count == 0; }
}
/// <summary>
/// Clears the values stored in the current instance.
/// </summary>
public override void Clear ()
{
fields.Clear ();
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 506a556e0ad0577a69229948e87b11f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+238
View File
@@ -0,0 +1,238 @@
//
// MovieIdTag.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This class extends <see cref="ListTag" /> to provide support for
/// reading and writing MovieID tags.
/// </summary>
public class MovieIdTag : ListTag
{
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="MovieIdTag" /> with no contents.
/// </summary>
public MovieIdTag ()
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="MovieIdTag" /> by reading the contents of a raw
/// RIFF list stored in a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector"/> containing a raw RIFF list to
/// read into the new instance.
/// </param>
public MovieIdTag (ByteVector data) : base (data)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="MovieIdTag" /> by reading the contents of a raw
/// RIFF list from a specified position in a <see
/// cref="TagLib.File"/>.
/// </summary>
/// <param name="file">
/// A <see cref="TagLib.File" /> object containing the file
/// from which the contents of the new instance is to be
/// read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the list.
/// </param>
/// <param name="length">
/// A <see cref="int" /> value specifying the number of bytes
/// to read.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="position" /> is less than zero or greater
/// than the size of the file.
/// </exception>
public MovieIdTag (TagLib.File file, long position, int length)
: base (file, position, length)
{
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance enclosed in a "MID " item.
/// </summary>
/// <returns>
/// A <see cref="ByteVector"/> object containing the rendered
/// version of the current instance.
/// </returns>
public override ByteVector RenderEnclosed ()
{
return RenderEnclosed ("MID ");
}
#endregion
#region TagLib.Tag
/// <summary>
/// Gets the tag types contained in the current instance.
/// </summary>
/// <value>
/// Always <see cref="TagTypes.MovieId" />.
/// </value>
public override TagTypes TagTypes {
get { return TagTypes.MovieId; }
}
/// <summary>
/// Gets and sets the title for the media described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the title for
/// the media described by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "TITL" item.
/// </remarks>
public override string Title {
get {
foreach (string s in GetValuesAsStrings ("TITL"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("TITL", value); }
}
/// <summary>
/// Gets and sets the performers or artists who performed in
/// the media described by the current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the performers or
/// artists who performed in the media described by the
/// current instance or an empty array if no value is
/// present.
/// </value>
/// <remarks>
/// This property is implemented using the "IART" item.
/// </remarks>
public override string[] Performers {
get { return GetValuesAsStrings ("IART"); }
set { SetValue ("IART", value); }
}
/// <summary>
/// Gets and sets a user comment on the media represented by
/// the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing user comments
/// on the media represented by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "COMM" item.
/// </remarks>
public override string Comment {
get {
foreach (string s in GetValuesAsStrings ("COMM"))
if (!string.IsNullOrEmpty (s))
return s;
return null;
}
set { SetValue ("COMM", value); }
}
/// <summary>
/// Gets and sets the genres of the media represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> containing the genres of the
/// media represented by the current instance or an empty
/// array if no value is present.
/// </value>
/// <remarks>
/// This property is implemented using the "GENR" item.
/// </remarks>
public override string[] Genres {
get { return GetValuesAsStrings ("GENR"); }
set { SetValue ("GENR", value); }
}
/// <summary>
/// Gets and sets the position of the media represented by
/// the current instance in its containing album.
/// </summary>
/// <value>
/// A <see cref="uint" /> containing the position of the
/// media represented by the current instance in its
/// containing album or zero if not specified.
/// </value>
/// <remarks>
/// This property is implemented using the "PRT1" item.
/// </remarks>
public override uint Track {
get { return GetValueAsUInt ("PRT1"); }
set { SetValue ("PRT1", value); }
}
/// <summary>
/// Gets and sets the number of tracks in the album
/// containing the media represented by the current instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> containing the number of tracks in
/// the album containing the media represented by the current
/// instance or zero if not specified.
/// </value>
/// <remarks>
/// This property is implemented using the "PRT2" item.
/// </remarks>
public override uint TrackCount {
get { return GetValueAsUInt ("PRT2"); }
set { SetValue ("PRT2", value); }
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7e35f343dc0482b3cae5ee678fa31b48
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+746
View File
@@ -0,0 +1,746 @@
//
// WaveFormatEx.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2007 Brian Nickel
//
// 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.Riff
{
/// <summary>
/// This structure provides a representation of a Microsoft
/// WaveFormatEx structure.
/// </summary>
public struct WaveFormatEx : IAudioCodec, ILosslessAudioCodec
{
#region Private Fields
/// <summary>
/// Contains the number of audio channels.
/// </summary>
readonly ushort channels;
/// <summary>
/// Contains the number of samples per second.
/// </summary>
readonly uint samples_per_second;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="WaveFormatEx" /> by reading the raw structure from
/// the beginning of a <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 16 bytes.
/// </exception>
[Obsolete ("Use WaveFormatEx(ByteVector,int)")]
public WaveFormatEx (ByteVector data)
: this (data, 0)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="WaveFormatEx" /> by reading the raw structure from
/// a specified position in a <see cref="ByteVector" />
/// object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data structure.
/// </param>
/// <param name="offset">
/// A <see cref="int" /> value specifying the index in
/// <paramref name="data"/> at which the structure begins.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="offset" /> is less than zero.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> contains less than 16 bytes at
/// <paramref name="offset" />.
/// </exception>
public WaveFormatEx (ByteVector data, int offset)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (offset < 0)
throw new ArgumentOutOfRangeException (nameof (offset));
if (offset + 16 > data.Count)
throw new CorruptFileException ("Expected 16 bytes.");
FormatTag = data.Mid (offset, 2).ToUShort (false);
channels = data.Mid (offset + 2, 2).ToUShort (false);
samples_per_second = data.Mid (offset + 4, 4).ToUInt (false);
AverageBytesPerSecond = data.Mid (offset + 8, 4).ToUInt (false);
BitsPerSample = data.Mid (offset + 14, 2).ToUShort (false);
}
#endregion
#region Public Properties
/// <summary>
/// Gets the format tag of the audio described by the
/// current instance.
/// </summary>
/// <returns>
/// A <see cref="ushort" /> value containing the format tag
/// of the audio.
/// </returns>
/// <remarks>
/// Format tags indicate the codec of the audio contained in
/// the file and are contained in a Microsoft registry. For
/// a description of the format, use <see cref="Description"
/// />.
/// </remarks>
public ushort FormatTag { get; private set; }
/// <summary>
/// Gets the average bytes per second of the audio described
/// by the current instance.
/// </summary>
/// <returns>
/// A <see cref="ushort" /> value containing the average
/// bytes per second of the audio.
/// </returns>
public uint AverageBytesPerSecond { get; private set; }
/// <summary>
/// Gets the bits per sample of the audio described by the
/// current instance.
/// </summary>
/// <returns>
/// A <see cref="ushort" /> value containing the bits per
/// sample of the audio.
/// </returns>
public ushort BitsPerSample { get; private set; }
#endregion
#region ILosslessAudioCodec
int ILosslessAudioCodec.BitsPerSample {
get { return BitsPerSample; }
}
#endregion
#region IAudioCodec
/// <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)Math.Round (AverageBytesPerSecond * 8d / 1000d);
}
}
/// <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)samples_per_second; }
}
/// <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 channels; }
}
/// <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 the duration of the media represented by the current
/// instance.
/// </summary>
/// <value>
/// Always <see cref="TimeSpan.Zero" />.
/// </value>
public TimeSpan Duration {
get { return TimeSpan.Zero; }
}
/// <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 {
switch (FormatTag) {
case 0x0000:
return "Unknown Wave Format";
case 0x0001:
return "PCM Audio";
case 0x0002:
return "Microsoft Adaptive PCM Audio";
case 0x0003:
return "PCM Audio in IEEE floating-point format";
case 0x0004:
return "Compaq VSELP Audio";
case 0x0005:
return "IBM CVSD Audio";
case 0x0006:
return "Microsoft ALAW Audio";
case 0x0007:
return "Microsoft MULAW Audio";
case 0x0008:
return "Microsoft DTS Audio";
case 0x0009:
return "Microsoft DRM Encrypted Audio";
case 0x000A:
return "Microsoft Speech Audio";
case 0x000B:
return "Microsoft Windows Media RT Voice Audio";
case 0x0010:
return "OKI ADPCM Audio";
case 0x0011:
return "Intel ADPCM Audio";
case 0x0012:
return "VideoLogic ADPCM Audio";
case 0x0013:
return "Sierra ADPCM Audio";
case 0x0014:
return "Antex ADPCM Audio";
case 0x0015:
return "DSP DIGISTD Audio";
case 0x0016:
return "DSP DIGIFIX Audio";
case 0x0017:
return "Dialogic OKI ADPCM Audio";
case 0x0018:
return "Media Vision ADPCM Audio for Jazz 16";
case 0x0019:
return "Hewlett-Packard CU Audio";
case 0x001A:
return "Hewlett-Packard Dynamic Voice Audio";
case 0x0020:
return "Yamaha ADPCM Audio";
case 0x0021:
return "Speech Compression Audio";
case 0x0022:
return "DSP Group True Speech Audio";
case 0x0023:
return "Echo Speech Audio";
case 0x0024:
return "Ahead AF36 Audio";
case 0x0025:
return "Audio Processing Technology Audio";
case 0x0026:
return "Ahead AF10 Audio";
case 0x0027:
return "Aculab Prosody CTI Speech Card Audio";
case 0x0028:
return "Merging Technologies LRC Audio";
case 0x0030:
return "Dolby AC2 Audio";
case 0x0031:
return "Microsoft GSM6.10 Audio";
case 0x0032:
return "Microsoft MSN Audio";
case 0x0033:
return "Antex ADPCME Audio";
case 0x0034:
return "Control Resources VQLPC";
case 0x0035:
return "DSP REAL Audio";
case 0x0036:
return "DSP ADPCM Audio";
case 0x0037:
return "Control Resources CR10 Audio";
case 0x0038:
return "Natural MicroSystems VBXADPCM Audio";
case 0x0039:
return "Roland RDAC Proprietary Audio Format";
case 0x003A:
return "Echo Speech Proprietary Audio Compression Format";
case 0x003B:
return "Rockwell ADPCM Audio";
case 0x003C:
return "Rockwell DIGITALK Audio";
case 0x003D:
return "Xebec Proprietary Audio Compression Format";
case 0x0040:
return "Antex G721 ADPCM Audio";
case 0x0041:
return "Antex G728 CELP Audio";
case 0x0042:
return "Microsoft MSG723 Audio";
case 0x0043:
return "Microsoft MSG723.1 Audio";
case 0x0044:
return "Microsoft MSG729 Audio";
case 0x0045:
return "Microsoft SPG726 Audio";
case 0x0050:
return "Microsoft MPEG Audio";
case 0x0052:
return "InSoft RT24 Audio";
case 0x0053:
return "InSoft PAC Audio";
case 0x0055:
return "ISO/MPEG Layer 3 Audio";
case 0x0059:
return "Lucent G723 Audio";
case 0x0060:
return "Cirrus Logic Audio";
case 0x0061:
return "ESS Technology PCM Audio";
case 0x0062:
return "Voxware Audio";
case 0x0063:
return "Canopus ATRAC Audio";
case 0x0064:
return "APICOM G726 ADPCM Audio";
case 0x0065:
return "APICOM G722 ADPCM Audio";
case 0x0067:
return "Microsoft DSAT Display Audio";
case 0x0069:
return "Voxware Byte Aligned Audio";
case 0x0070:
return "Voxware AC8 Audio";
case 0x0071:
return "Voxware AC10 Audio";
case 0x0072:
return "Voxware AC16 Audio";
case 0x0073:
return "Voxware AC20 Audio";
case 0x0074:
return "Voxware RT24 Audio";
case 0x0075:
return "Voxware RT29 Audio";
case 0x0076:
return "Voxware RT29HW Audio";
case 0x0077:
return "Voxware VR12 Audio";
case 0x0078:
return "Voxware VR18 Audio";
case 0x0079:
return "Voxware TQ40 Audio";
case 0x007A:
return "Voxware SC3 Audio";
case 0x007B:
return "Voxware SC3 Audio";
case 0x0080:
return "SoftSound Audio";
case 0x0081:
return "Voxware TQ60 Audio";
case 0x0082:
return "Microsoft RT24 Audio";
case 0x0083:
return "AT&T G729A Audio";
case 0x0084:
return "Motion Pixels MVI2 Audio";
case 0x0085:
return "Datafusion Systems G726 Audio";
case 0x0086:
return "Datafusion Systems G610 Audio";
case 0x0088:
return "Iterated Systems Audio";
case 0x0089:
return "OnLive! Audio";
case 0x008A:
return "Multitude FT SX20 Audio";
case 0x008B:
return "InfoCom ITS ACM G721 Audio";
case 0x008C:
return "Convedia G729 Audio";
case 0x008D:
return "Congruency Audio";
case 0x0091:
return "Siemens Business Communications 24 Audio";
case 0x0092:
return "Sonic Foundary Dolby AC3 Audio";
case 0x0093:
return "MediaSonic G723 Audio";
case 0x0094:
return "Aculab Prosody CTI Speech Card Audio";
case 0x0097:
return "ZyXEL ADPCM";
case 0x0098:
return "Philips Speech Processing LPCBB Audio";
case 0x0099:
return "Studer Professional PACKED Audio";
case 0x00A0:
return "Malden Electronics Phony Talk Audio";
case 0x00A1:
return "Racal Recorder GSM Audio";
case 0x00A2:
return "Racal Recorder G720.a Audio";
case 0x00A3:
return "Racal G723.1 Audio";
case 0x00A4:
return "Racal Tetra ACELP Audio";
case 0x00B0:
return "NEC AAC Audio";
case 0x0100:
return "Rhetorex ADPCM Audio";
case 0x0101:
return "BeCubed IRAT Audio";
case 0x0111:
return "Vivo G723 Audio";
case 0x0112:
return "Vivo Siren Audio";
case 0x0120:
return "Philips Speach Processing CELP Audio";
case 0x0121:
return "Philips Speach Processing GRUNDIG Audio";
case 0x0123:
return "Digital Equipment Corporation G723 Audio";
case 0x0125:
return "Sanyo LD-ADPCM Audio";
case 0x0130:
return "Sipro Lab ACELPNET Audio";
case 0x0131:
return "Sipro Lab ACELP4800 Audio";
case 0x0132:
return "Sipro Lab ACELP8v3 Audio";
case 0x0133:
return "Sipro Lab G729 Audio";
case 0x0134:
return "Sipro Lab G729A Audio";
case 0x0135:
return "Sipro Lab KELVIN Audio";
case 0x0136:
return "VoiceAge AMR Audio";
case 0x0140:
return "Dictaphone G726 ADPCM Audio";
case 0x0141:
return "Dictaphone CELP68 Audio";
case 0x0142:
return "Dictaphone CELP54 Audio";
case 0x0150:
return "QUALCOMM Pure Voice Audio";
case 0x0151:
return "QUALCOMM Half Rate Audio";
case 0x0155:
return "Ring Zero TUBGSM Audio";
case 0x0160:
return "Microsoft WMA1 Audio";
case 0x0161:
return "Microsoft WMA2 Audio";
case 0x0162:
return "Microsoft Multichannel WMA Audio";
case 0x0163:
return "Microsoft Lossless WMA Audio";
case 0x0170:
return "Unisys NAP ADPCM Audio";
case 0x0171:
return "Unisys NAP ULAW Audio";
case 0x0172:
return "Unisys NAP ALAW Audio";
case 0x0173:
return "Unisys NAP 16K Audio";
case 0X0174:
return "SysCom ACM SYC008 Audio";
case 0x0175:
return "SysCom ACM SYC701 G726L Audio";
case 0x0176:
return "SysCom ACM SYC701 CELP54 Audio";
case 0x0177:
return "SysCom ACM SYC701 CELP68 Audio";
case 0x0178:
return "Knowledge Adventure ADPCM Audio";
case 0x0180:
return "MPEG2 AAC Audio";
case 0x0190:
return "Digital Theater Systems DTS DS Audio";
case 0x1979:
return "Innings ADPCM Audio";
case 0x0200:
return "Creative ADPCM Audio";
case 0x0202:
return "Creative FastSpeech8 Audio";
case 0x0203:
return "Creative FastSpeech10 Audio";
case 0x0210:
return "UHER ADPCM Audio";
case 0x0220:
return "Quarterdeck Audio";
case 0x0230:
return "I-Link VC Audio";
case 0x0240:
return "Aureal RAW SPORT Audio";
case 0x0250:
return "Interactive Prodcuts HSX Audio";
case 0x0251:
return "Interactive Products RPELP Audio";
case 0x0260:
return "Consistens Software CS2 Audio";
case 0x0270:
return "Sony SCX Audio";
case 0x0271:
return "Sony SCY Audio";
case 0x0272:
return "Sony ATRAC3 Audio";
case 0x0273:
return "Sony SPC Audio";
case 0x0280:
return "Telum Audio";
case 0x0281:
return "Telum IA Audio";
case 0x0285:
return "Norcom Voice Systems ADPCM Audio";
case 0x0300:
return "Fujitsu FM TOWNS SND Audio";
case 0x0301:
case 0x0302:
case 0x0303:
case 0x0304:
case 0x0305:
case 0x0306:
case 0x0307:
case 0x0308:
return "Unknown Fujitsu Audio";
case 0x0350:
return "Micronas Semiconductors Development Audio";
case 0x0351:
return "Micronas Semiconductors CELP833 Audio";
case 0x0400:
return "Brooktree Digital Audio";
case 0x0450:
return "QDesign Audio";
case 0x0680:
return "AT&T VME VMPCM Audio";
case 0x0681:
return "AT&T TPC Audio";
case 0x1000:
return "Ing. C. Olivetti & C., S.p.A. GSM Audio";
case 0x1001:
return "Ing. C. Olivetti & C., S.p.A. ADPCM Audio";
case 0x1002:
return "Ing. C. Olivetti & C., S.p.A. CELP Audio";
case 0x1003:
return "Ing. C. Olivetti & C., S.p.A. SBC Audio";
case 0x1004:
return "Ing. C. Olivetti & C., S.p.A. OPR Audio";
case 0x1100:
return "Lernout & Hauspie Audio";
case 0X1101:
return "Lernout & Hauspie CELP Audio";
case 0X1102:
return "Lernout & Hauspie SB8 Audio";
case 0X1103:
return "Lernout & Hauspie SB12 Audio";
case 0X1104:
return "Lernout & Hauspie SB16 Audio";
case 0x1400:
return "Norris Audio";
case 0x1500:
return "AT&T Soundspace Musicompress Audio";
case 0x1971:
return "Sonic Foundry Lossless Audio";
case 0x2000:
return "FAST Multimedia DVM Audio";
case 0x4143:
return "Divio AAC";
case 0x4201:
return "Nokia Adaptive Multirate Audio";
case 0x4243:
return "Divio G726 Audio";
case 0x7000:
return "3Com NBX Audio";
case 0x7A21:
return "Microsoft Adaptive Multirate Audio";
case 0x7A22:
return "Microsoft Adaptive Multirate Audio with silence detection";
case 0xA100:
return "Comverse Infosys G723 1 Audio";
case 0xA101:
return "Comverse Infosys AVQSBC Audio";
case 0xA102:
return "Comverse Infosys OLDSBC Audio";
case 0xA103:
return "Symbol Technology G729A Audio";
case 0xA104:
return "VoiceAge AMR WB Audio";
case 0xA105:
return "Ingenient G726 Audio";
case 0xA106:
return "ISO/MPEG-4 Advanced Audio Coding";
case 0xA107:
return "Encore G726 Audio";
default:
return "Unknown Audio (" + FormatTag + ")";
}
}
}
#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)(FormatTag ^ channels ^
samples_per_second ^
AverageBytesPerSecond ^
BitsPerSample);
}
}
/// <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 WaveFormatEx))
return false;
return Equals ((WaveFormatEx)other);
}
/// <summary>
/// Checks whether or not the current instance is equal to
/// another instance of <see cref="WaveFormatEx" />.
/// </summary>
/// <param name="other">
/// A <see cref="WaveFormatEx" /> 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 (WaveFormatEx other)
{
return FormatTag == other.FormatTag &&
channels == other.channels &&
samples_per_second == other.samples_per_second &&
AverageBytesPerSecond == other.AverageBytesPerSecond &&
BitsPerSample == other.BitsPerSample;
}
/// <summary>
/// Gets whether or not two instances of <see
/// cref="WaveFormatEx" /> are equal to eachother.
/// </summary>
/// <param name="first">
/// A <see cref="WaveFormatEx" /> object to compare.
/// </param>
/// <param name="second">
/// A <see cref="WaveFormatEx" /> 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 == (WaveFormatEx first, WaveFormatEx second)
{
return first.Equals (second);
}
/// <summary>
/// Gets whether or not two instances of <see
/// cref="WaveFormatEx" /> differ.
/// </summary>
/// <param name="first">
/// A <see cref="WaveFormatEx" /> object to compare.
/// </param>
/// <param name="second">
/// A <see cref="WaveFormatEx" /> 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 != (WaveFormatEx first, WaveFormatEx second)
{
return !first.Equals (second);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2e1efda4c5ee8833fbbc1973f815afa3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: