Initial commit
This commit is contained in:
commit
262601edb8
2025 files changed
+218754
No files matched your search
@@ -0,0 +1,486 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for Apple's AIFF
|
||||
// files.
|
||||
//
|
||||
// Author:
|
||||
// Helmut Wahrmann
|
||||
//
|
||||
// Copyright (C) 2009 Helmut Wahrmann
|
||||
//
|
||||
// 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.Aiff
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.File" /> to provide
|
||||
/// support for reading and writing tags and properties for files
|
||||
/// using the AIFF file format.
|
||||
/// </summary>
|
||||
[SupportedMimeType ("taglib/aif", "aif")]
|
||||
[SupportedMimeType ("taglib/aiff", "aiff")]
|
||||
[SupportedMimeType ("audio/x-aiff")]
|
||||
[SupportedMimeType ("audio/aiff")]
|
||||
[SupportedMimeType ("sound/aiff")]
|
||||
[SupportedMimeType ("application/x-aiff")]
|
||||
public class File : TagLib.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the address of the AIFF header block.
|
||||
/// </summary>
|
||||
ByteVector header_block;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Id3v2 tag.
|
||||
/// </summary>
|
||||
Id3v2.Tag tag;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the media properties.
|
||||
/// </summary>
|
||||
Properties properties;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Fields
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF files.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "FORM"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector FileIdentifier = "FORM";
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF Common chunk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "COMM"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector CommIdentifier = "COMM";
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF Sound Data Chunk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "SSND"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector SoundIdentifier = "SSND";
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF ID3 chunk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "ID3 "
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector ID3Identifier = "ID3 ";
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF Form type.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "AIFF"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector AIFFFormType = "AIFF";
|
||||
|
||||
#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 aiff_size, out var tag_start, out var tag_end);
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
|
||||
TagTypesOnDisk = TagTypes;
|
||||
|
||||
GetTag (TagTypes.Id3v2, 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 {
|
||||
var data = new ByteVector ();
|
||||
|
||||
// Add the ID3 chunk and ID32 tag to the vector
|
||||
if (tag != null) {
|
||||
ByteVector tag_data = 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, true));
|
||||
data.Add (tag_data);
|
||||
}
|
||||
}
|
||||
|
||||
Read (false, ReadStyle.None, out var aiff_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 + 8);
|
||||
|
||||
// Insert the tagging data.
|
||||
Insert (data, tag_start, length);
|
||||
|
||||
// If the data size changed update the aiff size.
|
||||
if (data.Count - length != 0 &&
|
||||
tag_start <= aiff_size) {
|
||||
// Depending, if a Tag has been added or removed,
|
||||
// the length needs to be adjusted
|
||||
if (tag == null) {
|
||||
length -= 16;
|
||||
} else {
|
||||
length -= 8;
|
||||
}
|
||||
|
||||
Insert (ByteVector.FromUInt ((uint)(aiff_size + data.Count - length), true), 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 || types == TagTypes.AllTags) {
|
||||
tag = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 id32_tag = null;
|
||||
|
||||
switch (type) {
|
||||
case TagTypes.Id3v2:
|
||||
if (tag == null && create) {
|
||||
tag = new Id3v2.Tag {
|
||||
Version = 2
|
||||
};
|
||||
}
|
||||
|
||||
id32_tag = tag;
|
||||
break;
|
||||
}
|
||||
|
||||
return id32_tag;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Search the file for a chunk whose name is given by
|
||||
/// the chunkName parameter, starting from startPos.
|
||||
/// Note that startPos must be a valid position for a
|
||||
/// chunk, or else finding will fail.
|
||||
/// </summary>
|
||||
/// <param name="chunkName">Name of the chunk to search for</param>
|
||||
/// <param name="startPos">Position for starting the search</param>
|
||||
/// <returns>
|
||||
/// Position of the chunk in the stream, or -1
|
||||
/// if no chunk was found.
|
||||
/// </returns>
|
||||
long FindChunk (ByteVector chunkName, long startPos)
|
||||
{
|
||||
long initialPos = Tell;
|
||||
|
||||
try {
|
||||
// Start at the given position
|
||||
Seek (startPos);
|
||||
|
||||
// While not eof
|
||||
while (Tell < Length) {
|
||||
// Read 4-byte chunk name
|
||||
ByteVector chunkHeader = ReadBlock (4);
|
||||
|
||||
if (chunkHeader == chunkName) {
|
||||
// We found a matching chunk, return the position
|
||||
// of the header start
|
||||
return Tell - 4;
|
||||
} else {
|
||||
// This chunk is not the one we are looking for
|
||||
// Continue the search, seeking over the chunk
|
||||
uint chunkSize = ReadBlock (4).ToUInt ();
|
||||
// Seek forward "chunkSize" bytes
|
||||
Seek (chunkSize, System.IO.SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
|
||||
// We did not find the chunk
|
||||
return -1;
|
||||
} finally {
|
||||
Seek (initialPos);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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="aiff_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 aiff_size, out long tag_start, out long tag_end)
|
||||
{
|
||||
Seek (0);
|
||||
if (ReadBlock (4) != FileIdentifier)
|
||||
throw new CorruptFileException ("File does not begin with AIFF identifier");
|
||||
|
||||
aiff_size = ReadBlock (4).ToUInt (true);
|
||||
tag_start = -1;
|
||||
tag_end = -1;
|
||||
|
||||
// Check formType
|
||||
if (ReadBlock (4) != AIFFFormType)
|
||||
throw new CorruptFileException ("File form type is not AIFF");
|
||||
|
||||
long formBlockChunksPosition = Tell;
|
||||
|
||||
// Get the properties of the file
|
||||
if (header_block == null &&
|
||||
style != ReadStyle.None) {
|
||||
long common_chunk_pos = FindChunk (CommIdentifier, formBlockChunksPosition);
|
||||
|
||||
if (common_chunk_pos == -1) {
|
||||
throw new CorruptFileException ("No Common chunk available in AIFF file.");
|
||||
}
|
||||
|
||||
Seek (common_chunk_pos);
|
||||
header_block = ReadBlock ((int)StreamHeader.Size);
|
||||
|
||||
var header = new StreamHeader (header_block, aiff_size);
|
||||
properties = new Properties (TimeSpan.Zero, header);
|
||||
}
|
||||
|
||||
// Search for the ID3 chunk
|
||||
long id3_chunk_pos = FindChunk (ID3Identifier, formBlockChunksPosition);
|
||||
|
||||
// Search for the sound chunk
|
||||
long sound_chunk_pos = FindChunk (SoundIdentifier, formBlockChunksPosition);
|
||||
|
||||
// Ensure there is a sound chunk for the file to be valid
|
||||
if (sound_chunk_pos == -1) {
|
||||
throw new CorruptFileException ("No Sound chunk available in AIFF file.");
|
||||
}
|
||||
|
||||
// Get the length of the Sound chunk and use this as a start value to look for the ID3 chunk
|
||||
Seek (sound_chunk_pos + 4);
|
||||
|
||||
// Read the id3 chunk
|
||||
if (id3_chunk_pos > -1) {
|
||||
if (read_tags && tag == null) {
|
||||
tag = new Id3v2.Tag (this, id3_chunk_pos + 8, style);
|
||||
}
|
||||
|
||||
// Get the length of the tag out of the ID3 chunk
|
||||
Seek (id3_chunk_pos + 4);
|
||||
uint tag_size = ReadBlock (4).ToUInt (true) + 8;
|
||||
|
||||
tag_start = InvariantStartPosition = id3_chunk_pos;
|
||||
tag_end = InvariantEndPosition = tag_start + tag_size;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c3c2cdcd3206d6c2984e6419139fc01
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// StreamHeader.cs: Provides support for reading Apple's AIFF stream
|
||||
// properties.
|
||||
//
|
||||
// Author:
|
||||
// Helmut Wahrmann
|
||||
//
|
||||
// Copyright (C) 2009 Helmut Wahrmann
|
||||
//
|
||||
// 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.Aiff
|
||||
{
|
||||
/// <summary>
|
||||
/// This struct implements <see cref="IAudioCodec" /> to provide
|
||||
/// support for reading Apple's AIFF stream properties.
|
||||
/// </summary>
|
||||
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of channels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (9,10).
|
||||
/// 1 is monophonic, 2 is stereo, 4 means 4 channels, etc..
|
||||
/// any number of audio channels may be represented
|
||||
/// </remarks>
|
||||
readonly ushort channels;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of sample frames in the Sound Data chunk.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (11-14).
|
||||
/// </remarks>
|
||||
readonly ulong total_frames;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of bits per sample.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (15,16).
|
||||
/// It can be any number from 1 to 32.
|
||||
/// </remarks>
|
||||
readonly ushort bits_per_sample;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the sample rate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (17-26).
|
||||
/// the sample rate at which the sound is to be played back,
|
||||
/// in sample frames per second
|
||||
/// </remarks>
|
||||
readonly ulong sample_rate;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the length of the audio stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is provided by the constructor.
|
||||
/// </remarks>
|
||||
readonly long stream_length;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Fields
|
||||
|
||||
/// <summary>
|
||||
/// The size of an AIFF Common chunk
|
||||
/// </summary>
|
||||
public const uint Size = 26;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF file.
|
||||
/// Altough an AIFF file start with "FORM2, we're interested
|
||||
/// in the Common chunk only, which contains the properties we need.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "COMM"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector FileIdentifier = "COMM";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="StreamHeader" /> for a specified header block and
|
||||
/// stream length.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the stream
|
||||
/// header data.
|
||||
/// </param>
|
||||
/// <param name="streamLength">
|
||||
/// A <see cref="long" /> value containing the length of the
|
||||
/// AIFF Audio stream in bytes.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> does not begin with <see
|
||||
/// cref="FileIdentifier" />
|
||||
/// </exception>
|
||||
public StreamHeader (ByteVector data, long streamLength)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException (nameof (data));
|
||||
|
||||
|
||||
if (!data.StartsWith (FileIdentifier))
|
||||
throw new CorruptFileException ("Data does not begin with identifier.");
|
||||
|
||||
stream_length = streamLength;
|
||||
|
||||
// The first 8 bytes contain the Common chunk identifier "COMM"
|
||||
// And the size of the common chunk, which is always 18
|
||||
channels = data.Mid (8, 2).ToUShort (true);
|
||||
total_frames = data.Mid (10, 4).ToULong (true);
|
||||
bits_per_sample = data.Mid (14, 2).ToUShort (true);
|
||||
sample_rate = (ulong)data.Mid (16, 10).ToExtendedPrecision ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> containing the duration of the
|
||||
/// media represented by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan Duration {
|
||||
get {
|
||||
if (sample_rate <= 0 || total_frames <= 0)
|
||||
return TimeSpan.Zero;
|
||||
|
||||
return TimeSpan.FromSeconds (
|
||||
total_frames /
|
||||
(double)sample_rate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Audio" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes {
|
||||
get { return MediaTypes.Audio; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get { return "AIFF Audio"; }
|
||||
}
|
||||
|
||||
/// <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 {
|
||||
TimeSpan d = Duration;
|
||||
if (d <= TimeSpan.Zero)
|
||||
return 0;
|
||||
|
||||
return (int)((stream_length * 8L) / d.TotalSeconds) / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleRate {
|
||||
get { return (int)sample_rate; }
|
||||
}
|
||||
|
||||
/// <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 number of bits per sample in the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of bits
|
||||
/// per sample in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int BitsPerSample {
|
||||
get { return bits_per_sample; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c36b8cbc292897db7b1633bd3967807b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user