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

+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 32fed777e7f6daacfa1a4e532b30c12e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+13
View File
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace BangerTypes
{
public class Note
{
public float t; // Time
public string a; // Arrow type
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a284c53b4540b5598dc592caa8fe84d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+17
View File
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace BangerTypes
{
public class Rhys
{
public Note[] notes;
public string artist;
public string title;
public int track_time;
public string audio; // Base64 encoded
public string cover_art; // Base64 encoded
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 201ec27a96f795d6f94dabd5b8d453d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+23
View File
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace BangerTypes
{
public class Song
{
public Note[] Notes { get; set; }
public string Title { get; set; }
public string Artist { get; set; }
public string Album { get; set; }
public string Duration { get; set; }
public TimeSpan DurationSpan { get; set; }
public AudioClip Clip { get; set; }
public Sprite CoverArt { get; set; }
public string SongPath { get; set; }
public Color32 AverageColor { get; set; }
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f157c1fad538aaaa38f7d178e7b359a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+13
View File
@@ -0,0 +1,13 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoroutineStarter : MonoBehaviour
{
private static CoroutineStarter instance = new();
public static void StartRoutine(IEnumerator routine)
{
instance.StartCoroutine(routine);
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 448219931c01415039b70f8af79a05bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2c69f559f3da0b59d97db4723910f9e5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+11
View File
@@ -0,0 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum ButtonType
{
UP,
DOWN,
LEFT,
RIGHT
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b6890e1a271ae58dc98e3e3e26f2d442
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ea9f7e8f0b3a66e84858a5b4a3c904f5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+38
View File
@@ -0,0 +1,38 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManager : MonoBehaviour
{
[HideInInspector]
public AudioClip Clip { get; set; }
public AudioSource source;
[Range(0f, 1f)]
public float volume;
[Range(0f, 1f)]
public float pitch;
void Awake()
{
source = GetComponent<AudioSource>();
source.clip = Clip;
}
public void UpdateClip(AudioClip clip)
{
source.clip = clip;
}
public void Play()
{
source.Play();
}
public void Stop()
{
source.Stop();
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61669be1370e61be299d7421ad39b205
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+97
View File
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BassEffect
{
public AudioSource source;
public int range = 128;
public int sensitivity = 9;
public float bassDesensitivity = 0.4f;
public float[] SpectrumData { get; set; }
public float bassThreshhold = 0.1f;
public Queue<float> bassHistory = new(5);
List<float> bassData = new();
// No sensitivity and bass reduction
public float[] UnprocessedSpectrumData { get; set; }
// Raw data from GetSpectrumData
private float[] RawSpectrumData;
public BassEffect(AudioSource source)
{
this.source = source;
SpectrumData = new float[range];
RawSpectrumData = new float[4 * range];
}
public float[] UpdateSpectrumData()
{
source.GetSpectrumData(RawSpectrumData, 0, FFTWindow.Blackman);
float[] res = new float[range];
// Smooth the spectrum data using a moving average
for (int i = 0; i < range; i++)
{
float result = Mathf.Lerp(SpectrumData[i], RawSpectrumData[i], 0.1f);
SpectrumData[i] = result;
if (i < (range / 14))
{
result *= bassDesensitivity;
}
res[i] = sensitivity * result;
}
IsBassOn();
return res;
}
public float[] GetBass()
{
return SpectrumData.Take(3).ToArray();
}
public float GetBassStrength()
{
float[] bass = GetBass();
float sum = bass.Sum() * 5f;
return (float) Math.Pow(sum, 2) / 10f;
}
public bool IsBassOn()
{
float[] bass = GetBass();
float level = bass.Sum() / bass.Length;
bassData.Add(level);
return level > bassThreshhold;
}
public void WriteData()
{
string res = "";
foreach (var bass in bassData)
{
res += bass + ", ";
}
System.IO.File.WriteAllText("/home/thastertyn/bass-data.txt", res);
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 439cd1a6fdb271b12bbba95d1273c881
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+82
View File
@@ -0,0 +1,82 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UIElements;
using UITypes;
public class Game : MonoBehaviour
{
const float DELAY = 0.005f; // 200 TPS
public AudioManager manager;
private MainMenu menu;
private BassEffect effect;
string totalDuration;
bool repeatRoutine = true;
void Awake()
{
menu = GetComponent<MainMenu>();
effect = new(manager.source);
}
public void GameUpdate()
{
float[] specData = effect.UpdateSpectrumData();
float bassStrength = effect.GetBassStrength();
menu.GameElem.UpdateVisualizers(specData, bassStrength);
UpdateTimestamp();
}
IEnumerator GameLoop()
{
while (repeatRoutine)
{
GameUpdate();
yield return new WaitForSeconds(DELAY);
}
}
public void LoadSong(SongEntry song)
{
totalDuration = song.Song.Duration;
manager.source.clip = song.Song.Clip;
menu.GameElem.SetColumnColor(song.Song.AverageColor);
}
void UpdateTimestamp()
{
int totalSeconds = (int)manager.source.time;
int h = totalSeconds / 3600;
int m = (totalSeconds % 3600) / 60;
int s = totalSeconds % 60;
string result = $"{h:D2}:{m:D2}:{s:D2} / {totalDuration}";
menu.GameElem.UpdateSongTime(result);
}
public void EscapeClicked()
{
repeatRoutine = false;
manager.Stop();
menu.Escape();
}
public void Play()
{
manager.Play();
repeatRoutine = true;
StartCoroutine(GameLoop());
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1cb1154a484d1bf18dda4f1c4f16322
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+20
View File
@@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Sound : MonoBehaviour
{
public AudioClip clip;
[Range(0f, 1f)]
public float volume;
[Range(0f, 1f)]
public float pitch;
public string soundName;
[HideInInspector]
public AudioSource source;
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33f413aa8eabb985da07d956df7f198e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7db8be7cfa459fa15990f6ed6fcb6a92
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+110
View File
@@ -0,0 +1,110 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using TagLib;
using System;
using BangerTypes;
using NAudio.Wave;
using UnityEngine.Networking;
namespace MenuAndSongs
{
public class FindSongs
{
public static List<string> Find(string songPath)
{
if (!Directory.Exists(songPath))
Directory.CreateDirectory(songPath);
List<string> ls = Directory
.GetFiles(songPath)
.Where(file => Regex.IsMatch(file, ".*\\.mp3"))
.ToList();
return ls;
}
public static Song ParseRHYS(string rhysPath, Sprite defaultImage)
{
string jsonContent = System.IO.File.ReadAllText(rhysPath);
Rhys rhys = JsonUtility.FromJson<Rhys>(jsonContent);
string title = "<b>" + (rhys.title ?? "Title not found") + "</b>";
string artist = String.IsNullOrEmpty(rhys.artist) ? "Artist not found" : "By: <b>" + rhys.artist + "</b>";
string album = "Album information not available";
TimeSpan duration = TimeSpan.FromSeconds(rhys.track_time);
string formattedTimeSpan = string.Format("{0:D2}:{1:D2}:{2:D2}",
(int)duration.TotalHours,
duration.Minutes,
duration.Seconds);
Sprite coverImage;
if (!string.IsNullOrEmpty(rhys.cover_art))
{
byte[] imageBytes = Convert.FromBase64String(rhys.cover_art);
Texture2D texture = new Texture2D(2, 2);
texture.LoadImage(imageBytes);
coverImage = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
}
else
{
coverImage = defaultImage;
}
var notes = rhys.notes;
Debug.Log("NOTES: ");
Debug.Log(notes);
return new()
{
Title = title,
Artist = artist,
Album = album,
DurationSpan = duration,
Duration = formattedTimeSpan,
CoverArt = coverImage,
Clip = LoadAudioFromBase64(rhys.audio)
};
}
private static AudioClip LoadAudioFromBase64(string base64String)
{
// Decode Base64 String to byte array
byte[] mp3Bytes = Convert.FromBase64String(base64String);
// Create a temporary file path
string tempFilePath = Path.Combine(Application.persistentDataPath, "tempMp3File.mp3");
System.IO.File.WriteAllBytes(tempFilePath, mp3Bytes);
// Load the AudioClip synchronously
AudioClip clip = LoadAudioSync(tempFilePath);
// Optionally delete the temporary file if no longer needed
System.IO.File.Delete(tempFilePath);
return clip;
}
private static AudioClip LoadAudioSync(string filePath)
{
UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip("file://" + filePath, AudioType.MPEG);
var operation = uwr.SendWebRequest();
while (!operation.isDone)
; // Busy wait - not recommended
if (uwr.result == UnityWebRequest.Result.Success)
{
return DownloadHandlerAudioClip.GetContent(uwr);
}
else
{
Debug.LogError("Error loading audio clip: " + uwr.error);
return null;
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 653a02710366ea592b0b57a41d8d165a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+12
View File
@@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MenuAndSongs
{
[CreateAssetMenu(fileName = "SongData", menuName = "Custom/Song Data")]
public class SongData : ScriptableObject
{
public static string songPath;
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87a87ffb34f411f57934067574b91792
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 82dacfd5a3919507382bfb33213d0ae9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 308bd862125e5ae9c95724055c402e8c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+415
View File
@@ -0,0 +1,415 @@
//
// AudioHeader.cs: Provides information about an ADTS AAC audio stream.
//
// Copyright (C) 2009 Patrick Dehne
//
// 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.Aac
{
/// <summary>
/// This structure implements <see cref="IAudioCodec" /> and provides
/// information about an ADTS AAC audio stream.
/// </summary>
public class AudioHeader : IAudioCodec
{
#region Private Static Value Arrays
/// <summary>
/// Contains a sample rate table for ADTS AAC audio.
/// </summary>
static readonly int[] sample_rates = new int[13] {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000, 7350
};
/// <summary>
/// Contains a channel table for ADTS AAC audio.
/// </summary>
static readonly int[] channels = new int[8] {
0, 1, 2, 3, 4, 5, 6, 8
};
#endregion
#region Private Properties
/// <summary>
/// Contains the audio stream length.
/// </summary>
long stream_length;
/// <summary>
/// Contains the audio stream duration.
/// </summary>
TimeSpan duration;
/// <summary>
/// Contains the number of channels in the audio
/// </summary>
readonly int audiochannels;
/// <summary>
/// Contains the bitrate of the audio stream
/// </summary>
readonly int audiobitrate;
/// <summary>
/// Contains the samplerate of the audio stream
/// </summary>
readonly int audiosamplerate;
#endregion
#region Public Fields
/// <summary>
/// An empty and unset header.
/// </summary>
public static readonly AudioHeader Unknown = new AudioHeader ();
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new empty instance of <see
/// cref="AudioHeader" />
/// </summary>
AudioHeader ()
{
stream_length = 0;
duration = TimeSpan.Zero;
audiochannels = 0;
audiobitrate = 0;
audiosamplerate = 0;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="AudioHeader" /> by populating it with specified
/// values.
/// </summary>
/// <param name="channels">
/// A <see cref="int" /> value indicating the number
/// of channels in the audio stream
/// </param>
/// <param name="bitrate">
/// A <see cref="int" /> value indicating the bitrate
/// of the audio stream
/// </param>
/// <param name="samplerate">
/// A <see cref="int" /> value indicating the samplerate
/// of the audio stream
/// </param>
/// <param name="numberofsamples">
/// A <see cref="int" /> value indicating the number
/// of samples in the audio stream
/// </param>
/// <param name="numberofframes">
/// A <see cref="int" /> value indicating the number
/// of frames in the audio stream
/// </param>
AudioHeader (int channels, int bitrate, int samplerate, int numberofsamples, int numberofframes)
{
duration = TimeSpan.Zero;
stream_length = 0;
audiochannels = channels;
audiobitrate = bitrate;
audiosamplerate = samplerate;
}
#endregion
#region Public Properties
/// <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 "ADTS AAC";
}
}
/// <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>
/// A <see cref="TimeSpan" /> containing the duration of the
/// media represented by the current instance.
/// </value>
/// <remarks>
/// If <see cref="SetStreamLength" /> has not been called, this
/// value will not be correct.
/// </remarks>
public TimeSpan Duration {
get {
return duration;
}
}
/// <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 audiobitrate;
}
}
/// <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 audiosamplerate;
}
}
/// <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 audiochannels; }
}
#endregion
#region Public Methods
/// <summary>
/// Sets the length of the audio stream represented by the
/// current instance.
/// </summary>
/// <param name="streamLength">
/// A <see cref="long" /> value specifying the length in
/// bytes of the audio stream represented by the current
/// instance.
/// </param>
/// <remarks>
/// The this value has been set, <see cref="Duration" /> will
/// return an incorrect value.
/// </remarks>
public void SetStreamLength (long streamLength)
{
stream_length = streamLength;
duration = TimeSpan.FromSeconds (stream_length * 8.0 / audiobitrate);
}
#endregion
#region Public Static Methods
/// <summary>
/// Searches for an audio header in a <see cref="TagLib.File"
/// /> starting at a specified position and searching through
/// a specified number of bytes.
/// </summary>
/// <param name="header">
/// A <see cref="AudioHeader" /> object in which the found
/// header will be stored.
/// </param>
/// <param name="file">
/// A <see cref="TagLib.File" /> object to search.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specifying the seek position
/// in <paramref name="file" /> at which to start searching.
/// </param>
/// <param name="length">
/// A <see cref="int" /> value specifying the maximum number
/// of bytes to search before aborting.
/// </param>
/// <returns>
/// A <see cref="bool" /> value indicating whether or not a
/// header was found.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
public static bool Find (out AudioHeader header, TagLib.File file, long position, int length)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
long end = position + length;
header = Unknown;
file.Seek (position);
ByteVector buffer = file.ReadBlock (3);
if (buffer.Count < 3)
return false;
do {
file.Seek (position + 3);
buffer = buffer.Mid (buffer.Count - 3);
buffer.Add (file.ReadBlock (
(int)TagLib.File.BufferSize));
for (int i = 0; i < buffer.Count - 3 &&
(length < 0 || position + i < end); i++)
if (buffer[i] == 0xFF
&& buffer[i + 1] >= 0xF0) // 0xFFF
try {
BitStream bits = new BitStream (buffer.Mid (i, 7).Data);
// 12 bits sync header
bits.ReadInt32 (12);
// 1 bit mpeg 2/4
bits.ReadInt32 (1);
// 2 bits layer
bits.ReadInt32 (2);
// 1 bit protection absent
bits.ReadInt32 (1);
// 2 bits profile object type
bits.ReadInt32 (2);
// 4 bits sampling frequency index
int samplerateindex = bits.ReadInt32 (4);
if (samplerateindex >= sample_rates.Length)
return false;
long samplerate = sample_rates[samplerateindex];
// 1 bit private bit
bits.ReadInt32 (1);
// 3 bits channel configuration
int channelconfigindex = bits.ReadInt32 (3);
if (channelconfigindex >= channels.Length)
return false;
// 4 copyright bits
bits.ReadInt32 (4);
// 13 bits frame length
long framelength = bits.ReadInt32 (13); // double check framelength
if (framelength < 7)
return false;
// 11 bits buffer fullness
bits.ReadInt32 (11);
// 2 bits number of raw data blocks in frame
int numberofframes = bits.ReadInt32 (2) + 1;
long numberofsamples = numberofframes * 1024;
long bitrate = framelength * 8 * samplerate / numberofsamples;
header = new AudioHeader (channels[channelconfigindex],
(int)bitrate,
(int)samplerate,
(int)numberofsamples,
numberofframes);
return true;
} catch (CorruptFileException) {
}
position += TagLib.File.BufferSize;
} while (buffer.Count > 3 && (length < 0 || position < end));
return false;
}
/// <summary>
/// Searches for an audio header in a <see cref="TagLib.File"
/// /> starting at a specified position and searching to the
/// end of the file.
/// </summary>
/// <param name="header">
/// A <see cref="AudioHeader" /> object in which the found
/// header will be stored.
/// </param>
/// <param name="file">
/// A <see cref="TagLib.File" /> object to search.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specifying the seek position
/// in <paramref name="file" /> at which to start searching.
/// </param>
/// <returns>
/// A <see cref="bool" /> value indicating whether or not a
/// header was found.
/// </returns>
/// <remarks>
/// Searching to the end of the file can be very, very slow
/// especially for corrupt or non-MPEG files. It is
/// recommended to use <see
/// cref="M:AudioHeader.Find(AudioHeader,TagLib.File,long,int)" />
/// instead.
/// </remarks>
public static bool Find (out AudioHeader header, TagLib.File file, long position)
{
return Find (out header, file, position, -1);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a70f4e38ac189d2389cf4717f5a1869a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+100
View File
@@ -0,0 +1,100 @@
//
// BitStream.cs: Helper to read bits from a byte array.
//
// Copyright (C) 2009 Patrick Dehne
//
// 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;
using System.Diagnostics;
namespace TagLib.Aac
{
/// <summary>
/// This class is used to help reading arbitary number of bits from
/// a fixed array of bytes
/// </summary>
public class BitStream
{
readonly BitArray bits;
int bitindex;
#region Constructors
/// <summary>
/// Construct a new <see cref="BitStream"/>.
/// </summary>
/// <param name="buffer">
/// A <see cref="T:System.Byte[]"/>, must be 7 bytes long.
/// </param>
public BitStream (byte[] buffer)
{
Debug.Assert (buffer.Length == 7, "buffer.Length == 7", "buffer size invalid");
if (buffer.Length != 7)
throw new ArgumentException ("Buffer size must be 7 bytes");
// Reverse bits
bits = new BitArray (buffer.Length * 8);
for (int i = 0; i < buffer.Length; i++) {
for (int y = 0; y < 8; y++) {
bits[i * 8 + y] = ((buffer[i] & (1 << (7 - y))) > 0);
}
}
bitindex = 0;
}
#endregion
#region Public Methods
/// <summary>
/// Reads an Int32 from the bitstream
/// </summary>
/// <param name="numberOfBits">
/// A <see cref="int" /> value containing the number
/// of bits to read from the bitstream
/// </param>
public int ReadInt32 (int numberOfBits)
{
Debug.Assert (numberOfBits > 0, "numberOfBits < 1");
Debug.Assert (numberOfBits <= 32, "numberOfBits <= 32");
if (numberOfBits <= 0)
throw new ArgumentException ("Number of bits to read must be >= 1");
if (numberOfBits > 32)
throw new ArgumentException ("Number of bits to read must be <= 32");
int value = 0;
int start = bitindex + numberOfBits - 1;
for (int i = 0; i < numberOfBits; i++) {
value += bits[start] ? (1 << i) : 0;
bitindex++;
start--;
}
return value;
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8284bad068f4283f29df4c52751a79cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+272
View File
@@ -0,0 +1,272 @@
//
// File.cs: Provides tagging and properties support for ADTS AAC files
//
// Here is the ADTS Header description used for implementation:
// http://www.hydrogenaudio.org/forums/lofiversion/index.php/t21617.html
//
// Copyright (C) 2009 Patrick Dehne
//
// 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.Aac
{
/// <summary>
/// This class extends <see cref="TagLib.NonContainer.File" /> to
/// provide tagging and properties support for ADTS AAC audio files.
/// </summary>
/// <remarks>
/// A <see cref="TagLib.Id3v1.Tag" /> and <see
/// cref="TagLib.Id3v2.Tag" /> will be added automatically to any
/// file that doesn't contain one. This change does not effect the
/// file until it is saved and can be reversed using the following
/// method:
/// <code>file.RemoveTags (file.TagTypes &amp; ~file.TagTypesOnDisk);</code>
/// </remarks>
[SupportedMimeType ("taglib/aac", "aac")]
[SupportedMimeType ("audio/aac")]
public class File : TagLib.NonContainer.File
{
#region Private Fields
/// <summary>
/// Contains the first audio header.
/// </summary>
AudioHeader first_header;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local
/// file system and specified read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path, ReadStyle propertiesStyle)
: base (path, propertiesStyle)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local
/// file system with an average read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path) : base (path)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified file abstraction and
/// specified read style.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
/// reading from and writing to the file.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public File (IFileAbstraction abstraction, ReadStyle propertiesStyle)
: base (abstraction, propertiesStyle)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified file abstraction with
/// an average read style.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
/// reading from and writing to the file.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public File (IFileAbstraction abstraction)
: base (abstraction)
{
}
#endregion
#region Public Methods
/// <summary>
/// Gets a tag of a specified type from the current instance,
/// optionally creating a new tag if possible.
/// </summary>
/// <param name="type">
/// A <see cref="TagLib.TagTypes" /> value indicating the
/// type of tag to read.
/// </param>
/// <param name="create">
/// A <see cref="bool" /> value specifying whether or not to
/// try and create the tag if one is not found.
/// </param>
/// <returns>
/// A <see cref="Tag" /> object containing the tag that was
/// found in or added to the current instance. If no
/// matching tag was found and none was created, <see
/// langword="null" /> is returned.
/// </returns>
/// <remarks>
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
/// current instance, it will be placed at the start of the
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
/// the file. All other tag types will be ignored.
/// </remarks>
public override Tag GetTag (TagTypes type, bool create)
{
Tag t = (Tag as TagLib.NonContainer.Tag).GetTag (type);
if (t != null || !create)
return t;
switch (type) {
case TagTypes.Id3v1:
return EndTag.AddTag (type, Tag);
case TagTypes.Id3v2:
return StartTag.AddTag (type, Tag);
case TagTypes.Ape:
return EndTag.AddTag (type, Tag);
default:
return null;
}
}
#endregion
#region Protected Methods
/// <summary>
/// Reads format specific information at the start of the
/// file.
/// </summary>
/// <param name="start">
/// A <see cref="long" /> value containing the seek position
/// at which the tags end and the media data begins.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <remarks>
/// This method only searches for an audio header in the
/// first 16384 bytes of code to avoid searching forever in
/// corrupt files.
/// </remarks>
protected override void ReadStart (long start, ReadStyle propertiesStyle)
{
// Only check the first 16 bytes so we're not stuck
// reading a bad file forever.
if ((propertiesStyle & ReadStyle.Average) != 0 &&
!AudioHeader.Find (out first_header, this, start, 0x4000))
throw new CorruptFileException ("ADTS audio header not found.");
}
/// <summary>
/// Reads format specific information at the end of the
/// file.
/// </summary>
/// <param name="end">
/// A <see cref="long" /> value containing the seek position
/// at which the media data ends and the tags begin.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
protected override void ReadEnd (long end, ReadStyle propertiesStyle)
{
// Make sure we have ID3v1 and ID3v2 tags.
GetTag (TagTypes.Id3v1, true);
GetTag (TagTypes.Id3v2, true);
}
/// <summary>
/// Reads the audio properties from the file represented by
/// the current instance.
/// </summary>
/// <param name="start">
/// A <see cref="long" /> value containing the seek position
/// at which the tags end and the media data begins.
/// </param>
/// <param name="end">
/// A <see cref="long" /> value containing the seek position
/// at which the media data ends and the tags begin.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <returns>
/// A <see cref="TagLib.Properties" /> object describing the
/// media properties of the file represented by the current
/// instance.
/// </returns>
protected override Properties ReadProperties (long start, long end, ReadStyle propertiesStyle)
{
first_header.SetStreamLength (end - start);
return new Properties (TimeSpan.Zero, first_header);
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ea5a2b9978c53a708489187d4f05f90
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4e181c0c58fe3641d805ee0aabca0c10
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+486
View File
@@ -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
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7c3c2cdcd3206d6c2984e6419139fc01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+248
View File
@@ -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:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81f4ff937a733e84599dd980bba85dcf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+275
View File
@@ -0,0 +1,275 @@
//
// File.cs: Provides tagging and properties support for Monkey's Audio APE
// files.
//
// Author:
// Helmut Wahrmann
//
// Copyright (C) 2007 Helmut Wahrmann
// 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.Ape
{
/// <summary>
/// This class extends <see cref="TagLib.NonContainer.File" /> to
/// provide tagging and properties support for Monkey's Audio APE
/// files.
/// </summary>
/// <remarks>
/// A <see cref="TagLib.Ape.Tag" /> will be added automatically to
/// any file that doesn't contain one. This change does not effect
/// the physical file until <see cref="TagLib.File.Save" /> is called and can be
/// reversed using the following method:
/// <code>file.RemoveTags (file.TagTypes &amp; ~file.TagTypesOnDisk);</code>
/// </remarks>
[SupportedMimeType ("taglib/ape", "ape")]
[SupportedMimeType ("audio/x-ape")]
[SupportedMimeType ("audio/ape")]
[SupportedMimeType ("application/x-ape")]
public class File : TagLib.NonContainer.File
{
#region Private Fields
/// <summary>
/// Contains the block with the audio header.
/// </summary>
ByteVector header_block;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local file
/// system and specified read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path, ReadStyle propertiesStyle)
: base (path, propertiesStyle)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local file
/// system with an average read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path)
: base (path)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified file abstraction and
/// specified read style.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
/// reading from and writing to the file.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public File (IFileAbstraction abstraction, ReadStyle propertiesStyle)
: base (abstraction, propertiesStyle)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified file abstraction with an
/// average read style.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
/// reading from and writing to the file.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public File (IFileAbstraction abstraction)
: base (abstraction)
{
}
#endregion
#region Public Methods
/// <summary>
/// Gets a tag of a specified type from the current instance,
/// optionally creating a new tag if possible.
/// </summary>
/// <param name="type">
/// A <see cref="TagLib.TagTypes" /> value indicating the
/// type of tag to read.
/// </param>
/// <param name="create">
/// A <see cref="bool" /> value specifying whether or not to
/// try and create the tag if one is not found.
/// </param>
/// <returns>
/// A <see cref="Tag" /> object containing the tag that was
/// found in or added to the current instance. If no
/// matching tag was found and none was created, <see
/// langword="null" /> is returned.
/// </returns>
/// <remarks>
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
/// current instance, it will be placed at the start of the
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
/// the file. All other tag types will be ignored.
/// </remarks>
public override TagLib.Tag GetTag (TagTypes type, bool create)
{
TagLib.Tag t = (Tag as TagLib.NonContainer.Tag)
.GetTag (type);
if (t != null || !create)
return t;
switch (type) {
case TagTypes.Id3v1:
return EndTag.AddTag (type, Tag);
case TagTypes.Id3v2:
return StartTag.AddTag (type, Tag);
case TagTypes.Ape:
return EndTag.AddTag (type, Tag);
default:
return null;
}
}
#endregion
#region Protected Methods
/// <summary>
/// Reads format specific information at the start of the
/// file.
/// </summary>
/// <param name="start">
/// A <see cref="long" /> value containing the seek position
/// at which the tags end and the media data begins.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
protected override void ReadStart (long start, ReadStyle propertiesStyle)
{
if (header_block != null &&
(propertiesStyle & ReadStyle.Average) == 0)
return;
Seek (start);
header_block = ReadBlock ((int)StreamHeader.Size);
}
/// <summary>
/// Reads format specific information at the end of the
/// file.
/// </summary>
/// <param name="end">
/// A <see cref="long" /> value containing the seek position
/// at which the media data ends and the tags begin.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
protected override void ReadEnd (long end, ReadStyle propertiesStyle)
{
// Make sure we have an APE tag.
GetTag (TagTypes.Ape, true);
}
/// <summary>
/// Reads the audio properties from the file represented by
/// the current instance.
/// </summary>
/// <param name="start">
/// A <see cref="long" /> value containing the seek position
/// at which the tags end and the media data begins.
/// </param>
/// <param name="end">
/// A <see cref="long" /> value containing the seek position
/// at which the media data ends and the tags begin.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <returns>
/// A <see cref="TagLib.Properties" /> object describing the
/// media properties of the file represented by the current
/// instance.
/// </returns>
protected override Properties ReadProperties (long start, long end, ReadStyle propertiesStyle)
{
StreamHeader header = new StreamHeader (header_block,
end - start);
return new Properties (TimeSpan.Zero, header);
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6bd919f3cebce9e6b94eb2887772bf8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+392
View File
@@ -0,0 +1,392 @@
//
// Footer.cs: Provides a representation of an APEv2 tag footer which can be read
// from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Original Source:
// apefooter.cpp from TagLib
//
// Copyright (C) 2005-2007 Brian Nickel
// Copyright (C) 2004 Allan Sandfeld Jensen (Original Implementation)
// copyright (C) 2002, 2003 Scott Wheeler (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
namespace TagLib.Ape
{
#region Enums
/// <summary>
/// Indicates the flags applied to a <see cref="Footer" /> object.
/// </summary>
[Flags]
public enum FooterFlags : uint
{
/// <summary>
/// The tag lacks a footer object.
/// </summary>
FooterAbsent = 0x40000000,
/// <summary>
/// The footer is actually a header.
/// </summary>
IsHeader = 0x20000000,
/// <summary>
/// The tag contains a header.
/// </summary>
HeaderPresent = 0x80000000
}
#endregion
/// <summary>
/// This structure provides a representation of an APEv2 tag footer
/// which can be read from and written to disk.
/// </summary>
public struct Footer : IEquatable<Footer>
{
#region Private Properties
/// <summary>
/// Contains the APE tag version.
/// </summary>
readonly uint version;
#endregion
#region Public Static Fields
/// <summary>
/// Specifies the size of an APEv2 footer.
/// </summary>
public const uint Size = 32;
/// <summary>
/// Specifies the identifier used find an APEv2 footer in a
/// file.
/// </summary>
/// <value>
/// "<c>APETAGEX</c>"
/// </value>
public static readonly ReadOnlyByteVector FileIdentifier = "APETAGEX";
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Footer" /> by reading it from raw footer data.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the raw
/// data to build the new instance from.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> is smaller than <see
/// cref="Size" /> or does not begin with <see
/// cref="FileIdentifier" />.
/// </exception>
public Footer (ByteVector data)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (data.Count < Size)
throw new CorruptFileException ("Provided data is smaller than object size.");
if (!data.StartsWith (FileIdentifier))
throw new CorruptFileException ("Provided data does not start with File Identifier");
version = data.Mid (8, 4).ToUInt (false);
TagSize = data.Mid (12, 4).ToUInt (false);
ItemCount = data.Mid (16, 4).ToUInt (false);
Flags = (FooterFlags)data.Mid (20, 4).ToUInt (false);
}
#endregion
#region Public Properties
/// <summary>
/// Gets the version of APE tag described by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the version of the
/// APE tag described by the current instance.
/// </value>
public uint Version {
get { return version == 0 ? 2000 : version; }
}
/// <summary>
/// Gets and sets the flags that apply to the current
/// instance.
/// </summary>
/// <value>
/// A bitwise combined <see cref="FooterFlags" /> value
/// containing the flags that apply to the current instance.
/// </value>
public FooterFlags Flags { get; set; }
/// <summary>
/// Gets and sets the number of items in the tag represented
/// by the current instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the number of
/// items in the tag represented by the current instance.
/// </value>
public uint ItemCount { get; set; }
/// <summary>
/// Gets the size of the tag represented by the current
/// instance, including the footer but excluding the header
/// if applicable.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the size of the
/// tag represented by the current instance.
/// </value>
public uint TagSize { get; set; }
/// <summary>
/// Gets the complete size of the tag represented by the
/// current instance, including the header and footer.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the size of the
/// tag represented by the current instance.
/// </value>
public uint CompleteTagSize {
get {
return TagSize + ((Flags &
FooterFlags.HeaderPresent) != 0 ?
Size : 0);
}
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as an APE tag footer.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public ByteVector RenderFooter ()
{
return Render (false);
}
/// <summary>
/// Renders the current instance as an APE tag header.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance or an empty
/// <see cref="ByteVector" /> object if <see cref="Flags" />
/// does not include <see cref="FooterFlags.HeaderPresent"
/// />.
/// </returns>
public ByteVector RenderHeader ()
{
return (Flags & FooterFlags.HeaderPresent) != 0 ? Render (true) : new ByteVector ();
}
#endregion
#region Private Methods
/// <summary>
/// Renders the current instance as either an APE tag header
/// or footer.
/// </summary>
/// <param name="isHeader">
/// A <see cref="bool" /> value indicating whether or not the
/// current instance is to be rendered as a header.
/// </param>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
ByteVector Render (bool isHeader)
{
var v = new ByteVector {
// add the file identifier -- "APETAGEX"
FileIdentifier,
// add the version number -- we always render a 2.000
// tag regardless of what the tag originally was.
ByteVector.FromUInt (2000, false),
// add the tag size
ByteVector.FromUInt (TagSize, false),
// add the item count
ByteVector.FromUInt (ItemCount, false)
};
// render and add the flags
uint flags = 0;
if ((Flags & FooterFlags.HeaderPresent) != 0)
flags |= (uint)FooterFlags.HeaderPresent;
// footer is always present
if (isHeader)
flags |= (uint)FooterFlags.IsHeader;
else
flags &= (uint)~FooterFlags.IsHeader;
v.Add (ByteVector.FromUInt (flags, false));
// add the reserved 64bit
v.Add (ByteVector.FromULong (0));
return v;
}
#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)((uint)Flags ^ TagSize ^ ItemCount ^ version);
}
}
/// <summary>
/// Checks whether or not the current instance is equal to
/// another object.
/// </summary>
/// <param name="other">
/// A <see cref="object" /> to compare to the current
/// instance.
/// </param>
/// <returns>
/// A <see cref="bool" /> value indicating whether or not the
/// current instance is equal to <paramref name="other" />.
/// </returns>
/// <seealso cref="M:System.IEquatable`1.Equals" />
public override bool Equals (object other)
{
if (!(other is Footer))
return false;
return Equals ((Footer)other);
}
/// <summary>
/// Checks whether or not the current instance is equal to
/// another instance of <see cref="Footer" />.
/// </summary>
/// <param name="other">
/// A <see cref="Footer" /> 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 (Footer other)
{
return Flags == other.Flags &&
TagSize == other.TagSize &&
ItemCount == other.ItemCount &&
version == other.version;
}
/// <summary>
/// Gets whether or not two instances of <see cref="Footer"
/// /> are equal to eachother.
/// </summary>
/// <param name="first">
/// The first <see cref="Footer" /> object to compare.
/// </param>
/// <param name="second">
/// The second <see cref="Footer" /> 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 == (Footer first, Footer second)
{
return first.Equals (second);
}
/// <summary>
/// Gets whether or not two instances of <see cref="Footer"
/// /> are unequal to eachother.
/// </summary>
/// <param name="first">
/// The first <see cref="Footer" /> object to compare.
/// </param>
/// <param name="second">
/// The second <see cref="Footer" /> 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 != (Footer first, Footer second)
{
return !first.Equals (second);
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3fd643b62da0d63f89725b4266c74752
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+500
View File
@@ -0,0 +1,500 @@
//
// Item.cs: Provides a representation of an APEv2 tag item which can be read
// from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Original Source:
// apeitem.cpp from TagLib
//
// Copyright (C) 2005-2007 Brian Nickel
// Copyright (C) 2004 by Allan Sandfeld Jensen (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
namespace TagLib.Ape
{
/// <summary>
/// Indicates the type of data stored in a <see cref="Item" />
/// object.
/// </summary>
public enum ItemType
{
/// <summary>
/// The item contains Unicode text.
/// </summary>
Text = 0,
/// <summary>
/// The item contains binary data.
/// </summary>
Binary = 1,
/// <summary>
/// The item contains a locator (file path/URL) for external
/// information.
/// </summary>
Locator = 2
}
/// <summary>
/// This class provides a representation of an APEv2 tag item which
/// can be read from and written to disk.
/// </summary>
public class Item : ICloneable
{
#region Private Fields
/// <summary>
/// Contains the item value.
/// </summary>
ReadOnlyByteVector data;
/// <summary>
/// Contains the item text.
/// </summary>
string[] text;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Item" /> by reading in a raw APEv2 item.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the item to
/// read.
/// </param>
/// <param name="offset">
/// A <see cref="int" /> value specifying the offset in
/// <paramref name="data" /> at which the item data 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">
/// A complete item could not be read.
/// </exception>
public Item (ByteVector data, int offset)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
Parse (data, offset);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Item" /> with a specified key and value.
/// </summary>
/// <param name="key">
/// A <see cref="string" /> object containing the key to use
/// for the current instance.
/// </param>
/// <param name="value">
/// A <see cref="string" /> object containing the value to
/// store in the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="key" /> or <paramref name="value" /> is
/// <see langword="null" />.
/// </exception>
public Item (string key, string value)
{
if (key == null)
throw new ArgumentNullException (nameof (key));
if (value == null)
throw new ArgumentNullException (nameof (value));
Key = key;
text = new [] { value };
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Item" /> with a specified key and collection of
/// values.
/// </summary>
/// <param name="key">
/// A <see cref="string" /> object containing the key to use
/// for the current instance.
/// </param>
/// <param name="value">
/// A <see cref="T:string[]" /> containing the values to store
/// in the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="key" /> or <paramref name="value" /> is
/// <see langword="null" />.
/// </exception>
public Item (string key, params string[] value)
{
if (key == null)
throw new ArgumentNullException (nameof (key));
if (value == null)
throw new ArgumentNullException (nameof (value));
Key = key;
text = (string[])value.Clone ();
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Item" /> with a specified key and collection of
/// values.
/// </summary>
/// <param name="key">
/// A <see cref="string" /> object containing the key to use
/// for the current instance.
/// </param>
/// <param name="value">
/// A <see cref="StringCollection" /> object containing the
/// values to store in the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="key" /> or <paramref name="value" /> is
/// <see langword="null" />.
/// </exception>
/// <seealso cref="Item(string,string[])" />
[Obsolete ("Use Item(string,string[])")]
public Item (string key, StringCollection value)
{
if (key == null)
throw new ArgumentNullException (nameof (key));
if (value == null)
throw new ArgumentNullException (nameof (value));
Key = key;
text = value.ToArray ();
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Item" /> with a specified key and raw data.
/// </summary>
/// <param name="key">
/// A <see cref="string" /> object containing the key to use
/// for the current instance.
/// </param>
/// <param name="value">
/// A <see cref="StringCollection" /> object containing the
/// values to store in the new instance.
/// </param>
/// <remarks>
/// This constructor automatically marks the new instance as
/// <see cref="ItemType.Binary" />.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// <paramref name="key" /> or <paramref name="value" /> is
/// <see langword="null" />.
/// </exception>
/// <seealso cref="Item(string,string[])" />
public Item (string key, ByteVector value)
{
Key = key;
Type = ItemType.Binary;
data = value as ReadOnlyByteVector;
if (data == null)
data = new ReadOnlyByteVector (value);
}
Item (Item item)
{
Type = item.Type;
Key = item.Key;
if (item.data != null)
data = new ReadOnlyByteVector (item.data);
if (item.text != null)
text = (string[])item.text.Clone ();
ReadOnly = item.ReadOnly;
Size = item.Size;
}
#endregion
#region Public Properties
/// <summary>
/// Gets the key used to identify the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the key used to
/// identify the current instance.
/// </value>
/// <remarks>
/// This value is used for specifying the contents of the
/// item in a common and consistant fashion. For example,
/// <c>"TITLE"</c> specifies that the item contains the title
/// of the track.
/// </remarks>
public string Key { get; private set; }
/// <summary>
/// Gets the binary value stored in the current instance.
/// </summary>
/// <value>
/// A <see cref="ByteVector" /> object containing the binary
/// value stored in the current instance, or <see
/// langword="null" /> if the item contains text.
/// </value>
public ByteVector Value {
get { return (Type == ItemType.Binary) ? data : null; }
}
/// <summary>
/// Gets the size of the current instance as it last appeared
/// on disk.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing the size of the
/// current instance as it last appeared on disk.
/// </value>
public int Size { get; private set; }
/// <summary>
/// Gets and sets the type of value contained in the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="ItemType" /> value indicating the type of
/// value contained in the current instance.
/// </value>
public ItemType Type { get; set; } = ItemType.Text;
/// <summary>
/// Gets and sets whether or not the current instance is
/// flagged as read-only on disk.
/// </summary>
/// <value>
/// A <see cref="bool" /> value indicating whether or not the
/// current instance is flagged as read-only on disk.
/// </value>
public bool ReadOnly { get; set; }
/// <summary>
/// Gets whether or not the current instance is empty.
/// </summary>
/// <value>
/// A <see cref="bool" /> value indicating whether or not the
/// current instance contains no value.
/// </value>
public bool IsEmpty {
get {
if (Type != ItemType.Binary)
return text == null || text.Length == 0;
else
return data == null || data.IsEmpty;
}
}
#endregion
#region Public Methods
/// <summary>
/// Gets the contents of the current instance as a <see
/// cref="string" />.
/// </summary>
/// <returns>
/// <para>A <see cref="string" /> object containing the text
/// stored in the current instance, or <see langword="null"
/// /> if the item is empty of contains binary data.</para>
/// <para>If the current instance contains multiple string
/// values, they will be returned as a comma separated
/// value.</para>
/// </returns>
public override string ToString ()
{
if (Type == ItemType.Binary || text == null)
return null;
return string.Join (", ", text);
}
/// <summary>
/// Gets the contents of the current instance as a <see
/// cref="string" /> array.
/// </summary>
/// <returns>
/// A <see cref="T:string[]" /> containing the text stored in
/// the current instance, or an empty array if the item
/// contains binary data.
/// </returns>
public string[] ToStringArray ()
{
if (Type == ItemType.Binary || text == null)
return new string[0];
return text;
}
/// <summary>
/// Renders the current instance as an APEv2 item.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public ByteVector Render ()
{
uint flags = (uint)((ReadOnly) ? 1 : 0) |
((uint)Type << 1);
if (IsEmpty)
return new ByteVector ();
ByteVector result = null;
if (Type == ItemType.Binary) {
if (text == null && data != null)
result = data;
}
if (result == null && text != null) {
result = new ByteVector ();
for (int i = 0; i < text.Length; i++) {
if (i != 0)
result.Add (0);
result.Add (ByteVector.FromString (text[i], StringType.UTF8));
}
}
// If no data is stored, don't write the item.
if (result == null || result.Count == 0)
return new ByteVector ();
var output = new ByteVector {
ByteVector.FromUInt ((uint)result.Count,
false),
ByteVector.FromUInt (flags, false),
ByteVector.FromString (Key, StringType.UTF8),
0,
result
};
Size = output.Count;
return output;
}
#endregion
#region Protected Methods
/// <summary>
/// Populates the current instance by reading in a raw APEv2
/// item.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the item to
/// read.
/// </param>
/// <param name="offset">
/// A <see cref="int" /> value specifying the offset in
/// <paramref name="data" /> at which the item data 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">
/// A complete item could not be read.
/// </exception>
protected void Parse (ByteVector data, int offset)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (offset < 0)
throw new ArgumentOutOfRangeException (nameof (offset));
// 11 bytes is the minimum size for an APE item
if (data.Count < offset + 11)
throw new CorruptFileException ("Not enough data for APE Item");
uint value_length = data.Mid (offset, 4).ToUInt (false);
uint flags = data.Mid (offset + 4, 4).ToUInt (false);
ReadOnly = (flags & 1) == 1;
Type = (ItemType)((flags >> 1) & 3);
int pos = data.Find (ByteVector.TextDelimiter (StringType.UTF8), offset + 8);
Key = data.ToString (StringType.UTF8, offset + 8, pos - offset - 8);
if (value_length > data.Count - pos - 1)
throw new CorruptFileException ("Invalid data length.");
Size = pos + 1 + (int)value_length - offset;
if (Type == ItemType.Binary)
this.data = new ReadOnlyByteVector (data.Mid (pos + 1, (int)value_length));
else
text = data.Mid (pos + 1, (int)value_length).ToStrings (StringType.UTF8, 0);
}
#endregion
#region ICloneable
/// <summary>
/// Creates a deep copy of the current instance.
/// </summary>
/// <returns>
/// A new <see cref="Item"/> object identical to the current
/// instance.
/// </returns>
public Item Clone ()
{
return new Item (this);
}
object ICloneable.Clone ()
{
return Clone ();
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec6d7edea3a67467d8e074bff4ac65d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+359
View File
@@ -0,0 +1,359 @@
//
// StreamHeader.cs: Provides support for reading Monkey's Audio APE stream
// properties.
//
// Author:
// Helmut Wahrmann
//
// Copyright (C) 2007 Helmut Wahrmann
// 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.Ape
{
/// <summary>
/// Indicates the compression level used when encoding a Monkey's
/// Audio APE file.
/// </summary>
public enum CompressionLevel
{
/// <summary>
/// The audio is not compressed.
/// </summary>
None = 0,
/// <summary>
/// The audio is mildly compressed.
/// </summary>
Fast = 1000,
/// <summary>
/// The audio is compressed at a normal level.
/// </summary>
Normal = 2000,
/// <summary>
/// The audio is highly compressed.
/// </summary>
High = 3000,
/// <summary>
/// The audio is extremely highly compressed.
/// </summary>
ExtraHigh = 4000,
/// <summary>
/// The audio is compressed to an insane level.
/// </summary>
Insane
}
/// <summary>
/// This struct implements <see cref="IAudioCodec" /> to provide
/// support for reading Monkey's Audio APE stream properties.
/// </summary>
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
{
#region Private Fields
/// <summary>
/// Contains the APE version.
/// </summary>
/// <remarks>
/// This value is stored in bytes (4,5) of the file and is
/// 1000 times the actual version number, so 3810 indicates
/// version 3.81.
/// </remarks>
readonly ushort version;
/*
/// <summary>
/// Contains the format flags.
/// </summary>
/// <remarks>
/// This value is stored in bytes (53,54).
/// </remarks>
private ushort format_flags;
*/
/// <summary>
/// Contains the number of audio blocks in one frame.
/// </summary>
/// <remarks>
/// This value is stored in bytes (55-58).
/// </remarks>
readonly uint blocks_per_frame;
/// <summary>
/// Contains the number of audio blocks in the final frame.
/// </summary>
/// <remarks>
/// This value is stored in bytes (59-62).
/// </remarks>
readonly uint final_frame_blocks;
/// <summary>
/// Contains the total number of frames.
/// </summary>
/// <remarks>
/// This value is stored in bytes (63-66).
/// </remarks>
readonly uint total_frames;
/// <summary>
/// Contains the number of bits per sample.
/// </summary>
/// <remarks>
/// This value is stored in bytes (67,68) and is typically
/// 16.
/// </remarks>
readonly ushort bits_per_sample;
/// <summary>
/// Contains the number of channels.
/// </summary>
/// <remarks>
/// This value is stored in bytes (69,70) and is typically
/// 1 or 2.
/// </remarks>
readonly ushort channels;
/// <summary>
/// Contains the sample rate.
/// </summary>
/// <remarks>
/// This value is stored in bytes (71-74) and is typically
/// 44100.
/// </remarks>
readonly uint 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 a Monkey Audio header.
/// </summary>
public const uint Size = 76;
/// <summary>
/// The identifier used to recognize a WavPack file.
/// </summary>
/// <value>
/// "MAC "
/// </value>
public static readonly ReadOnlyByteVector FileIdentifier = "MAC ";
#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
/// Monkey 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" /> or is less than <see cref="Size"
/// /> bytes long.
/// </exception>
public StreamHeader (ByteVector data, long streamLength)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
if (!data.StartsWith (FileIdentifier))
throw new CorruptFileException (
"Data does not begin with identifier.");
if (data.Count < Size)
throw new CorruptFileException (
"Insufficient data in stream header");
stream_length = streamLength;
version = data.Mid (4, 2).ToUShort (false);
Compression = (CompressionLevel)data.Mid (52, 2)
.ToUShort (false);
// format_flags = data.Mid(54, 2).ToUShort(false);
blocks_per_frame = data.Mid (56, 4).ToUInt (false);
final_frame_blocks = data.Mid (60, 4).ToUInt (false);
total_frames = data.Mid (64, 4).ToUInt (false);
bits_per_sample = data.Mid (68, 2).ToUShort (false);
channels = data.Mid (70, 2).ToUShort (false);
sample_rate = data.Mid (72, 4).ToUInt (false);
}
#endregion
#region Public Properties
/// <summary>
/// Gets the duration of the media represented by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="TimeSpan" /> containing the duration of the
/// media represented by the current instance.
/// </value>
public TimeSpan Duration {
get {
if (sample_rate <= 0 || total_frames <= 0)
return TimeSpan.Zero;
return TimeSpan.FromSeconds (
((total_frames - 1) *
blocks_per_frame + final_frame_blocks) /
(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 string.Format (
CultureInfo.InvariantCulture, "Monkey's Audio APE Version {0:0.000}", Version);
}
}
/// <summary>
/// Gets the bitrate of the audio represented by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="int" /> value containing a bitrate of the
/// audio represented by the current instance.
/// </value>
public int AudioBitrate {
get {
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 APE version of the audio represented by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="double" /> value containing the APE version
/// of the audio represented by the current instance.
/// </value>
public double Version {
get { return version / (double)1000; }
}
/// <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; }
}
/// <summary>
/// Gets the level of compression used when encoding the
/// audio represented by the current instance.
/// </summary>
/// <value>
/// A <see cref="CompressionLevel" /> value indicating the
/// level of compression used when encoding the audio
/// represented by the current instance.
/// </value>
public CompressionLevel Compression { get; private set; }
#endregion
}␍}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d8234dea7db8f83ed86cb702f3474bbe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e937bf4e5ed85bb70b1660583e8eb5dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5551302f5547e0525a891b390866fb18
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,263 @@
//
// ContentDescriptionObject.cs: Provides a representation of an ASF Content
// Description object which can be read from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF Content Description object which can be
/// read from and written to disk.
/// </summary>
public class ContentDescriptionObject : Object
{
#region Private Fields
/// <summary>
/// Contains the media title.
/// </summary>
string title = string.Empty;
/// <summary>
/// Contains the author/performer.
/// </summary>
string author = string.Empty;
/// <summary>
/// Contains the copyright information.
/// </summary>
string copyright = string.Empty;
/// <summary>
/// Contains the description of the media.
/// </summary>
string description = string.Empty;
/// <summary>
/// Contains the rating of the media.
/// </summary>
string rating = string.Empty;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptionObject" /> by reading the
/// contents from a specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or smaller than the minimum size.
/// </exception>
public ContentDescriptionObject (File file, long position)
: base (file, position)
{
if (Guid != Asf.Guid.AsfContentDescriptionObject)
throw new CorruptFileException ("Object GUID incorrect.");
if (OriginalSize < 34)
throw new CorruptFileException ("Object size too small.");
ushort title_length = file.ReadWord ();
ushort author_length = file.ReadWord ();
ushort copyright_length = file.ReadWord ();
ushort description_length = file.ReadWord ();
ushort rating_length = file.ReadWord ();
title = file.ReadUnicode (title_length);
author = file.ReadUnicode (author_length);
copyright = file.ReadUnicode (copyright_length);
description = file.ReadUnicode (description_length);
rating = file.ReadUnicode (rating_length);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptionObject" /> with no contents.
/// </summary>
public ContentDescriptionObject ()
: base (Asf.Guid.AsfContentDescriptionObject)
{
}
#endregion
#region Public Region
/// <summary>
/// Gets and sets the title of the media described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the title of
/// the media or <see langword="null" /> if it is not set.
/// </value>
public string Title {
get { return title.Length == 0 ? null : title; }
set {
title = string.IsNullOrEmpty (value) ? string.Empty : value;
}
}
/// <summary>
/// Gets and sets the author or performer of the media
/// described by the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the author of
/// the media or <see langword="null" /> if it is not set.
/// </value>
public string Author {
get { return author.Length == 0 ? null : author; }
set {
author = string.IsNullOrEmpty (value) ? string.Empty : value;
}
}
/// <summary>
/// Gets and sets the copyright information for the media
/// described by the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the copyright
/// information for the media or <see langword="null" /> if
/// it is not set.
/// </value>
public string Copyright {
get { return copyright.Length == 0 ? null : copyright; }
set {
copyright = string.IsNullOrEmpty (value) ? string.Empty : value;
}
}
/// <summary>
/// Gets and sets the description of the media described by
/// the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing a description
/// of the media or <see langword="null" /> if it is not set.
/// </value>
public string Description {
get {
return description.Length == 0 ? null : description;
}
set {
description = string.IsNullOrEmpty (value) ? string.Empty : value;
}
}
/// <summary>
/// Gets and sets the rating of the media described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing a rating of the
/// media or <see langword="null" /> if it is not set.
/// </value>
public string Rating {
get { return rating.Length == 0 ? null : rating; }
set {
rating = string.IsNullOrEmpty (value) ? string.Empty : value;
}
}
/// <summary>
/// Gets whether or not the current instance is empty.
/// </summary>
/// <value>
/// <see langword="true" /> if all the values are cleared.
/// Otherwise <see langword="false" />.
/// </value>
public bool IsEmpty {
get {
return title.Length == 0 &&
author.Length == 0 &&
copyright.Length == 0 &&
description.Length == 0 &&
rating.Length == 0;
}
}
#endregion
#region Public Region
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
ByteVector title_bytes = RenderUnicode (title);
ByteVector author_bytes = RenderUnicode (author);
ByteVector copyright_bytes = RenderUnicode (copyright);
ByteVector description_bytes =
RenderUnicode (description);
ByteVector rating_bytes = RenderUnicode (rating);
ByteVector output = RenderWord ((ushort)
title_bytes.Count);
output.Add (RenderWord ((ushort)author_bytes.Count));
output.Add (RenderWord ((ushort)copyright_bytes.Count));
output.Add (RenderWord ((ushort)
description_bytes.Count));
output.Add (RenderWord ((ushort)rating_bytes.Count));
output.Add (title_bytes);
output.Add (author_bytes);
output.Add (copyright_bytes);
output.Add (description_bytes);
output.Add (rating_bytes);
return Render (output);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f526cfb69af160d3c9edf6227f73e985
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,474 @@
//
// ContentDescriptor.cs: Provides a representation of an ASF Content Descriptor
// to be used in combination with ExtendedContentDescriptionObject.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// Indicates the type of data stored in a <see
/// cref="ContentDescriptor" /> or <see cref="DescriptionRecord" />
/// object.
/// </summary>
public enum DataType
{
/// <summary>
/// The descriptor contains Unicode (UTF-16LE) text.
/// </summary>
Unicode = 0,
/// <summary>
/// The descriptor contains binary data.
/// </summary>
Bytes = 1,
/// <summary>
/// The descriptor contains a boolean value.
/// </summary>
Bool = 2,
/// <summary>
/// The descriptor contains a 4-byte DWORD value.
/// </summary>
DWord = 3,
/// <summary>
/// The descriptor contains a 8-byte QWORD value.
/// </summary>
QWord = 4,
/// <summary>
/// The descriptor contains a 2-byte WORD value.
/// </summary>
Word = 5,
/// <summary>
/// The descriptor contains a 16-byte GUID value.
/// </summary>
Guid = 6
}
/// <summary>
/// This class provides a representation of an ASF Content
/// Descriptor to be used in combination with <see
/// cref="ExtendedContentDescriptionObject" />.
/// </summary>
public class ContentDescriptor
{
#region Private Fields
/// <summary>
/// Contains the string value.
/// </summary>
string strValue;
/// <summary>
/// Contains the byte value.
/// </summary>
ByteVector byteValue;
/// <summary>
/// Contains the long value.
/// </summary>
ulong longValue;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptor" /> with a specified name and
/// and value.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="string" /> object containing the value for
/// the new instance.
/// </param>
public ContentDescriptor (string name, string value)
{
Name = name;
strValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptor" /> with a specified name and
/// and value.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="ByteVector" /> object containing the value
/// for the new instance.
/// </param>
public ContentDescriptor (string name, ByteVector value)
{
Name = name;
Type = DataType.Bytes;
byteValue = new ByteVector (value);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptor" /> with a specified name and
/// and value.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="uint" /> value containing the value
/// for the new instance.
/// </param>
public ContentDescriptor (string name, uint value)
{
Name = name;
Type = DataType.DWord;
longValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptor" /> with a specified name and
/// and value.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="ulong" /> value containing the value
/// for the new instance.
/// </param>
public ContentDescriptor (string name, ulong value)
{
Name = name;
Type = DataType.QWord;
longValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptor" /> with a specified name and
/// and value.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="ushort" /> value containing the value
/// for the new instance.
/// </param>
public ContentDescriptor (string name, ushort value)
{
Name = name;
Type = DataType.Word;
longValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptor" /> with a specified name and
/// and value.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="bool" /> value containing the value
/// for the new instance.
/// </param>
public ContentDescriptor (string name, bool value)
{
Name = name;
Type = DataType.Bool;
longValue = value ? 1uL : 0;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ContentDescriptor" /> by reading its contents from
/// a file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object to read the raw ASF
/// Description Record from.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// A valid descriptor could not be read.
/// </exception>
/// <remarks>
/// <paramref name="file" /> must be at a seek position at
/// which the descriptor can be read.
/// </remarks>
protected internal ContentDescriptor (File file)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
if (!Parse (file))
throw new CorruptFileException ("Failed to parse content descriptor.");
}
#endregion
#region Public Properties
/// <summary>
/// Gets the name of the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the name of the
/// current instance.
/// </value>
public string Name { get; private set; }
/// <summary>
/// Gets the type of data contained in the current instance.
/// </summary>
/// <value>
/// A <see cref="DataType" /> value indicating type of data
/// contained in the current instance.
/// </value>
public DataType Type { get; private set; } = DataType.Unicode;
#endregion
#region Public Methods
/// <summary>
/// Gets a string representation of the current instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> object containing the value of
/// the current instance.
/// </returns>
public override string ToString ()
{
if (Type == DataType.Unicode)
return strValue;
if (Type == DataType.Bytes)
return byteValue.ToString (StringType.UTF16LE);
return longValue.ToString ();
}
/// <summary>
/// Gets the binary contents of the current instance.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// contents of the current instance, or <see langword="null"
/// /> if <see cref="Type" /> is unequal to <see
/// cref="DataType.Bytes" />.
/// </returns>
public ByteVector ToByteVector ()
{
return byteValue;
}
/// <summary>
/// Gets the boolean value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="bool" /> value containing the value of the
/// current instance.
/// </returns>
public bool ToBool ()
{
return longValue != 0;
}
/// <summary>
/// Gets the DWORD value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="uint" /> value containing the value of the
/// current instance.
/// </returns>
public uint ToDWord ()
{
if (Type == DataType.Unicode && strValue != null && uint.TryParse (strValue, out var value))
return value;
return (uint)longValue;
}
/// <summary>
/// Gets the QWORD value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="ulong" /> value containing the value of the
/// current instance.
/// </returns>
public ulong ToQWord ()
{
if (Type == DataType.Unicode && strValue != null && ulong.TryParse (strValue, out var value))
return value;
return longValue;
}
/// <summary>
/// Gets the WORD value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="ushort" /> value containing the value of the
/// current instance.
/// </returns>
public ushort ToWord ()
{
if (Type == DataType.Unicode && strValue != null && ushort.TryParse (strValue, out var value))
return value;
return (ushort)longValue;
}
/// <summary>
/// Renders the current instance as a raw ASF Description
/// Record.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public ByteVector Render ()
{
ByteVector value;
switch (Type) {
case DataType.Unicode:
value = Object.RenderUnicode (strValue);
break;
case DataType.Bytes:
value = byteValue;
break;
case DataType.Bool:
case DataType.DWord:
value = Object.RenderDWord ((uint)longValue);
break;
case DataType.QWord:
value = Object.RenderQWord (longValue);
break;
case DataType.Word:
value = Object.RenderWord ((ushort)longValue);
break;
default:
return null;
}
ByteVector name = Object.RenderUnicode (Name);
var output = new ByteVector {
Object.RenderWord ((ushort)name.Count),
name,
Object.RenderWord ((ushort)Type),
Object.RenderWord ((ushort)value.Count),
value
};
return output;
}
#endregion
#region Protected Methods
/// <summary>
/// Populates the current instance by reading in the contents
/// from a file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object to read the raw ASF
/// Content Descriptor from.
/// </param>
/// <returns>
/// <see langword="true" /> if the data was read correctly.
/// Otherwise <see langword="false" />.
/// </returns>
protected bool Parse (File file)
{
int name_count = file.ReadWord ();
Name = file.ReadUnicode (name_count);
Type = (DataType)file.ReadWord ();
int value_count = file.ReadWord ();
switch (Type) {
case DataType.Word:
longValue = file.ReadWord ();
break;
case DataType.Bool:
longValue = file.ReadDWord ();
break;
case DataType.DWord:
longValue = file.ReadDWord ();
break;
case DataType.QWord:
longValue = file.ReadQWord ();
break;
case DataType.Unicode:
strValue = file.ReadUnicode (value_count);
break;
case DataType.Bytes:
byteValue = file.ReadBlock (value_count);
break;
default:
return false;
}
return true;
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 12848f0d0cefe0dd3864fc18248f7482
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,568 @@
//
// DescriptionRecord.cs: Provides a representation of an ASF Description Record
// to be used in combination with MetadataLibaryObject.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class provides a representation of an ASF Description Record
/// to be used in combination with <see cref="MetadataLibraryObject"
/// />.
/// </summary>
public class DescriptionRecord
{
#region Private Fields
/// <summary>
/// Contains the string value.
/// </summary>
string strValue;
/// <summary>
/// Contains the byte value.
/// </summary>
ByteVector byteValue;
/// <summary>
/// Contains the long value.
/// </summary>
ulong longValue;
/// <summary>
/// Contains the GUID value.
/// </summary>
System.Guid guidValue = System.Guid.Empty;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> with a specified language,
/// stream, name, and value.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the new instance.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the new instance.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="string" /> object containing the value for
/// the new instance.
/// </param>
public DescriptionRecord (ushort languageListIndex, ushort streamNumber, string name, string value)
{
LanguageListIndex = languageListIndex;
StreamNumber = streamNumber;
Name = name;
strValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> with a specified language,
/// stream, name, and value.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the new instance.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the new instance.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="ByteVector" /> object containing the value
/// for the new instance.
/// </param>
public DescriptionRecord (ushort languageListIndex, ushort streamNumber, string name, ByteVector value)
{
LanguageListIndex = languageListIndex;
StreamNumber = streamNumber;
Name = name;
Type = DataType.Bytes;
byteValue = new ByteVector (value);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> with a specified language,
/// stream, name, and value.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the new instance.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the new instance.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="uint" /> value containing the value
/// for the new instance.
/// </param>
public DescriptionRecord (ushort languageListIndex, ushort streamNumber, string name, uint value)
{
LanguageListIndex = languageListIndex;
StreamNumber = streamNumber;
Name = name;
Type = DataType.DWord;
longValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> with a specified language,
/// stream, name, and value.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the new instance.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the new instance.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="ulong" /> value containing the value
/// for the new instance.
/// </param>
public DescriptionRecord (ushort languageListIndex, ushort streamNumber, string name, ulong value)
{
LanguageListIndex = languageListIndex;
StreamNumber = streamNumber;
Name = name;
Type = DataType.QWord;
longValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> with a specified language,
/// stream, name, and value.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the new instance.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the new instance.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="ushort" /> value containing the value
/// for the new instance.
/// </param>
public DescriptionRecord (ushort languageListIndex, ushort streamNumber, string name, ushort value)
{
LanguageListIndex = languageListIndex;
StreamNumber = streamNumber;
Name = name;
Type = DataType.Word;
longValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> with a specified language,
/// stream, name, and value.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the new instance.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the new instance.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="bool" /> value containing the value
/// for the new instance.
/// </param>
public DescriptionRecord (ushort languageListIndex, ushort streamNumber, string name, bool value)
{
LanguageListIndex = languageListIndex;
StreamNumber = streamNumber;
Name = name;
Type = DataType.Bool;
longValue = value ? 1uL : 0;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> with a specified language,
/// stream, name, and value.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the new instance.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the new instance.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// new instance.
/// </param>
/// <param name="value">
/// A <see cref="System.Guid" /> value containing the value
/// for the new instance.
/// </param>
public DescriptionRecord (ushort languageListIndex, ushort streamNumber, string name, System.Guid value)
{
LanguageListIndex = languageListIndex;
StreamNumber = streamNumber;
Name = name;
Type = DataType.Guid;
guidValue = value;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="DescriptionRecord" /> by reading its contents from
/// a file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object to read the raw ASF
/// Description Record from.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="file" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// A valid record could not be read.
/// </exception>
/// <remarks>
/// <paramref name="file" /> must be at a seek position at
/// which the record can be read.
/// </remarks>
protected internal DescriptionRecord (File file)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
if (!Parse (file))
throw new CorruptFileException ("Failed to parse description record.");
}
#endregion
#region Public Properties
/// <summary>
/// Gets the index of the language associated with the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value containing the index of the
/// language associated with the current instance.
/// </value>
public ushort LanguageListIndex { get; private set; }
/// <summary>
/// Gets the index of the stream associated with the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value containing the index of the
/// stream associated with the current instance.
/// </value>
public ushort StreamNumber { get; private set; }
/// <summary>
/// Gets the name of the current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the name of the
/// current instance.
/// </value>
public string Name { get; private set; }
/// <summary>
/// Gets the type of data contained in the current instance.
/// </summary>
/// <value>
/// A <see cref="DataType" /> value indicating type of data
/// contained in the current instance.
/// </value>
public DataType Type { get; private set; } = DataType.Unicode;
#endregion
#region Public Methods
/// <summary>
/// Gets a string representation of the current instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> object containing the value of
/// the current instance.
/// </returns>
public override string ToString ()
{
if (Type == DataType.Unicode)
return strValue;
if (Type == DataType.Bytes)
return byteValue.ToString (StringType.UTF16LE);
return longValue.ToString ();
}
/// <summary>
/// Gets the binary contents of the current instance.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// contents of the current instance, or <see langword="null"
/// /> if <see cref="Type" /> is unequal to <see
/// cref="DataType.Bytes" />.
/// </returns>
public ByteVector ToByteVector ()
{
return byteValue;
}
/// <summary>
/// Gets the boolean value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="bool" /> value containing the value of the
/// current instance.
/// </returns>
public bool ToBool ()
{
return longValue != 0;
}
/// <summary>
/// Gets the DWORD value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="uint" /> value containing the value of the
/// current instance.
/// </returns>
public uint ToDWord ()
{
if (Type == DataType.Unicode && strValue != null && uint.TryParse (strValue, out var value))
return value;
return (uint)longValue;
}
/// <summary>
/// Gets the QWORD value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="ulong" /> value containing the value of the
/// current instance.
/// </returns>
public ulong ToQWord ()
{
if (Type == DataType.Unicode && strValue != null && ulong.TryParse (strValue, out var value))
return value;
return longValue;
}
/// <summary>
/// Gets the WORD value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="ushort" /> value containing the value of the
/// current instance.
/// </returns>
public ushort ToWord ()
{
if (Type == DataType.Unicode && strValue != null && ushort.TryParse (strValue, out var value))
return value;
return (ushort)longValue;
}
/// <summary>
/// Gets the GUID value contained in the current instance.
/// </summary>
/// <returns>
/// A <see cref="System.Guid" /> value containing the value
/// of the current instance.
/// </returns>
public System.Guid ToGuid ()
{
return guidValue;
}
/// <summary>
/// Renders the current instance as a raw ASF Description
/// Record.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public ByteVector Render ()
{
ByteVector value;
switch (Type) {
case DataType.Unicode:
value = Object.RenderUnicode (strValue);
break;
case DataType.Bytes:
value = byteValue;
break;
case DataType.Bool:
case DataType.DWord:
value = Object.RenderDWord ((uint)longValue);
break;
case DataType.QWord:
value = Object.RenderQWord (longValue);
break;
case DataType.Word:
value = Object.RenderWord ((ushort)longValue);
break;
case DataType.Guid:
value = guidValue.ToByteArray ();
break;
default:
return null;
}
ByteVector name = Object.RenderUnicode (Name);
var output = new ByteVector {
Object.RenderWord (LanguageListIndex),
Object.RenderWord (StreamNumber),
Object.RenderWord ((ushort)name.Count),
Object.RenderWord ((ushort)Type),
Object.RenderDWord ((uint)value.Count),
name,
value
};
return output;
}
#endregion
#region Protected Methods
/// <summary>
/// Populates the current instance by reading in the contents
/// from a file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object to read the raw ASF
/// Description Record from.
/// </param>
/// <returns>
/// <see langword="true" /> if the data was read correctly.
/// Otherwise <see langword="false" />.
/// </returns>
protected bool Parse (File file)
{
// Field name Field type Size (bits)
// Language List Index WORD 16
// Stream Number WORD 16
// Name Length WORD 16
// Data Type WORD 16
// Data Length DWORD 32
// Name WCHAR varies
// Data See below varies
LanguageListIndex = file.ReadWord ();
StreamNumber = file.ReadWord ();
ushort name_length = file.ReadWord ();
Type = (DataType)file.ReadWord ();
int data_length = (int)file.ReadDWord ();
Name = file.ReadUnicode (name_length);
switch (Type) {
case DataType.Word:
longValue = file.ReadWord ();
break;
case DataType.Bool:
case DataType.DWord:
longValue = file.ReadDWord ();
break;
case DataType.QWord:
longValue = file.ReadQWord ();
break;
case DataType.Unicode:
strValue = file.ReadUnicode (data_length);
break;
case DataType.Bytes:
byteValue = file.ReadBlock (data_length);
break;
case DataType.Guid:
guidValue = file.ReadGuid ();
break;
default:
return false;
}
return true;
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b240cea38450eb09286babb6fd6d82c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,270 @@
//
// ExtendedContentDescriptionObject.cs: Provides a representation of an ASF
// Extended Content Description object which can be read from and written to
// disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF Extended Content Description object
/// which can be read from and written to disk.
/// </summary>
public class ExtendedContentDescriptionObject : Object, IEnumerable<ContentDescriptor>
{
#region Private Fields
/// <summary>
/// Contains the content descriptors.
/// </summary>
readonly List<ContentDescriptor> descriptors = new List<ContentDescriptor> ();
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ExtendedContentDescriptionObject" /> by reading the
/// contents from a specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or smaller than the minimum size.
/// </exception>
public ExtendedContentDescriptionObject (File file, long position)
: base (file, position)
{
if (!Guid.Equals (Asf.Guid.AsfExtendedContentDescriptionObject))
throw new CorruptFileException ("Object GUID incorrect.");
if (OriginalSize < 26)
throw new CorruptFileException ("Object size too small.");
ushort count = file.ReadWord ();
for (ushort i = 0; i < count; i++)
AddDescriptor (new ContentDescriptor (file));
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ExtendedContentDescriptionObject" /> with no
/// contents.
/// </summary>
public ExtendedContentDescriptionObject ()
: base (Asf.Guid.AsfExtendedContentDescriptionObject)
{
}
#endregion
#region Public Properties
/// <summary>
/// Gets whether or not the current instance is empty.
/// </summary>
/// <value>
/// <see langword="true" /> if the current instance doesn't
/// contain any <see cref="ContentDescriptor" /> objects.
/// Otherwise <see langword="false" />.
/// </value>
public bool IsEmpty {
get { return descriptors.Count == 0; }
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
ByteVector output = new ByteVector ();
ushort count = 0;
foreach (ContentDescriptor desc in descriptors) {
count++;
output.Add (desc.Render ());
}
return Render (RenderWord (count) + output);
}
/// <summary>
/// Removes all descriptors with a given name from the
/// current instance.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// descriptors to be removed.
/// </param>
public void RemoveDescriptors (string name)
{
for (int i = descriptors.Count - 1; i >= 0; i--)
if (name == descriptors[i].Name)
descriptors.RemoveAt (i);
}
/// <summary>
/// Gets all descriptors with any of a collection of names
/// from the current instance.
/// </summary>
/// <param name="names">
/// A <see cref="T:string[]" /> containing the names of the
/// descriptors to be retrieved.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="names" /> is <see langword="null" />.
/// </exception>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
/// through the <see cref="ContentDescriptor" /> objects
/// retrieved from the current instance.
/// </returns>
public IEnumerable<ContentDescriptor> GetDescriptors (params string[] names)
{
if (names == null)
throw new ArgumentNullException (nameof (names));
foreach (string name in names)
foreach (ContentDescriptor desc in descriptors)
if (desc.Name == name)
yield return desc;
}
/// <summary>
/// Adds a descriptor to the current instance.
/// </summary>
/// <param name="descriptor">
/// A <see cref="ContentDescriptor" /> object to add to the
/// current instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="descriptor" /> is <see langword="null"
/// />.
/// </exception>
public void AddDescriptor (ContentDescriptor descriptor)
{
if (descriptor == null)
throw new ArgumentNullException (nameof (descriptor));
descriptors.Add (descriptor);
}
/// <summary>
/// Sets the a collection of desciptors for a given name,
/// removing the existing matching records.
/// </summary>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// descriptors to be added.
/// </param>
/// <param name="descriptors">
/// A <see cref="T:ContentDescriptor[]" /> containing
/// descriptors to add to the new instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="name" /> is <see langword="null" />.
/// </exception>
/// <remarks>
/// All added entries in <paramref name="descriptors" />
/// should match <paramref name="name" /> but it is not
/// verified by the method. The descriptors will be added
/// with their own names and not the one provided in this
/// method, which are used for removing existing values and
/// determining where to position the new objects.
/// </remarks>
public void SetDescriptors (string name, params ContentDescriptor[] descriptors)
{
if (name == null)
throw new ArgumentNullException (nameof (name));
int position = this.descriptors.Count;
for (int i = this.descriptors.Count - 1; i >= 0; i--) {
if (name == this.descriptors[i].Name) {
this.descriptors.RemoveAt (i);
position = i;
}
}
this.descriptors.InsertRange (position, descriptors);
}
#endregion
#region IEnumerable
/// <summary>
/// Gets an enumerator for enumerating through the content
/// descriptors.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.IEnumerator`1" /> for
/// enumerating through the content descriptors.
/// </returns>
public IEnumerator<ContentDescriptor> GetEnumerator ()
{
return descriptors.GetEnumerator ();
}
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator ()
{
return descriptors.GetEnumerator ();
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d284fb627fd9b464a993ff8f4769b52c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+436
View File
@@ -0,0 +1,436 @@
//
// File.cs: Provides tagging and properties support for Microsoft's ASF files.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="TagLib.File" /> to provide tagging
/// and properties support for Microsoft's ASF files.
/// </summary>
[SupportedMimeType ("taglib/wma", "wma")]
[SupportedMimeType ("taglib/wmv", "wmv")]
[SupportedMimeType ("taglib/asf", "asf")]
[SupportedMimeType ("audio/x-ms-wma")]
[SupportedMimeType ("audio/x-ms-asf")]
[SupportedMimeType ("video/x-ms-asf")]
public class File : TagLib.File
{
#region Private Fields
/// <summary>
/// Contains the file's tag.
/// </summary>
Tag asf_tag;
/// <summary>
/// Contains the file's properties.
/// </summary>
Properties properties;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local file
/// system and specified read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path, ReadStyle propertiesStyle)
: base (path)
{
Read (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)
{
Read (propertiesStyle);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified file abstraction with an
/// average read style.
/// </summary>
/// <param name="abstraction">
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
/// reading from and writing to the file.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="abstraction" /> is <see langword="null"
/// />.
/// </exception>
public File (IFileAbstraction abstraction)
: 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 TagLib.Tag Tag {
get { return asf_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 header = new HeaderObject (this, 0);
if (asf_tag == null) {
header.RemoveContentDescriptors ();
TagTypesOnDisk &= ~TagTypes.Asf;
} else {
TagTypesOnDisk |= TagTypes.Asf;
header.AddUniqueObject (
asf_tag.ContentDescriptionObject);
header.AddUniqueObject (
asf_tag.ExtendedContentDescriptionObject);
header.Extension.AddUniqueObject (
asf_tag.MetadataLibraryObject);
}
var output = header.Render ();
long diff = output.Count - (long)header.OriginalSize;
Insert (output, 0, (long)header.OriginalSize);
InvariantStartPosition += diff;
InvariantEndPosition += diff;
} finally {
Mode = AccessMode.Closed;
}
}
/// <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 TagLib.Tag GetTag (TagTypes type, bool create)
{
if (type == TagTypes.Asf)
return asf_tag;
return null;
}
/// <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.Asf) == TagTypes.Asf)
asf_tag.Clear ();
}
/// <summary>
/// Reads a 2-byte WORD from the current instance.
/// </summary>
/// <returns>
/// A <see cref="ushort" /> value containing the WORD read
/// from the current instance.
/// </returns>
public ushort ReadWord ()
{
return ReadBlock (2).ToUShort (false);
}
/// <summary>
/// Reads a 4-byte DWORD from the current instance.
/// </summary>
/// <returns>
/// A <see cref="uint" /> value containing the DWORD read
/// from the current instance.
/// </returns>
public uint ReadDWord ()
{
return ReadBlock (4).ToUInt (false);
}
/// <summary>
/// Reads a 8-byte QWORD from the current instance.
/// </summary>
/// <returns>
/// A <see cref="ulong" /> value containing the QWORD read
/// from the current instance.
/// </returns>
public ulong ReadQWord ()
{
return ReadBlock (8).ToULong (false);
}
/// <summary>
/// Reads a 16-byte GUID from the current instance.
/// </summary>
/// <returns>
/// A <see cref="System.Guid" /> value containing the GUID
/// read from the current instance.
/// </returns>
public System.Guid ReadGuid ()
{
return new System.Guid (ReadBlock (16).Data);
}
/// <summary>
/// Reads a Unicode (UTF-16LE) string of specified length
/// from the current instance.
/// </summary>
/// <param name="length">
/// A <see cref="int" /> value specifying the number of bytes
/// to read. This should always be an even number.
/// </param>
/// <returns>
/// A <see cref="string" /> object containing the Unicode
/// string read from the current instance.
/// </returns>
public string ReadUnicode (int length)
{
ByteVector data = ReadBlock (length);
string output = data.ToString (StringType.UTF16LE);
int i = output.IndexOf ('\0');
return (i >= 0) ? output.Substring (0, i) : output;
}
/// <summary>
/// Reads a collection of objects from the current instance.
/// </summary>
/// <param name="count">
/// A <see cref="uint" /> value specifying the number of
/// objects to read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specifying the seek position
/// at which to start reading.
/// </param>
/// <returns>
/// A new <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
/// through the <see cref="Object" /> objects read from the
/// current instance.
/// </returns>
public IEnumerable<Object> ReadObjects (uint count,
long position)
{
for (int i = 0; i < (int)count; i++) {
Object obj = ReadObject (position);
position += (long)obj.OriginalSize;
yield return obj;
}
}
/// <summary>
/// Reads a <see cref="Object" /> from the current instance.
/// </summary>
/// <param name="position">
/// A <see cref="long" /> value specifying the seek position
/// at which to start reading.
/// </param>
/// <returns>
/// A new <see cref="Object" /> object of appropriate type as
/// read from the current instance.
/// </returns>
public Object ReadObject (long position)
{
Seek (position);
System.Guid id = ReadGuid ();
if (id.Equals (Guid.AsfFilePropertiesObject))
return new FilePropertiesObject (this,
position);
if (id.Equals (Guid.AsfStreamPropertiesObject))
return new StreamPropertiesObject (this,
position);
if (id.Equals (Guid.AsfContentDescriptionObject))
return new ContentDescriptionObject (this,
position);
if (id.Equals (
Guid.AsfExtendedContentDescriptionObject))
return new ExtendedContentDescriptionObject (
this, position);
if (id.Equals (Guid.AsfPaddingObject))
return new PaddingObject (this, position);
if (id.Equals (Guid.AsfHeaderExtensionObject))
return new HeaderExtensionObject (this,
position);
if (id.Equals (Guid.AsfMetadataLibraryObject))
return new MetadataLibraryObject (this,
position);
return new UnknownObject (this, position);
}
#endregion
#region Private Methods
/// <summary>
/// Reads the contents of the current instance.
/// </summary>
/// <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>
void Read (ReadStyle propertiesStyle)
{
Mode = AccessMode.Read;
try {
HeaderObject header = new HeaderObject (this, 0);
if (header.HasContentDescriptors)
TagTypesOnDisk |= TagTypes.Asf;
asf_tag = new Tag (header);
InvariantStartPosition = (long)header.OriginalSize;
InvariantEndPosition = Length;
if ((propertiesStyle & ReadStyle.Average) != 0)
properties = header.Properties;
} finally {
Mode = AccessMode.Closed;
}
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 230597e1f22d7c4048805f50836d30b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,275 @@
//
// FilePropertiesObject.cs: Provides a representation of an ASF File Properties
// object which can be read from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF File Properties object which can be read
/// from and written to disk.
/// </summary>
public class FilePropertiesObject : Object
{
#region Constant Values
static readonly DateTime FileTimeOffset = new DateTime (1601, 1, 1);
#endregion
#region Private Fields
/// <summary>
/// Contains the GUID for the file.
/// </summary>
System.Guid file_id;
/// <summary>
/// Contains the creation date.
/// </summary>
readonly ulong creation_date;
/// <summary>
/// Contains the play duration.
/// </summary>
readonly ulong play_duration;
/// <summary>
/// Contains the send duration.
/// </summary>
readonly ulong send_duration;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="FilePropertiesObject" /> by reading the contents
/// from a specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or smaller than the minimum size.
/// </exception>
public FilePropertiesObject (File file, long position)
: base (file, position)
{
if (!Guid.Equals (Asf.Guid.AsfFilePropertiesObject))
throw new CorruptFileException ("Object GUID incorrect.");
if (OriginalSize < 104)
throw new CorruptFileException ("Object size too small.");
file_id = file.ReadGuid ();
FileSize = file.ReadQWord ();
creation_date = file.ReadQWord ();
DataPacketsCount = file.ReadQWord ();
play_duration = file.ReadQWord ();
send_duration = file.ReadQWord ();
Preroll = file.ReadQWord ();
Flags = file.ReadDWord ();
MinimumDataPacketSize = file.ReadDWord ();
MaximumDataPacketSize = file.ReadDWord ();
MaximumBitrate = file.ReadDWord ();
}
#endregion
#region Public Properties
/// <summary>
/// Gets the GUID for the file described by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="System.Guid" /> value containing the GUID
/// for the file described by the current instance.
/// </value>
public System.Guid FileId {
get { return file_id; }
}
/// <summary>
/// Gets the size of the file described by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="ulong" /> value containing the size of the
/// file described by the current instance.
/// </value>
public ulong FileSize { get; private set; }
/// <summary>
/// Gets the creation date of the file described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="DateTime" /> value containing the creation
/// date of the file described by the current instance.
/// </value>
public DateTime CreationDate {
get { return new DateTime ((long)creation_date + FileTimeOffset.Ticks); }
}
/// <summary>
/// Gets the number of data packets in the file described by
/// the current instance.
/// </summary>
/// <value>
/// A <see cref="ulong" /> value containing the number of
/// data packets in the file described by the current
/// instance.
/// </value>
public ulong DataPacketsCount { get; private set; }
/// <summary>
/// Gets the play duration of the file described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="TimeSpan" /> value containing the play
/// duration of the file described by the current instance.
/// </value>
public TimeSpan PlayDuration {
get { return new TimeSpan ((long)play_duration); }
}
/// <summary>
/// Gets the send duration of the file described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="TimeSpan" /> value containing the send
/// duration of the file described by the current instance.
/// </value>
public TimeSpan SendDuration {
get { return new TimeSpan ((long)send_duration); }
}
/// <summary>
/// Gets the pre-roll of the file described by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="ulong" /> value containing the pre-roll of
/// the file described by the current instance.
/// </value>
public ulong Preroll { get; private set; }
/// <summary>
/// Gets the flags of the file described by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the flags of the
/// file described by the current instance.
/// </value>
public uint Flags { get; private set; }
/// <summary>
/// Gets the minimum data packet size of the file described
/// by the current instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the minimum data
/// packet size of the file described by the current
/// instance.
/// </value>
public uint MinimumDataPacketSize { get; private set; }
/// <summary>
/// Gets the maximum data packet size of the file described
/// by the current instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the maximum data
/// packet size of the file described by the current
/// instance.
/// </value>
public uint MaximumDataPacketSize { get; private set; }
/// <summary>
/// Gets the maximum bitrate of the file described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="uint" /> value containing the maximum
/// bitrate of the file described by the current instance.
/// </value>
public uint MaximumBitrate { get; private set; }
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
ByteVector output = file_id.ToByteArray ();
output.Add (RenderQWord (FileSize));
output.Add (RenderQWord (creation_date));
output.Add (RenderQWord (DataPacketsCount));
output.Add (RenderQWord (play_duration));
output.Add (RenderQWord (send_duration));
output.Add (RenderQWord (Preroll));
output.Add (RenderDWord (Flags));
output.Add (RenderDWord (MinimumDataPacketSize));
output.Add (RenderDWord (MaximumDataPacketSize));
output.Add (RenderDWord (MaximumBitrate));
return Render (output);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aadef2fcac80345fe8d8d585ba22aed5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+110
View File
@@ -0,0 +1,110 @@
//
// Guid.cs: Provides common GUID values used by ASF Objects.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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
//
namespace TagLib.Asf
{
/// <summary>
/// This static class contains common <see cref="System.Guid" />
/// values used by ASF Objects.
/// </summary>
public static class Guid
{
/// <summary>
/// Indicates that an object is a <see
/// cref="ContentDescriptionObject" />.
/// </summary>
public static readonly System.Guid AsfContentDescriptionObject =
new System.Guid ("75B22633-668E-11CF-A6D9-00AA0062CE6C");
/// <summary>
/// Indicates that an object is a <see
/// cref="ExtendedContentDescriptionObject" />.
/// </summary>
public static readonly System.Guid AsfExtendedContentDescriptionObject =
new System.Guid ("D2D0A440-E307-11D2-97F0-00A0C95EA850");
/// <summary>
/// Indicates that an object is a <see
/// cref="FilePropertiesObject" />.
/// </summary>
public static readonly System.Guid AsfFilePropertiesObject =
new System.Guid ("8CABDCA1-A947-11CF-8EE4-00C00C205365");
/// <summary>
/// Indicates that an object is a <see
/// cref="HeaderExtensionObject" />.
/// </summary>
public static readonly System.Guid AsfHeaderExtensionObject =
new System.Guid ("5FBF03B5-A92E-11CF-8EE3-00C00C205365");
/// <summary>
/// Indicates that an object is a <see
/// cref="HeaderObject" />.
/// </summary>
public static readonly System.Guid AsfHeaderObject =
new System.Guid ("75B22630-668E-11CF-A6D9-00AA0062CE6C");
/// <summary>
/// Indicates that an object is a <see
/// cref="MetadataLibraryObject" />.
/// </summary>
public static readonly System.Guid AsfMetadataLibraryObject =
new System.Guid ("44231C94-9498-49D1-A141-1D134E457054");
/// <summary>
/// Indicates that an object is a <see
/// cref="PaddingObject" />.
/// </summary>
public static readonly System.Guid AsfPaddingObject =
new System.Guid ("1806D474-CADF-4509-A4BA-9AABCB96AAE8");
/// <summary>
/// Indicates that an object is a <see
/// cref="StreamPropertiesObject" />.
/// </summary>
public static readonly System.Guid AsfStreamPropertiesObject =
new System.Guid ("B7DC0791-A9B7-11CF-8EE6-00C00C205365");
/// <summary>
/// Indicates that a <see cref="StreamPropertiesObject" />
/// contains information about an audio stream.
/// </summary>
public static readonly System.Guid AsfAudioMedia =
new System.Guid ("F8699E40-5B4D-11CF-A8FD-00805F5C442B");
/// <summary>
/// Indicates that a <see cref="StreamPropertiesObject" />
/// contains information about an video stream.
/// </summary>
public static readonly System.Guid AsfVideoMedia =
new System.Guid ("BC19EFC0-5B4D-11CF-A8FD-00805F5C442B");
/// <summary>
/// Indicates a placeholder portion of a file is correctly
/// encoded.
/// </summary>
public static readonly System.Guid AsfReserved1 =
new System.Guid ("ABD3D211-A9BA-11cf-8EE6-00C00C205365");
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 106d81de03690f00d9a5574b209c688b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,174 @@
//
// HeaderExtensionObject.cs: Provides a representation of an ASF Header
// Extension object which can be read from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF Header Extension object which can be
/// read from and written to disk.
/// </summary>
public class HeaderExtensionObject : Object
{
#region Private Fields
/// <summary>
/// Contains the child objects.
/// </summary>
readonly List<Object> children = new List<Object> ();
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="HeaderExtensionObject" /> by reading the contents
/// from a specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or contents.
/// </exception>
public HeaderExtensionObject (File file, long position)
: base (file, position)
{
if (!Guid.Equals (Asf.Guid.AsfHeaderExtensionObject))
throw new CorruptFileException ("Object GUID incorrect.");
if (file.ReadGuid () != Asf.Guid.AsfReserved1)
throw new CorruptFileException ("Reserved1 GUID expected.");
if (file.ReadWord () != 6)
throw new CorruptFileException ("Invalid reserved WORD. Expected '6'.");
uint size_remaining = file.ReadDWord ();
position += 0x170 / 8;
while (size_remaining > 0) {
Object obj = file.ReadObject (position);
position += (long)obj.OriginalSize;
size_remaining -= (uint)obj.OriginalSize;
children.Add (obj);
}
}
#endregion
#region Public Properties
/// <summary>
/// Gets the child objects contained in the current instance.
/// </summary>
/// <value>
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
/// through the children of the current instance.
/// </value>
public IEnumerable<Object> Children {
get { return children; }
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
ByteVector output = new ByteVector ();
foreach (var child in children)
output.Add (child.Render ());
output.Insert (0, RenderDWord ((uint)output.Count));
output.Insert (0, RenderWord (6));
output.Insert (0, Asf.Guid.AsfReserved1.ToByteArray ());
return Render (output);
}
/// <summary>
/// Adds a child object to the current instance.
/// </summary>
/// <param name="obj">
/// A <see cref="Object" /> object to add to the current
/// instance.
/// </param>
public void AddObject (Object obj)
{
children.Add (obj);
}
/// <summary>
/// Adds a child unique child object to the current instance,
/// replacing and existing child if present.
/// </summary>
/// <param name="obj">
/// A <see cref="Object" /> object to add to the current
/// instance.
/// </param>
public void AddUniqueObject (Object obj)
{
for (int i = 0; i < children.Count; i++)
if (children[i].Guid == obj.Guid) {
children[i] = obj;
return;
}
children.Add (obj);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc8a5039b8de0c71c9af979086ce9378
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+265
View File
@@ -0,0 +1,265 @@
//
// HeaderObject.cs: Provides a representation of an ASF Header object which can
// be read from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF Header object which can be read from and
/// written to disk.
/// </summary>
public class HeaderObject : Object
{
#region Private Fields
/// <summary>
/// Contains the reserved header data.
/// </summary>
readonly ByteVector reserved;
/// <summary>
/// Contains the child objects.
/// </summary>
readonly List<Object> children;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="HeaderObject" /> by reading the contents from a
/// specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or smaller than the minimum size.
/// </exception>
public HeaderObject (File file, long position)
: base (file, position)
{
if (!Guid.Equals (Asf.Guid.AsfHeaderObject))
throw new CorruptFileException ("Object GUID incorrect.");
if (OriginalSize < 26)
throw new CorruptFileException ("Object size too small.");
children = new List<Object> ();
uint child_count = file.ReadDWord ();
reserved = file.ReadBlock (2);
children.AddRange (file.ReadObjects (child_count,
file.Tell));
}
#endregion
#region Public Properties
/// <summary>
/// Gets the header extension object contained in the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="HeaderExtensionObject" /> object containing
/// the header extension object.
/// </value>
public HeaderExtensionObject Extension {
get {
foreach (Object child in children)
if (child is HeaderExtensionObject)
return child as HeaderExtensionObject;
return null;
}
}
/// <summary>
/// Gets the child objects contained in the current instance.
/// </summary>
/// <value>
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
/// through the children of the current instance.
/// </value>
public IEnumerable<Object> Children {
get { return children; }
}
/// <summary>
/// Gets the media properties contained within the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="Properties" /> object containing the media
/// properties of the current instance.
/// </value>
public Properties Properties {
get {
TimeSpan duration = TimeSpan.Zero;
var codecs = new List<ICodec> ();
foreach (var obj in Children) {
if (obj is FilePropertiesObject fpobj) {
duration = fpobj.PlayDuration - TimeSpan.FromMilliseconds (fpobj.Preroll);
continue;
}
if (obj is StreamPropertiesObject spobj) {
codecs.Add (spobj.Codec);
}
}
return new Properties (duration, codecs);
}
}
/// <summary>
/// Gets whether or not the current instance contains either
/// type of content descriptiors.
/// </summary>
/// <value>
/// <see langword="true" /> if the current instance contains
/// a <see cref="ContentDescriptionObject" /> or a <see
/// cref="ExtendedContentDescriptionObject" />. Otherwise
/// <see langword="false" />.
/// </value>
public bool HasContentDescriptors {
get {
foreach (Object child in children)
if (child.Guid == Asf.Guid.AsfContentDescriptionObject ||
child.Guid == Asf.Guid.AsfExtendedContentDescriptionObject)
return true;
return false;
}
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
var output = new ByteVector ();
uint child_count = 0;
foreach (var child in children)
if (child.Guid != Asf.Guid.AsfPaddingObject) {
output.Add (child.Render ());
child_count++;
}
long size_diff = (long)output.Count + 30 -
(long)OriginalSize;
if (size_diff != 0) {
var obj = new PaddingObject ((uint)(size_diff > 0 ? 4096 : -size_diff));
output.Add (obj.Render ());
child_count++;
}
output.Insert (0, reserved);
output.Insert (0, RenderDWord (child_count));
return Render (output);
}
/// <summary>
/// Adds a child object to the current instance.
/// </summary>
/// <param name="obj">
/// A <see cref="Object" /> object to add to the current
/// instance.
/// </param>
public void AddObject (Object obj)
{
children.Add (obj);
}
/// <summary>
/// Adds a child unique child object to the current instance,
/// replacing and existing child if present.
/// </summary>
/// <param name="obj">
/// A <see cref="Object" /> object to add to the current
/// instance.
/// </param>
public void AddUniqueObject (Object obj)
{
for (int i = 0; i < children.Count; i++)
if (children[i].Guid == obj.Guid) {
children[i] = obj;
return;
}
children.Add (obj);
}
/// <summary>
/// Removes the content description objects from the current
/// instance.
/// </summary>
public void RemoveContentDescriptors ()
{
for (int i = children.Count - 1; i >= 0; i--)
if (children[i].Guid == Asf.Guid.AsfContentDescriptionObject ||
children[i].Guid == Asf.Guid.AsfExtendedContentDescriptionObject)
children.RemoveAt (i);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28f74c9348168792da3d31feb083107a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,288 @@
//
// MetadataLibraryObject.cs: Provides a representation of an ASF Metadata
// Library object which can be read from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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;
using System.Collections.Generic;
namespace TagLib.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF Metadata Library object which can be
/// read from and written to disk.
/// </summary>
public class MetadataLibraryObject : Object, IEnumerable<DescriptionRecord>
{
#region Private Fields
/// <summary>
/// Contains the description records.
/// </summary>
readonly List<DescriptionRecord> records = new List<DescriptionRecord> ();
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="MetadataLibraryObject" /> by reading the contents
/// from a specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or smaller than the minimum size.
/// </exception>
public MetadataLibraryObject (File file, long position)
: base (file, position)
{
if (!Guid.Equals (Asf.Guid.AsfMetadataLibraryObject))
throw new CorruptFileException ("Object GUID incorrect.");
if (OriginalSize < 26)
throw new CorruptFileException ("Object size too small.");
ushort count = file.ReadWord ();
for (ushort i = 0; i < count; i++) {
var rec = new DescriptionRecord (file);
AddRecord (rec);
}
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="MetadataLibraryObject" /> with no contents.
/// </summary>
public MetadataLibraryObject ()
: base (Asf.Guid.AsfMetadataLibraryObject)
{
}
#endregion
#region Public Properties
/// <summary>
/// Gets whether or not the current instance is empty.
/// </summary>
/// <value>
/// <see langword="true" /> if the current instance doesn't
/// contain any <see cref="DescriptionRecord" /> objects.
/// Otherwise <see langword="false" />.
/// </value>
public bool IsEmpty {
get { return records.Count == 0; }
}
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
ByteVector output = new ByteVector ();
ushort count = 0;
foreach (DescriptionRecord rec in records) {
count++;
output.Add (rec.Render ());
}
return Render (RenderWord (count) + output);
}
/// <summary>
/// Removes all records with a given language, stream, and
/// name from the current instance.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the records to be removed.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the records to be removed.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// records to be removed.
/// </param>
public void RemoveRecords (ushort languageListIndex, ushort streamNumber, string name)
{
for (int i = records.Count - 1; i >= 0; i--) {
DescriptionRecord rec = records[i];
if (rec.LanguageListIndex == languageListIndex &&
rec.StreamNumber == streamNumber &&
rec.Name == name)
records.RemoveAt (i);
}
}
/// <summary>
/// Gets all records with a given language, stream, and any
/// of a collection of names from the current instance.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the records to be retrieved.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the records to be retrieved.
/// </param>
/// <param name="names">
/// A <see cref="T:string[]" /> containing the names of the
/// records to be retrieved.
/// </param>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
/// through the <see cref="DescriptionRecord" /> objects
/// retrieved from the current instance.
/// </returns>
public IEnumerable<DescriptionRecord> GetRecords (ushort languageListIndex, ushort streamNumber, params string[] names)
{
foreach (DescriptionRecord rec in records) {
if (rec.LanguageListIndex != languageListIndex ||
rec.StreamNumber != streamNumber)
continue;
foreach (string name in names)
if (rec.Name == name)
yield return rec;
}
}
/// <summary>
/// Adds a record to the current instance.
/// </summary>
/// <param name="record">
/// A <see cref="DescriptionRecord" /> object to add to the
/// current instance.
/// </param>
public void AddRecord (DescriptionRecord record)
{
records.Add (record);
}
/// <summary>
/// Sets the a collection of records for a given language,
/// stream, and name, removing the existing matching records.
/// </summary>
/// <param name="languageListIndex">
/// A <see cref="ushort" /> value containing the language
/// list index of the records to be added.
/// </param>
/// <param name="streamNumber">
/// A <see cref="ushort" /> value containing the stream
/// number of the records to be added.
/// </param>
/// <param name="name">
/// A <see cref="string" /> object containing the name of the
/// records to be added.
/// </param>
/// <param name="records">
/// A <see cref="T:DescriptionRecord[]" /> containing records
/// to add to the new instance.
/// </param>
/// <remarks>
/// All added entries in <paramref name="records" /> should
/// match <paramref name="languageListIndex" />, <paramref
/// name="streamNumber" /> and <paramref name="name" /> but
/// it is not verified by the method. The records will be
/// added with their own values and not those provided in
/// this method, which are used for removing existing values
/// and determining where to position the new object.
/// </remarks>
public void SetRecords (ushort languageListIndex, ushort streamNumber, string name, params DescriptionRecord[] records)
{
int position = this.records.Count;
for (int i = this.records.Count - 1; i >= 0; i--) {
DescriptionRecord rec = this.records[i];
if (rec.LanguageListIndex == languageListIndex &&
rec.StreamNumber == streamNumber &&
rec.Name == name) {
this.records.RemoveAt (i);
position = i;
}
}
this.records.InsertRange (position, records);
}
#endregion
#region IEnumerable
/// <summary>
/// Gets an enumerator for enumerating through the
/// description records.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.IEnumerator`1" /> for
/// enumerating through the description records.
/// </returns>
public IEnumerator<DescriptionRecord> GetEnumerator ()
{
return records.GetEnumerator ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return records.GetEnumerator ();
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60b732db7695db75682664625a7c9288
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+244
View File
@@ -0,0 +1,244 @@
//
// Object.cs: Provides a basic representation of an ASF object which can be read
// from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This abstract class provides a basic representation of an ASF
/// object which can be read from and written to disk.
/// </summary>
public abstract class Object
{
#region Private Fields
/// <summary>
/// Contains the GUID of the object.
/// </summary>
readonly System.Guid id;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Object" /> by reading the contents from a
/// specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 Object (File file, long position)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
if (position < 0 ||
position > file.Length - 24)
throw new ArgumentOutOfRangeException (nameof (position));
file.Seek (position);
id = file.ReadGuid ();
OriginalSize = file.ReadQWord ();
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Object" /> with a specified GUID.
/// </summary>
/// <param name="guid">
/// A <see cref="System.Guid" /> value containing the GUID to
/// use for the new instance.
/// </param>
protected Object (System.Guid guid)
{
id = guid;
}
#endregion
#region Public Properties
/// <summary>
/// Gets the GUID for the current instance.
/// </summary>
/// <value>
/// A <see cref="System.Guid" /> object containing the GUID
/// of the current instance.
/// </value>
public System.Guid Guid {
get { return id; }
}
/// <summary>
/// Gets the original size of the current instance.
/// </summary>
/// <value>
/// A <see cref="ulong" /> value containing the size of the
/// current instance as it originally appeared on disk.
/// </value>
public ulong OriginalSize { get; private set; }
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
/// <seealso cref="Render(ByteVector)" />
public abstract ByteVector Render ();
#endregion
#region Public Static Methods
/// <summary>
/// Renders a Unicode (wide) string.
/// </summary>
/// <param name="value">
/// A <see cref="string" /> object containing the text to
/// render.
/// </param>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered value.
/// </returns>
public static ByteVector RenderUnicode (string value)
{
ByteVector v = ByteVector.FromString (value, StringType.UTF16LE);
v.Add (RenderWord (0));
return v;
}
/// <summary>
/// Renders a 4-byte DWORD.
/// </summary>
/// <param name="value">
/// A <see cref="uint" /> value containing the DWORD to
/// render.
/// </param>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered value.
/// </returns>
public static ByteVector RenderDWord (uint value)
{
return ByteVector.FromUInt (value, false);
}
/// <summary>
/// Renders a 8-byte QWORD.
/// </summary>
/// <param name="value">
/// A <see cref="ulong" /> value containing the QWORD to
/// render.
/// </param>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered value.
/// </returns>
public static ByteVector RenderQWord (ulong value)
{
return ByteVector.FromULong (value, false);
}
/// <summary>
/// Renders a 2-byte WORD.
/// </summary>
/// <param name="value">
/// A <see cref="ushort" /> value containing the WORD to
/// render.
/// </param>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered value.
/// </returns>
public static ByteVector RenderWord (ushort value)
{
return ByteVector.FromUShort (value, false);
}
#endregion
#region Protected Methods
/// <summary>
/// Renders the current instance as a raw ASF object
/// containing specified data.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the data to
/// contained in the rendered version of the current
/// instance.
/// </param>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
/// <remarks>
/// Child classes implementing <see cref="Render()" /> should
/// render their contents and then send the data through this
/// method to produce the final output.
/// </remarks>
protected ByteVector Render (ByteVector data)
{
ulong length = (ulong)((data != null ? data.Count : 0) + 24);
ByteVector v = id.ToByteArray ();
v.Add (RenderQWord (length));
v.Add (data);
return v;
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de6647e25247fb396826cf683998e204
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+125
View File
@@ -0,0 +1,125 @@
//
// PaddingObject.cs: Provides a representation of an ASF Padding object which
// can be read from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF Padding object which can be read from
/// and written to disk.
/// </summary>
public class PaddingObject : Object
{
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="PaddingObject" /> by reading the contents from a
/// specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or smaller than the minimum size.
/// </exception>
public PaddingObject (File file, long position)
: base (file, position)
{
if (!Guid.Equals (Asf.Guid.AsfPaddingObject))
throw new CorruptFileException ("Object GUID incorrect.");
if (OriginalSize < 24)
throw new CorruptFileException ("Object size too small.");
Size = OriginalSize;
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="PaddingObject" /> of a specified size.
/// </summary>
/// <param name="size">
/// A <see cref="uint" /> value specifying the number of
/// bytes the new instance is to take up on disk.
/// </param>
public PaddingObject (uint size)
: base (Asf.Guid.AsfPaddingObject)
{
Size = size;
}
#endregion
#region Prublic Properties
/// <summary>
/// Gets and sets the number of bytes the current instance
/// will take up on disk.
/// </summary>
/// <value>
/// A <see cref="ulong" /> value containing the size of the
/// current instance on disk.
/// </value>
public ulong Size { get; set; }
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
return Render (new ByteVector ((int)(Size - 24)));
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 57cc0edc0b79695a69d3f10c7d65944f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,226 @@
//
// StreamPropertiesObject.cs: Provides a representation of an ASF Stream
// Properties object which can be read from and written to disk.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an ASF Stream Properties object which can be
/// read from and written to disk.
/// </summary>
public class StreamPropertiesObject : Object
{
#region Private Fields
/// <summary>
/// Contains the time offset of the stream.
/// </summary>
readonly ulong time_offset;
/// <summary>
/// Contains the reserved data.
/// </summary>
readonly uint reserved;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="PaddingObject" /> by reading the contents from a
/// specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 object read from disk does not have the correct GUID
/// or smaller than the minimum size.
/// </exception>
public StreamPropertiesObject (File file, long position)
: base (file, position)
{
if (!Guid.Equals (Asf.Guid.AsfStreamPropertiesObject))
throw new CorruptFileException ("Object GUID incorrect.");
if (OriginalSize < 78)
throw new CorruptFileException ("Object size too small.");
StreamType = file.ReadGuid ();
ErrorCorrectionType = file.ReadGuid ();
time_offset = file.ReadQWord ();
int type_specific_data_length = (int)file.ReadDWord ();
int error_correction_data_length = (int)file.ReadDWord ();
Flags = file.ReadWord ();
reserved = file.ReadDWord ();
TypeSpecificData = file.ReadBlock (type_specific_data_length);
ErrorCorrectionData = file.ReadBlock (error_correction_data_length);
}
#endregion
#region Public Properties
/// <summary>
/// Gets the codec information contained in the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="ICodec" /> object containing the codec
/// information read from <see cref="TypeSpecificData" /> or
/// <see langword="null" /> if the data could not be decoded.
/// </value>
public ICodec Codec {
get {
if (StreamType == Asf.Guid.AsfAudioMedia)
return new Riff.WaveFormatEx (TypeSpecificData, 0);
if (StreamType == Asf.Guid.AsfVideoMedia)
return new Riff.BitmapInfoHeader (TypeSpecificData, 11);
return null;
}
}
/// <summary>
/// Gets the stream type GUID of the current instance.
/// </summary>
/// <summary>
/// A <see cref="System.Guid" /> object containing the stream
/// type GUID of the current instance.
/// </summary>
public System.Guid StreamType { get; }
/// <summary>
/// Gets the error correction type GUID of the current
/// instance.
/// </summary>
/// <summary>
/// A <see cref="System.Guid" /> object containing the error
/// correction type GUID of the current instance.
/// </summary>
public System.Guid ErrorCorrectionType { get; }
/// <summary>
/// Gets the time offset at which the stream described by the
/// current instance begins.
/// </summary>
/// <value>
/// A <see cref="TimeSpan" /> value containing the time
/// offset at which the stream described by the current
/// instance begins.
/// </value>
public TimeSpan TimeOffset {
get { return new TimeSpan ((long)time_offset); }
}
/// <summary>
/// Gets the flags that apply to the current instance.
/// </summary>
/// <value>
/// A <see cref="ushort" /> value containing the flags that
/// apply to the current instance.
/// </value>
public ushort Flags { get; private set; }
/// <summary>
/// Gets the type specific data contained in the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="ByteVector" /> object containing the type
/// specific data contained in the current instance.
/// </value>
/// <remarks>
/// The contents of this value are dependant on the type
/// contained in <see cref="StreamType" />.
/// </remarks>
public ByteVector TypeSpecificData { get; private set; }
/// <summary>
/// Gets the error correction data contained in the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="ByteVector" /> object containing the error
/// correction data contained in the current instance.
/// </value>
/// <remarks>
/// The contents of this value are dependant on the type
/// contained in <see cref="ErrorCorrectionType" />.
/// </remarks>
public ByteVector ErrorCorrectionData { get; private set; }
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
ByteVector output = StreamType.ToByteArray ();
output.Add (ErrorCorrectionType.ToByteArray ());
output.Add (RenderQWord (time_offset));
output.Add (RenderDWord ((uint)TypeSpecificData.Count));
output.Add (RenderDWord ((uint)ErrorCorrectionData.Count));
output.Add (RenderWord (Flags));
output.Add (RenderDWord (reserved));
output.Add (TypeSpecificData);
output.Add (ErrorCorrectionData);
return Render (output);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4fa10f38049b3e2499e7f713daf6b9a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d734ffb9edf169961b4e181c03effffd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+99
View File
@@ -0,0 +1,99 @@
//
// UnknownObject.cs: Provides a simple and generic representation of an object
// not identified by TagLib# so that its contents may be preserved.
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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.Asf
{
/// <summary>
/// This class extends <see cref="Object" /> to provide a
/// representation of an unknown object which can be read from and
/// written to disk.
/// </summary>
public class UnknownObject : Object
{
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="UnknownObject" /> by reading the contents from a
/// specified position in a specified file.
/// </summary>
/// <param name="file">
/// A <see cref="Asf.File" /> object containing the file from
/// which the contents of the new instance are to be read.
/// </param>
/// <param name="position">
/// A <see cref="long" /> value specify at what position to
/// read the object.
/// </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 UnknownObject (File file, long position)
: base (file, position)
{
Data = file.ReadBlock ((int)(OriginalSize - 24));
}
#endregion
#region Public Properties
/// <summary>
/// Gets and sets the data contained in the current instance.
/// </summary>
/// <value>
/// A <see cref="ByteVector" /> object containing the data
/// contained in the current instance.
/// </value>
public ByteVector Data { get; set; }
#endregion
#region Public Methods
/// <summary>
/// Renders the current instance as a raw ASF object.
/// </summary>
/// <returns>
/// A <see cref="ByteVector" /> object containing the
/// rendered version of the current instance.
/// </returns>
public override ByteVector Render ()
{
return Render (Data);
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91aaa7eb7ea3bc7638ef1a9a9bb9f898
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3f2cec2ef40ccecd7ba6d1a7e546abf8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+262
View File
@@ -0,0 +1,262 @@
//
// File.cs:
//
// Author:
// Guy Taylor (s0700260@sms.ed.ac.uk) (thebigguy.co.uk@gmail.com)
//
// Original Source:
// Ogg/File.cs from TagLib-sharp
//
// Copyright (C) 2009 Guy Taylor (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
namespace TagLib.Audible
{
/// <summary>
/// This class extends <see cref="TagLib.File" /> to provide tagging
/// and properties support for Audible inc's aa file format.
/// </summary>
[SupportedMimeType ("audio/x-audible")]
[SupportedMimeType ("taglib/aa", "aa")]
[SupportedMimeType ("taglib/aax", "aax")]
public class File : TagLib.File
{
#region Private Fields
/// <summary>
/// Contains the tags for the file.
/// </summary>
readonly TagLib.Tag tag;
#endregion
#region Public Static Fields
/// <summary>
/// The offset to the tag block.
/// </summary>
public const short TagBlockOffset = 0xBD;
/// <summary>
/// The offset to the end of tag pointer.
/// </summary>
public const short OffsetToEndTagPointer = 0x38;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="File" /> for a specified path in the local file
/// system and specified read style.
/// </summary>
/// <param name="path">
/// A <see cref="string" /> object containing the path of the
/// file to use in the new instance.
/// </param>
/// <param name="propertiesStyle">
/// A <see cref="ReadStyle" /> value specifying at what level
/// of accuracy to read the media properties, or <see
/// cref="ReadStyle.None" /> to ignore the properties.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="path" /> is <see langword="null" />.
/// </exception>
public File (string path, ReadStyle propertiesStyle)
: 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>
/// <exception cref="CorruptFileException">
/// The file is not the write length.
/// </exception>
public File (IFileAbstraction abstraction, ReadStyle propertiesStyle)
: base (abstraction)
{
Mode = AccessMode.Read;
try {
// get the pointer to the end of the tag block
// and calculate the tag block length
Seek (OffsetToEndTagPointer);
int tagLen = ((int)ReadBlock (4).ToUInt (true)) - TagBlockOffset;
// read the whole tag and send to Tag class
Seek (TagBlockOffset);
ByteVector bv = ReadBlock (tagLen);
tag = new Tag (bv);
} finally {
Mode = AccessMode.Closed;
}
// ??
TagTypesOnDisk = TagTypes;
}
/// <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 Methods
/// <summary>
/// Saves the changes made in the current instance to the
/// file it represents.
/// </summary>
/// <remarks>
/// Currently this does not work as there is not enough
/// information about the file format
/// </remarks>
public override void Save ()
{
}
/// <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>
/// <remarks>
/// Currently this does not work as there is not enough
/// information about the file format
/// </remarks>
public override void RemoveTags (TagTypes types)
{
}
/// <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 TagLib.Tag GetTag (TagTypes type, bool create)
{
if (type == TagTypes.AudibleMetadata)
return tag;
return null;
}
#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 TagLib.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; } = new Properties ();
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 006f7fb1983a3a1a89f28703d552cbc6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+320
View File
@@ -0,0 +1,320 @@
//
// Tag.cs:
//
// Author:
// Guy Taylor (s0700260@sms.ed.ac.uk) (thebigguy.co.uk@gmail.com)
//
// Original Source:
// Id3v1/Tag.cs from TagLib-sharp
//
// Copyright (C) 2009 Guy Taylor (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
using System.Collections.Generic;
namespace TagLib.Audible
{
/// <summary>
/// This class extends <see cref="Tag" /> to provide support for
/// reading tags stored in the Audible Metadata format.
/// </summary>
public class Tag : TagLib.Tag
{
#region Private Fields
List<KeyValuePair<string, string>> tags;
#endregion
#region Constructors
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Tag" /> with no contents.
/// </summary>
public Tag ()
{
Clear ();
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Tag" /> 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 FileIdentifier
/// at the given position.
/// </exception>
public Tag (File file, long position)
{
// TODO: can we read from file
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="Tag" /> by reading the contents from a specified
/// <see cref="ByteVector" /> object.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object to read the tag from.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="data" /> is <see langword="null" />.
/// </exception>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> is less than 128 bytes or does
/// not start with FileIdentifier.
/// </exception>
public Tag (ByteVector data)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
Clear ();
Parse (data);
}
#endregion
#region Private Methods
/// <summary>
/// Populates the current instance by parsing the contents of
/// a raw AudibleMetadata tag.
/// </summary>
/// <param name="data">
/// A <see cref="ByteVector" /> object containing the whole tag
/// object
/// </param>
/// <exception cref="CorruptFileException">
/// <paramref name="data" /> is less than 128 bytes or does
/// not start with FileIdentifier.
/// </exception>
void Parse (ByteVector data)
{
string currentKey, currentValue;
int keyLen, valueLen;
try {
do {
keyLen = (int)data.ToUInt (true);
data.RemoveRange (0, 4);
valueLen = (int)data.ToUInt (true);
data.RemoveRange (0, 4);
currentKey = data.ToString (StringType.UTF8, 0, keyLen);
data.RemoveRange (0, keyLen);
currentValue = data.ToString (StringType.UTF8, 0, valueLen);
data.RemoveRange (0, valueLen);
tags.Add (new KeyValuePair<string, string> (currentKey, currentValue));
//StringHandle (currentKey, currentValue);
// if it is not the last item remove the end byte (null terminated)
if (data.Count != 0)
data.RemoveRange (0, 1);
}
while (data.Count >= 4);
} catch (Exception) {
//
}
if (data.Count != 0)
throw new CorruptFileException ();
}
void setTag (string tagName, string value)
{
for (int i = 0; i < tags.Count; i++) {
if (tags[i].Key == tagName)
tags[i] = new KeyValuePair<string, string> (tags[i].Key, value);
}
}
string getTag (string tagName)
{
foreach (KeyValuePair<string, string> tag in tags) {
if (tag.Key == tagName)
return tag.Value;
}
return null;
}
/*
/// <summary>
/// Given a key and value pair it will update the
/// present metadata.
/// </summary>
/// <param name="key">
/// A <see cref="String" /> containing the key.
/// </param>
/// <param name="strValue">
/// A <see cref="String" /> containing the value.
/// </param>
private void StringHandle (String key, String strValue)
{
switch (key)
{
case "title":
title = strValue;
break;
case "author":
artist = strValue;
break;
case "provider":
album = strValue;
break;
}
}
*/
#endregion
#region TagLib.Tag
/// <summary>
/// Gets the tag types contained in the current instance.
/// </summary>
/// <value>
/// Always <see cref="TagTypes.AudibleMetadata" />.
/// </value>
public override TagTypes TagTypes {
get { return TagTypes.AudibleMetadata; }
}
/// <summary>
/// Get or Set the Author Tag
/// </summary>
public string Author {
get {
return getTag ("author");
}
}
/// <summary>
/// Get or Set the Copyright Tag
/// </summary>
public override string Copyright {
get {
return getTag ("copyright");
}
set {
setTag ("copyright", value);
}
}
/// <summary>
/// Get or Set the Description Tag
/// </summary>
public override string Description {
get { return getTag ("description"); }
}
/// <summary>
/// Get or Set the Narrator Tag
/// </summary>
public string Narrator {
get {
return getTag ("narrator");
}
}
/// <summary>
/// Gets 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>
public override string Title {
get {
return getTag ("title");
}
}
/// <summary>
/// Gets the album for the media described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="string" /> object containing the album for
/// the media described by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
public override string Album {
get {
return getTag ("provider");
//return string.IsNullOrEmpty (album) ?
// null : album;
}
}
/// <summary>
/// Gets the album artist for the media described by the
/// current instance.
/// </summary>
/// <value>
/// A <see cref="T:string[]" /> object containing a single
/// artist described by the current instance or <see
/// langword="null" /> if no value is present.
/// </value>
public override string[] AlbumArtists {
get {
var artist = getTag ("provider");
return string.IsNullOrEmpty (artist) ?
null : new [] { artist };
}
}
/// <summary>
/// Clears the values stored in the current instance.
/// </summary>
public override void Clear ()
{
tags = new List<KeyValuePair<string, string>> ();
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c399f58c554dc5479a139a58c8a72b80
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fd4901c34711c7eaba954926fa92969f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+273
View File
@@ -0,0 +1,273 @@
//
// ByteVectorList.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
// Aaron Bockover (abockover@novell.com)
//
// Original Source:
// tbytevectorlist.cpp from TagLib
//
// Copyright (C) 2005-2007 Brian Nickel
// Copyright (C) 2006 Novell, Inc.
// Copyright (C) 2002,2003 Scott Wheeler (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TagLib
{
/// <summary>
/// This class extends <see cref="T:TagLib.ListBase`1"/> to represent
/// a collection of <see cref="ByteVector" /> objects.
/// </summary>
[ComVisible (false)]
public class ByteVectorCollection : ListBase<ByteVector>
{
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ByteVectorCollection" /> with no contents.
/// </summary>
public ByteVectorCollection ()
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ByteVectorCollection" /> with specified contents.
/// </summary>
/// <param name="list">
/// A <see cref="T:System.Collections.Generic.IEnumerable`1"
/// /> containing <see cref="ByteVector" /> objects to add to
/// the current instance.
/// </param>
public ByteVectorCollection (IEnumerable<ByteVector> list)
{
if (list != null)
Add (list);
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="ByteVectorCollection" /> with specified contents.
/// </summary>
/// <param name="list">
/// A <see cref="T:ByteVector[]" /> containing objects to add to
/// the current instance.
/// </param>
public ByteVectorCollection (params ByteVector[] list)
{
if (list != null)
Add (list);
}
/// <summary>
/// Performs a sorted insert of a <see cref="ByteVector" />
/// object into the current instance, optionally only adding
/// if the item is unique.
/// </summary>
/// <param name="item">
/// A <see cref="ByteVector" /> object to add to the current
/// instance.
/// </param>
/// <param name="unique">
/// If <see langword="true" />, the object will only be added
/// if an identical value is not already contained in the
/// current instance.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="item" /> is <see langword="null" />.
/// </exception>
public override void SortedInsert (ByteVector item, bool unique)
{
if (item == null)
throw new ArgumentNullException (nameof (item));
// FIXME: This is not used, but if it is a faster
// method could be used.
int i = 0;
for (; i < Count; i++) {
if (item == this[i] && unique)
return;
if (item >= this[i])
break;
}
Insert (i + 1, item);
}
/// <summary>
/// Converts the current instance to a <see cref="ByteVector"
/// /> by joining the contents together with a specified
/// separator.
/// </summary>
/// <param name="separator">
/// A <see cref="ByteVector"/> object to separate the
/// combined contents of the current instance.
/// </param>
/// <returns>
/// A new <see cref="ByteVector"/> object containing the
/// joined contents of the current instance.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="separator" /> is <see langword="null" />.
/// </exception>
public ByteVector ToByteVector (ByteVector separator)
{
if (separator == null)
throw new ArgumentNullException (nameof (separator));
var vector = new ByteVector ();
for (int i = 0; i < Count; i++) {
if (i != 0 && separator.Count > 0)
vector.Add (separator);
vector.Add (this[i]);
}
return vector;
}
/// <summary>
/// Splits a <see cref="ByteVector" /> object using a
/// pattern.
/// </summary>
/// <param name="vector">
/// A <see cref="ByteVector"/> object to split.
/// </param>
/// <param name="pattern">
/// A <see cref="ByteVector"/> object to use to split
/// <paramref name="vector" /> with.
/// </param>
/// <param name="byteAlign">
/// A <see cref="int" /> specifying the byte align to use
/// when splitting. In order to split when a pattern is
/// encountered, the index at which it is found must be
/// divisible by <paramref name="byteAlign" />.
/// </param>
/// <param name="max">
/// A <see cref="int" /> value specifying the maximum number
/// of objects to return, or zero to not to limit the number.
/// If that that number is reached, the last value will
/// contain the remainder of the file even if it contains
/// more instances of <paramref name="pattern" />.
/// </param>
/// <returns>
/// A <see cref="ByteVectorCollection" /> object containing
/// the split contents of the current instance.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="vector" /> or <paramref name="pattern" />
/// is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="byteAlign" /> is less than 1.
/// </exception>
public static ByteVectorCollection Split (ByteVector vector, ByteVector pattern, int byteAlign, int max)
{
if (vector == null)
throw new ArgumentNullException (nameof (vector));
if (pattern == null)
throw new ArgumentNullException (nameof (pattern));
if (byteAlign < 1)
throw new ArgumentOutOfRangeException (nameof (byteAlign), "byteAlign must be at least 1.");
var list = new ByteVectorCollection ();
int previous_offset = 0;
for (int offset = vector.Find (pattern, 0, byteAlign);
offset != -1 && (max < 1 ||
max > list.Count + 1);
offset = vector.Find (pattern,
offset + pattern.Count, byteAlign)) {
list.Add (vector.Mid (previous_offset,
offset - previous_offset));
previous_offset = offset + pattern.Count;
}
if (previous_offset < vector.Count)
list.Add (vector.Mid (previous_offset,
vector.Count - previous_offset));
return list;
}
/// <summary>
/// Splits a <see cref="ByteVector" /> object using a
/// pattern.
/// </summary>
/// <param name="vector">
/// A <see cref="ByteVector"/> object to split.
/// </param>
/// <param name="pattern">
/// A <see cref="ByteVector"/> object to use to split
/// <paramref name="vector" /> with.
/// </param>
/// <param name="byteAlign">
/// A <see cref="int" /> specifying the byte align to use
/// when splitting. In order to split when a pattern is
/// encountered, the index at which it is found must be
/// divisible by <paramref name="byteAlign" />.
/// </param>
/// <returns>
/// A <see cref="ByteVectorCollection" /> object containing
/// the split contents of the current instance.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="vector" /> or <paramref name="pattern" />
/// is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="byteAlign" /> is less than 1.
/// </exception>
public static ByteVectorCollection Split (ByteVector vector, ByteVector pattern, int byteAlign)
{
return Split (vector, pattern, byteAlign, 0);
}
/// <summary>
/// Splits a <see cref="ByteVector" /> object using a
/// pattern.
/// </summary>
/// <param name="vector">
/// A <see cref="ByteVector"/> object to split.
/// </param>
/// <param name="pattern">
/// A <see cref="ByteVector"/> object to use to split
/// <paramref name="vector" /> with.
/// </param>
/// <returns>
/// A <see cref="ByteVectorCollection" /> object containing
/// the split contents of the current instance.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="vector" /> or <paramref name="pattern" />
/// is <see langword="null" />.
/// </exception>
public static ByteVectorCollection Split (ByteVector vector, ByteVector pattern)
{
return Split (vector, pattern, 1);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13ce76148d2aedf098df14fcf5195df7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fcfda10f765f9bf0b754fb38b66878e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+167
View File
@@ -0,0 +1,167 @@
//
// CorruptFileException.cs:
//
// Author:
// Aaron Bockover (abockover@novell.com)
//
// Original Source:
// Entagged#
//
// Copyright (C) 2006 Novell, Inc.
//
// 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.Runtime.Serialization;
namespace TagLib
{
/// <summary>
/// This class extends <see cref="Exception" /> and is used to
/// indicate that a file or tag is corrupt.
/// </summary>
/// <remarks>
/// This exception will be thrown if invalid data interferes with the
/// reading of the file or tag. One common example is in the (legal)
/// downloading of media files with BitTorrent, in which case large
/// portions of the file will contain zeroed bytes.
/// </remarks>
/// <example>
/// <para>Catching an exception when creating a <see
/// cref="File" />.</para>
/// <code lang="C#">
/// using System;
/// using TagLib;
///
/// public class ExceptionTest
/// {
/// public static void Main ()
/// {
/// try {
/// File file = File.Create ("partial.mp3"); // Partial download.
/// } catch (CorruptFileException e) {
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
/// }
/// }
/// }
/// </code>
/// <code lang="C++">
/// #using &lt;System.dll>
/// #using &lt;taglib-sharp.dll>
///
/// using System;
/// using TagLib;
///
/// void main ()
/// {
/// try {
/// File file = File::Create ("partial.mp3"); // Partial download.
/// } catch (CorruptFileException^ e) {
/// Console::WriteLine ("That file is corrupt: {0}", e);
/// }
/// }
/// </code>
/// <code lang="VB">
/// Imports System
/// Imports TagLib
///
/// Public Class ExceptionTest
/// Public Shared Sub Main ()
/// Try
/// file As File = File.Create ("partial.mp3") ' Partial download.
/// Catch e As CorruptFileException
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
/// End Try
/// End Sub
/// End Class
/// </code>
/// <code lang="Boo">
/// import System
/// import TagLib
///
/// try:
/// file As File = File.Create ("partial.mp3") # Partial download.
/// catch e as CorruptFileException:
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
/// </code>
/// </example>
[Serializable]
public class CorruptFileException : Exception
{
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="CorruptFileException" /> with a specified
/// message.
/// </summary>
/// <param name="message">
/// A <see cref="string" /> containing a message explaining
/// the reason for the exception.
/// </param>
public CorruptFileException (string message) : base (message)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="CorruptFileException" /> with the default
/// values.
/// </summary>
public CorruptFileException ()
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="CorruptFileException" /> with a specified
/// message containing a specified exception.
/// </summary>
/// <param name="message">
/// A <see cref="string" /> containing a message explaining
/// the reason for the exception.
/// </param>
/// <param name="innerException">
/// A <see cref="Exception" /> object to be contained in the
/// new exception. For example, previously caught exception.
/// </param>
public CorruptFileException (string message, Exception innerException)
: base (message, innerException)
{
}
/// <summary>
/// Constructs and initializes a new instance of <see
/// cref="CorruptFileException" /> 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="CorruptFileException" /> implements the <see
/// cref="ISerializable" /> interface.
/// </remarks>
protected CorruptFileException (SerializationInfo info, StreamingContext context)
: base (info, context)
{
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b3d4c56812fd17788a353ae122bb5c53
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+137
View File
@@ -0,0 +1,137 @@
//
// Debugger.cs:
//
// Author:
// Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2006-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
{
static class Debugger
{
public delegate void DebugMessageSentHandler (string message);
public static event DebugMessageSentHandler DebugMessageSent;
public static void Debug (string message)
{
DebugMessageSent?.Invoke (message);
}
public static void DumpHex (ByteVector data)
{
DumpHex (data.Data);
}
public static void DumpHex (byte[] data)
{
int cols = 16;
int rows = data.Length / cols + (data.Length % cols != 0 ? 1 : 0);
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (row == rows - 1 && data.Length % cols != 0 && col >= data.Length % cols)
Console.Write (" ");
else
Console.Write (" {0:x2}", data[row * cols + col]);
}
Console.Write (" | ");
for (int col = 0; col < cols; col++) {
if (row == rows - 1 && data.Length % cols != 0 && col >= data.Length % cols)
Console.Write (" ");
else
WriteByte2 (data[row * cols + col]);
}
Console.WriteLine ();
}
Console.WriteLine ();
}
static void WriteByte2 (byte data)
{
foreach (char c in allowed)
if (c == data) {
Console.Write (c);
return;
}
Console.Write (".");
}
static readonly string allowed = "0123456789abcdefghijklmnopqr" +
"stuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~!@#$%^&*()_+-={}" +
"[];:'\",.<>?/\\|";
static readonly Dictionary<object, Dictionary<object, DebugTimeData>>
debug_times = new Dictionary<object, Dictionary<object, DebugTimeData>> ();
public static void AddDebugTime (object o1, object o2, DateTime start)
{
var data = new DebugTimeData (DateTime.Now - start, 1);
if (debug_times.ContainsKey (o1) && debug_times[o1].ContainsKey (o2)) {
data.time += debug_times[o1][o2].time;
data.occurances += debug_times[o1][o2].occurances;
}
if (!debug_times.ContainsKey (o1))
debug_times.Add (o1, new Dictionary<object, DebugTimeData> ());
if (!debug_times[o1].ContainsKey (o2))
debug_times[o1].Add (o2, data);
else
debug_times[o1][o2] = data;
}
public static void DumpDebugTime (object o1)
{
Console.WriteLine (o1.ToString ());
if (!debug_times.ContainsKey (o1))
return;
foreach (var pair in debug_times[o1]) {
Console.WriteLine (" {0}", pair.Key);
Console.WriteLine (" Objects: {0}", pair.Value.time);
Console.WriteLine (" Total: {0}", pair.Value.occurances);
Console.WriteLine (" Average: {0}", new TimeSpan (pair.Value.time.Ticks / pair.Value.occurances));
Console.WriteLine ();
}
debug_times.Remove (o1);
}
struct DebugTimeData
{
public TimeSpan time;
public long occurances;
public DebugTimeData (TimeSpan time, int occurances)
{
this.time = time;
this.occurances = occurances;
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 43d149150f84518598c6d2c5500d9244
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 90815a5b58495074885ff707abaacda7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+411
View File
@@ -0,0 +1,411 @@
//
// File.cs: Provides tagging and properties support for the DSD (Direct Stream Digital) DSF
// file Format.
//
// Author:
// Helmut Wahrmann
//
// Copyright (C) 2014 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;
using TagLib.Id3v2;
namespace TagLib.Dsf
{
/// <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/dsf", "dsf")]
[SupportedMimeType ("audio/x-dsf")]
[SupportedMimeType ("audio/dsf")]
[SupportedMimeType ("sound/dsf")]
[SupportedMimeType ("application/x-dsf")]
public class File : TagLib.File
{
#region Private Fields
/// <summary>
/// Contains the address of the DSF header block.
/// </summary>
ByteVector header_block;
/// <summary>
/// Contains the Id3v2 tag.
/// </summary>
Id3v2.Tag tag;
/// <summary>
/// Contains the media properties.
/// </summary>
Properties properties;
/// <summary>
/// Contains the size of the DSF File
/// </summary>
readonly uint dsf_size;
/// <summary>
/// Contains the start position of the Tag
/// </summary>
long tag_start;
/// <summary>
/// Contains the end position of the Tag
/// </summary>
long tag_end;
#endregion
#region Public Static Fields
/// <summary>
/// The identifier used to recognize a DSF file.
/// </summary>
/// <value>
/// "DSD "
/// </value>
public static readonly ReadOnlyByteVector FileIdentifier = "DSD ";
/// <summary>
/// The identifier used to recognize a Format chunk.
/// </summary>
/// <value>
/// "fmt "
/// </value>
public static readonly ReadOnlyByteVector FormatIdentifier = "fmt ";
/// <summary>
/// The identifier used to recognize a DSF ID3 chunk.
/// </summary>
/// <value>
/// "ID3 "
/// </value>
public static readonly ReadOnlyByteVector ID3Identifier = "ID3";
#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 dsf_size, out tag_start, out 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 {
long original_tag_length = tag_end - tag_start;
ByteVector data = new ByteVector ();
if (tag == null) {
// The tag has been removed
RemoveBlock (tag_start, original_tag_length);
Insert (ByteVector.FromULong (0, false), 20, 8);
} else {
data = tag.Render ();
// If tagging info cannot be found, place it at
// the end of the file.
if (tag_start == 0 || tag_end < tag_start) {
tag_start = tag_end = Length;
// Update the New Tag start
Insert (ByteVector.FromULong ((ulong)(tag_start), false), 20, 8);
}
// Insert the tagging data.
Insert (data, tag_start, data.Count);
}
long length = dsf_size + data.Count - original_tag_length;
// If the data size changed update the dsf size.
if (data.Count - original_tag_length != 0 && tag_start <= dsf_size) {
Insert (ByteVector.FromULong ((ulong)(length), false), 12, 8);
}
// 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>
/// Reads the contents of the current instance determining
/// the size of the dsf 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="dsf_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 dsf_size, out long tag_start, out long tag_end)
{
Seek (0);
if (ReadBlock (4) != FileIdentifier)
throw new CorruptFileException ("File does not begin with DSF identifier");
Seek (12);
dsf_size = ReadBlock (8).ToUInt (false);
tag_start = (long)ReadBlock (8).ToULong (false);
tag_end = -1;
// Get the properties of the file
if (header_block == null && style != ReadStyle.None) {
long fmt_chunk_pos = Find (FormatIdentifier, 0);
if (fmt_chunk_pos == -1) {
throw new CorruptFileException ("No Format chunk available in DSF file.");
}
Seek (fmt_chunk_pos);
header_block = ReadBlock ((int)StreamHeader.Size);
var header = new StreamHeader (header_block, dsf_size);
properties = new Properties (TimeSpan.Zero, header);
}
// Now position to the ID3 chunk, which we read before
if (tag_start > 0) {
Seek (tag_start);
if (ReadBlock (3) == ID3Identifier) {
if (read_tags && tag == null) {
tag = new Id3v2.Tag (this, tag_start, style);
}
// Get the length of the tag out of the ID3 chunk
Seek (tag_start + 6);
uint tag_size = SynchData.ToUInt (ReadBlock (4)) + 10;
InvariantStartPosition = tag_start;
tag_end = InvariantEndPosition = tag_start + tag_size;
}
}
}
#endregion
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b09427e5619eec8580e4b303b312ac9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+292
View File
@@ -0,0 +1,292 @@
//
// StreamHeader.cs: Provides tagging and properties support for the DSD
// (Direct Stream Digital) DSF properties.
//
// Author:
// Helmut Wahrmann
//
// Copyright (C) 2014 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.Dsf
{
/// <summary>
/// This struct implements <see cref="IAudioCodec" /> to provide
/// support for reading DSF stream properties.
/// </summary>
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
{
#region Private Fields
/// <summary>
/// Contains the version.
/// </summary>
/// <remarks>
/// This value is stored in bytes (12-15).
/// Currently only value of 1 is valid.
/// </remarks>
readonly ushort version;
/// <summary>
/// The Format Id.
/// </summary>
/// <remarks>
/// This value is stored in bytes (16-19).
/// 0: DSD Raw
/// </remarks>
readonly ushort format_id;
/// <summary>
/// The Channel Type.
/// </summary>
/// <remarks>
/// This value is stored in bytes (20-23).
/// 1: mono
/// 2:stereo
/// 3:3 channels
/// 4: quad
/// 5: 4 channels
/// 6: 5 channels
/// 7: 5.1 channels
/// </remarks>
readonly ushort channel_type;
/// <summary>
/// Contains the number of channels.
/// </summary>
/// <remarks>
/// This value is stored in bytes (24-27).
/// 1 is monophonic, 2 is stereo, 4 means 4 channels, etc..
/// up to 6 channels may be represented
/// </remarks>
readonly ushort channels;
/// <summary>
/// Contains the sample rate.
/// </summary>
/// <remarks>
/// This value is stored in bytes (28-31).
/// the sample rate at which the sound is to be played back,
/// in Hz: 2822400, 5644800
/// </remarks>
readonly ulong sample_rate;
/// <summary>
/// Contains the number of bits per sample.
/// </summary>
/// <remarks>
/// This value is stored in bytes (32-35).
/// It can be any number from 1 to 8.
/// </remarks>
readonly ushort bits_per_sample;
/// <summary>
/// Contains the number of sample frames per channel.
/// </summary>
/// <remarks>
/// This value is stored in bytes (36-43).
/// </remarks>
readonly ulong sample_count;
/// <summary>
/// Contains the Block size per channel.
/// </summary>
/// <remarks>
/// This value is stored in bytes (44-47).
/// Always: 4096
/// </remarks>
readonly uint channel_blksize;
/// <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 DSF Format chunk
/// </summary>
public const uint Size = 52;
/// <summary>
/// The identifier used to recognize a DSF file.
/// Altough an DSF file start with "DSD ", we're interested
/// in the Format chunk only, which contains the properties we need.
/// </summary>
/// <value>
/// "fmt "
/// </value>
public static readonly ReadOnlyByteVector FileIdentifier = "fmt ";
#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
/// DSF 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 12 bytes contain the Format chunk identifier "fmt "
// And the size of the format chunk, which is always 52
version = data.Mid (12, 4).ToUShort (false);
format_id = data.Mid (16, 4).ToUShort (false);
channel_type = data.Mid (20, 4).ToUShort (false);
channels = data.Mid (24, 4).ToUShort (false);
sample_rate = data.Mid (28, 4).ToULong (false);
bits_per_sample = data.Mid (32, 4).ToUShort (false);
sample_count = data.Mid (36, 8).ToULong (false);
channel_blksize = data.Mid (44, 4).ToUShort (false);
}
#endregion
#region Public Properties
/// <summary>
/// Gets the duration of the media represented by the current
/// instance.
/// </summary>
/// <value>
/// A <see cref="TimeSpan" /> containing the duration of the
/// media represented by the current instance.
/// </value>
public TimeSpan Duration {
get {
if (sample_rate <= 0 || sample_count <= 0)
return TimeSpan.Zero;
return TimeSpan.FromSeconds (sample_count / (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 "DSF 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
}
}
Loaded 100 of 2025 files, more files were not shown because too many files have changed in this diff. Show more