mirror of
https://github.com/chibicitiberiu/libflac-sharp
synced 2024-02-24 04:53:30 +00:00
Implemented metadata, crc, part of frame and bitreader.
This commit is contained in:
parent
8c2f59c549
commit
1730d84b33
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
85
Flac/Flac.Test/Flac.Test.csproj
Normal file
85
Flac/Flac.Test/Flac.Test.csproj
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{1576AB6D-F8F4-42FC-BDC7-67D08648AEA6}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Flac.Test</RootNamespace>
|
||||
<AssemblyName>Flac.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
36
Flac/Flac.Test/Properties/AssemblyInfo.cs
Normal file
36
Flac/Flac.Test/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Flac.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Flac.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("2376dc52-6d6f-40ac-a34c-44a1523983ac")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
28
Flac/Flac.sln
Normal file
28
Flac/Flac.sln
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flac", "Flac\Flac.csproj", "{ECB7B567-6A67-43F4-89CA-64E5D9F07B97}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flac.Test", "Flac.Test\Flac.Test.csproj", "{1576AB6D-F8F4-42FC-BDC7-67D08648AEA6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{ECB7B567-6A67-43F4-89CA-64E5D9F07B97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ECB7B567-6A67-43F4-89CA-64E5D9F07B97}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ECB7B567-6A67-43F4-89CA-64E5D9F07B97}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ECB7B567-6A67-43F4-89CA-64E5D9F07B97}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1576AB6D-F8F4-42FC-BDC7-67D08648AEA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1576AB6D-F8F4-42FC-BDC7-67D08648AEA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1576AB6D-F8F4-42FC-BDC7-67D08648AEA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1576AB6D-F8F4-42FC-BDC7-67D08648AEA6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
53
Flac/Flac/ChannelData.cs
Normal file
53
Flac/Flac/ChannelData.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using Flac.Frame;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// FLAC channel data.
|
||||
/// This class holds the data for the channels in a FLAC frame.
|
||||
/// </summary>
|
||||
public class ChannelData
|
||||
{
|
||||
/// <summary>
|
||||
/// The output signal.
|
||||
/// </summary>
|
||||
public int[] Output
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The risidual signal.
|
||||
/// </summary>
|
||||
public int[] Residual
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Entropy signal.
|
||||
/// </summary>
|
||||
public EntropyPartitionedRiceContents PartitionedRiceContents
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of ChannelData
|
||||
/// </summary>
|
||||
/// <param name="size">The block size</param>
|
||||
public ChannelData(int size)
|
||||
{
|
||||
Output = new int[size];
|
||||
Residual = new int[size];
|
||||
PartitionedRiceContents = new EntropyPartitionedRiceContents();
|
||||
}
|
||||
}
|
||||
}
|
76
Flac/Flac/Flac.csproj
Normal file
76
Flac/Flac/Flac.csproj
Normal file
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{ECB7B567-6A67-43F4-89CA-64E5D9F07B97}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Flac</RootNamespace>
|
||||
<AssemblyName>Flac</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChannelData.cs" />
|
||||
<Compile Include="Frame\BadHeaderException.cs" />
|
||||
<Compile Include="Frame\Channel.cs" />
|
||||
<Compile Include="Frame\ChannelConstant.cs" />
|
||||
<Compile Include="Frame\ChannelFixed.cs" />
|
||||
<Compile Include="Frame\EntropyCodingMethod.cs" />
|
||||
<Compile Include="Frame\EntropyPartitionedRice.cs" />
|
||||
<Compile Include="Frame\EntropyPartitionedRiceContents.cs" />
|
||||
<Compile Include="Frame\Header.cs" />
|
||||
<Compile Include="IO\BitReader.cs" />
|
||||
<Compile Include="Metadata\Application.cs" />
|
||||
<Compile Include="Metadata\CueIndex.cs" />
|
||||
<Compile Include="Metadata\CueSheet.cs" />
|
||||
<Compile Include="Metadata\CueTrack.cs" />
|
||||
<Compile Include="Metadata\Metadata.cs" />
|
||||
<Compile Include="Metadata\Padding.cs" />
|
||||
<Compile Include="Metadata\Picture.cs" />
|
||||
<Compile Include="Metadata\SeekPoint.cs" />
|
||||
<Compile Include="Metadata\SeekTable.cs" />
|
||||
<Compile Include="Metadata\StreamInfo.cs" />
|
||||
<Compile Include="Metadata\Unknown.cs" />
|
||||
<Compile Include="Metadata\ValidationException.cs" />
|
||||
<Compile Include="Metadata\VorbisComment.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Util\CRC16.cs" />
|
||||
<Compile Include="Util\CRC8.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
42
Flac/Flac/Frame/BadHeaderException.cs
Normal file
42
Flac/Flac/Frame/BadHeaderException.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
/// <summary>
|
||||
/// Bad header exception
|
||||
/// </summary>
|
||||
public class BadHeaderException : IOException
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of bad header exception.
|
||||
/// </summary>
|
||||
public BadHeaderException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of bad header exception with specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message</param>
|
||||
public BadHeaderException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of bad header exception with specified message
|
||||
/// and a reference to the inner exception that is the cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The message</param>
|
||||
/// <param name="innerException">The inner exception</param>
|
||||
public BadHeaderException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
44
Flac/Flac/Frame/Channel.cs
Normal file
44
Flac/Flac/Frame/Channel.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for FLAC subframe (channel) classes.
|
||||
/// </summary>
|
||||
public abstract class Channel
|
||||
{
|
||||
#region Constants
|
||||
protected const int TypeLength = 2;
|
||||
protected const int PartitionedRiceOrderLength = 4;
|
||||
#endregion
|
||||
|
||||
protected enum EntropyCodingMethod
|
||||
{
|
||||
PartitionedRice = 0
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The FLAC Frame Header.
|
||||
/// </summary>
|
||||
protected Header Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of wasted bits in the frame.
|
||||
/// </summary>
|
||||
public int WastedBits { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of channel.
|
||||
/// </summary>
|
||||
/// <param name="header">The FLAC Frame Header.</param>
|
||||
/// <param name="wastedBits">The number of wasted bits in the frame.</param>
|
||||
protected Channel(Header header, int wastedBits)
|
||||
{
|
||||
Header = header;
|
||||
WastedBits = wastedBits;
|
||||
}
|
||||
}
|
||||
}
|
39
Flac/Flac/Frame/ChannelConstant.cs
Normal file
39
Flac/Flac/Frame/ChannelConstant.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
/// <summary>
|
||||
/// FLAC constant subframe (channel) data.
|
||||
/// This class represents a FLAC subframe (channel) for a Constant data
|
||||
/// </summary>
|
||||
public class ChannelConstant : Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// The constant signal value.
|
||||
/// </summary>
|
||||
private int value;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of ChannelConstant
|
||||
/// </summary>
|
||||
/// <param name="read">The bit reader</param>
|
||||
/// <param name="header">The FLAC Frame Header</param>
|
||||
/// <param name="channelData">The decoded channel data (output)</param>
|
||||
/// <param name="bps">The bits-per-second</param>
|
||||
/// <param name="wastedBits">The bits wasted in the frame</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public ChannelConstant(BitReader read, Header header, ChannelData channelData, int bps, int wastedBits)
|
||||
: base(header, wastedBits)
|
||||
{
|
||||
value = (int)read.ReadRawUInt32(bps);
|
||||
|
||||
// Decode the subframe
|
||||
for (int i = 0; i < header.BlockSize; i++)
|
||||
channelData.Output[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
76
Flac/Flac/Frame/ChannelFixed.cs
Normal file
76
Flac/Flac/Frame/ChannelFixed.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
/// <summary>
|
||||
/// Fixed FLAC subframe (channel).
|
||||
/// </summary>
|
||||
public class ChannelFixed : Channel
|
||||
{
|
||||
private const int MaxFixedOrder = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The residual coding method.
|
||||
/// </summary>
|
||||
private Frame.EntropyCodingMethod entropyCodingMethod;
|
||||
|
||||
/// <summary>
|
||||
/// The polynomial order.
|
||||
/// </summary>
|
||||
private int order;
|
||||
|
||||
/// <summary>
|
||||
/// Warmup samples to prime the predictor, length == order.
|
||||
/// </summary>
|
||||
private int[] warmup = new int[MaxFixedOrder];
|
||||
|
||||
/// <summary>
|
||||
/// The residual signal, length == (blocksize minus order) samples.
|
||||
/// </summary>
|
||||
private int[] residual;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of ChannelConstant
|
||||
/// </summary>
|
||||
/// <param name="read">The bit reader</param>
|
||||
/// <param name="header">The FLAC Frame Header</param>
|
||||
/// <param name="channelData">The decoded channel data (output)</param>
|
||||
/// <param name="bps">The bits-per-second</param>
|
||||
/// <param name="wastedBits">The bits wasted in the frame</param>
|
||||
/// <param name="order">The predicate order</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public ChannelFixed(BitReader read, Header header, ChannelData channelData, int bps, int wastedBits, int order)
|
||||
: base(header, wastedBits)
|
||||
{
|
||||
residual = channelData.Residual;
|
||||
this.order = order;
|
||||
|
||||
// Read warmup samples
|
||||
for (int u = 0; u < order; u++)
|
||||
warmup[u] = (int)read.ReadRawUInt32(bps);
|
||||
|
||||
// Read entropy coding method info
|
||||
int type = (int)read.ReadRawUInt32(TypeLength);
|
||||
EntropyPartitionedRice pr;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case (int)EntropyCodingMethod.PartitionedRice:
|
||||
pr = new EntropyPartitionedRice();
|
||||
entropyCodingMethod = pr;
|
||||
pr.Order = (int)read.ReadRawUInt32(PartitionedRiceOrderLength);
|
||||
pr.Contents = channelData.PartitionedRiceContents;
|
||||
pr.ReadResidual(read, order, pr.Order, header, channelData.Residual);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IOException("Unparseable stream!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Flac/Flac/Frame/EntropyCodingMethod.cs
Normal file
11
Flac/Flac/Frame/EntropyCodingMethod.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
public interface EntropyCodingMethod
|
||||
{
|
||||
}
|
||||
}
|
86
Flac/Flac/Frame/EntropyPartitionedRice.cs
Normal file
86
Flac/Flac/Frame/EntropyPartitionedRice.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
/// <summary>
|
||||
/// This class holds the Entropy Partitioned Rice contents.
|
||||
/// </summary>
|
||||
public class EntropyPartitionedRice : EntropyCodingMethod
|
||||
{
|
||||
#region Constants
|
||||
private const int ParameterLength = 4; // bits
|
||||
private const int RawLength = 5; // bits
|
||||
private const UInt32 EscapeParameter = 15;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The partition order, i.e. # of contexts = 2 ^ order.
|
||||
/// </summary>
|
||||
public int Order { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The context's Rice parameters and/or raw bits.
|
||||
/// </summary>
|
||||
public EntropyPartitionedRiceContents Contents
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read compressed signal residual data.
|
||||
/// </summary>
|
||||
/// <param name="read">The bit reader</param>
|
||||
/// <param name="predictorOrder">The predicate order</param>
|
||||
/// <param name="partitionOrder">The partition order</param>
|
||||
/// <param name="header">The FLAC Frame Header</param>
|
||||
/// <param name="residual">The residual signal (output)</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public void ReadResidual(BitReader read, int predictorOrder, int partitionOrder, Header header, int[] residual)
|
||||
{
|
||||
int sample = 0;
|
||||
int partitions = 1 << partitionOrder;
|
||||
|
||||
int partitionSamples;
|
||||
if (partitionOrder > 0)
|
||||
partitionSamples = (header.BlockSize >> partitionOrder);
|
||||
else
|
||||
partitionSamples = (header.BlockSize - predictorOrder);
|
||||
|
||||
Contents = new EntropyPartitionedRiceContents();
|
||||
Contents.EnsureSize(Math.Max(6, partitionOrder));
|
||||
Contents.Parameters = new int[partitions]; // why allocate again?
|
||||
|
||||
for (int partition = 0; partition < partitions; partition++)
|
||||
{
|
||||
int riceParameter = (int)read.ReadRawUInt32(ParameterLength);
|
||||
Contents.Parameters[partition] = riceParameter;
|
||||
|
||||
if (riceParameter < EscapeParameter)
|
||||
{
|
||||
int u = (partitionOrder == 0 || partition > 0) ?
|
||||
(partitionSamples) :
|
||||
(partitionSamples - predictorOrder);
|
||||
|
||||
read.ReadRiceSignedBlock(residual, sample, u, riceParameter);
|
||||
sample += u;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
riceParameter = (int)read.ReadRawUInt32(RawLength);
|
||||
Contents.RawBits[partition] = riceParameter;
|
||||
|
||||
int u = (partitionOrder == 0 || partition > 0) ? (0) : (predictorOrder);
|
||||
|
||||
for (; u < partitionSamples; u++, sample++)
|
||||
residual[sample] = (int)read.ReadRawUInt32(riceParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
Flac/Flac/Frame/EntropyPartitionedRiceContents.cs
Normal file
34
Flac/Flac/Frame/EntropyPartitionedRiceContents.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
public class EntropyPartitionedRiceContents
|
||||
{
|
||||
public int[] Parameters { get; set; }
|
||||
public int[] RawBits { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The capacity of the parameters and raw_bits arrays specified as an order.
|
||||
/// i.e. the number of array elements allocated is 2 ^ capacity_by_order.
|
||||
/// </summary>
|
||||
private int capacityByOrder = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Ensure enough menory has been allocated.
|
||||
/// </summary>
|
||||
/// <param name="maxPartitionOrder">The maximum partition order</param>
|
||||
public void EnsureSize(int maxPartitionOrder)
|
||||
{
|
||||
if (capacityByOrder >= maxPartitionOrder)
|
||||
return;
|
||||
|
||||
Parameters = new int[(1 << maxPartitionOrder)];
|
||||
RawBits = new int[(1 << maxPartitionOrder)];
|
||||
|
||||
capacityByOrder = maxPartitionOrder;
|
||||
}
|
||||
}
|
||||
}
|
70
Flac/Flac/Frame/Header.cs
Normal file
70
Flac/Flac/Frame/Header.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using Flac.IO;
|
||||
using Flac.Metadata;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Frame
|
||||
{
|
||||
/// <summary>
|
||||
/// Frame header class.
|
||||
/// </summary>
|
||||
public class Header
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the number of samples per subframe.
|
||||
/// </summary>
|
||||
public int BlockSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sample rate in Hz.
|
||||
/// </summary>
|
||||
public int SampleRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of channels (== number of subframes).
|
||||
/// </summary>
|
||||
public int Channels { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channel assignment for the frame.
|
||||
/// </summary>
|
||||
public int ChannelAssignment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sample resolution.
|
||||
/// </summary>
|
||||
public int BitsPerSample { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the frame number or sample number of first sample in frame.
|
||||
/// Use the number_type value to determine which to use.
|
||||
/// </summary>
|
||||
public int FrameNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The sample number for the first sample in the frame.
|
||||
/// </summary>
|
||||
public int SampleNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0)
|
||||
/// of the raw frame header bytes, meaning everything before the CRC byte
|
||||
/// including the sync code.
|
||||
/// </summary>
|
||||
protected byte crc;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="is"></param>
|
||||
/// <param name="headerWarmup"></param>
|
||||
/// <param name="streamInfo"></param>
|
||||
public Header(BitReader @is, byte[] headerWarmup, StreamInfo streamInfo)
|
||||
{
|
||||
FrameNumber = -1;
|
||||
SampleNumber = -1;
|
||||
}
|
||||
}
|
||||
}
|
788
Flac/Flac/IO/BitReader.cs
Normal file
788
Flac/Flac/IO/BitReader.cs
Normal file
@ -0,0 +1,788 @@
|
||||
using Flac.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.IO
|
||||
{
|
||||
public class BitReader
|
||||
{
|
||||
#region Constants
|
||||
private const int DefaultCapacity = 2048;
|
||||
private const int BitsPerByte = 8;
|
||||
private const int BitsPerByteLog2 = 3;
|
||||
private const byte ByteTopBitOne = (byte)0x80;
|
||||
#endregion
|
||||
|
||||
#region Private members
|
||||
private byte[] buffer;
|
||||
private int putByte = 0;
|
||||
private int getByte = 0;
|
||||
private int getBit = 0;
|
||||
private int availBits = 0;
|
||||
private int totalBitsRead = 0;
|
||||
private UInt16 readCrc16 = 0;
|
||||
private Stream stream;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new instance of BitReader
|
||||
/// </summary>
|
||||
/// <param name="stream">Input data stream</param>
|
||||
public BitReader(Stream stream)
|
||||
{
|
||||
buffer = new byte[DefaultCapacity];
|
||||
|
||||
this.stream = stream;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from stream.
|
||||
/// </summary>
|
||||
/// <returns>Number of bytes read</returns>
|
||||
private int ReadFromStream()
|
||||
{
|
||||
// first shift the unconsumed buffer data toward the front as much as possible
|
||||
if (getByte > 0 && putByte > getByte)
|
||||
{
|
||||
Array.Copy(buffer, getByte, buffer, 0, putByte - getByte);
|
||||
}
|
||||
putByte -= getByte;
|
||||
getByte = 0;
|
||||
|
||||
// Set the target for reading, taking into account byte alignment
|
||||
int bytes = buffer.Length - putByte;
|
||||
|
||||
// Read some data
|
||||
bytes = stream.Read(buffer, putByte, bytes);
|
||||
if (bytes <= 0)
|
||||
throw new IOException("Failed to read from buffer.");
|
||||
|
||||
// Now we have to handle partial byte cases
|
||||
putByte += bytes;
|
||||
availBits += bytes << 3;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the bit stream.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
getByte = 0;
|
||||
getBit = 0;
|
||||
putByte = 0;
|
||||
availBits = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the read CRC-16 value.
|
||||
/// </summary>
|
||||
/// <param name="seed">The initial CRC-16 value</param>
|
||||
public void ResetReadCrc16(UInt16 seed)
|
||||
{
|
||||
readCrc16 = seed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the the read CRC-16 value.
|
||||
/// </summary>
|
||||
public UInt16 ReadCrc16
|
||||
{
|
||||
get
|
||||
{
|
||||
return readCrc16;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the Bit Stream consumed bits is byte aligned.
|
||||
/// </summary>
|
||||
public bool IsConsumedByteAligned
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((getBit & 0x7) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bits to read to align the byte.
|
||||
/// </summary>
|
||||
public int BitsLeftForByteAlignment
|
||||
{
|
||||
get
|
||||
{
|
||||
return 8 - (getBit & 7);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bytes left to read.
|
||||
/// </summary>
|
||||
public int InputBitsUnconsumed
|
||||
{
|
||||
get
|
||||
{
|
||||
return availBits >> 3;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skips over bits in bit stream without updating CRC.
|
||||
/// </summary>
|
||||
/// <param name="bits">Number of bits to skip</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from input stream</exception>
|
||||
public void SkipBitsNoCrc(int bits)
|
||||
{
|
||||
if (bits > 0)
|
||||
{
|
||||
int bitsToAlign = getBit & 7;
|
||||
if (bitsToAlign != 0)
|
||||
{
|
||||
int bitsToTake = Math.Min(8 - bitsToAlign, bits);
|
||||
ReadRawUInt32(bitsToTake);
|
||||
bits -= bitsToTake;
|
||||
}
|
||||
|
||||
int bytesNeeded = bits / 8;
|
||||
if (bytesNeeded > 0)
|
||||
{
|
||||
ReadByteBlockAlignedNoCrc(null, bytesNeeded);
|
||||
bits %= 8;
|
||||
}
|
||||
|
||||
if (bits > 0)
|
||||
{
|
||||
ReadRawUInt32(bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a single bit.
|
||||
/// </summary>
|
||||
/// <returns>The bit</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public int ReadBit()
|
||||
{
|
||||
while (availBits <= 0)
|
||||
{
|
||||
ReadFromStream();
|
||||
}
|
||||
|
||||
int val = ((buffer[getByte] & (0x80 >> getBit)) != 0) ? 1 : 0;
|
||||
getBit++;
|
||||
if (getBit == BitsPerByte)
|
||||
{
|
||||
readCrc16 = CRC16.Update(buffer[getByte], readCrc16);
|
||||
getByte++;
|
||||
getBit = 0;
|
||||
}
|
||||
availBits--;
|
||||
totalBitsRead++;
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a bit into an integer value.
|
||||
/// The bits of the input integer are shifted left and the
|
||||
/// bit is placed into bit 0.
|
||||
/// </summary>
|
||||
/// <param name="val">The integer to shift and add read bit</param>
|
||||
/// <returns>The updated integer value</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt32 ReadBitToUInt32(UInt32 val)
|
||||
{
|
||||
while (availBits <= 0)
|
||||
{
|
||||
ReadFromStream();
|
||||
}
|
||||
|
||||
val <<= 1;
|
||||
val |= ((buffer[getByte] & (0x80 >> getBit)) != 0) ? 1u : 0u;
|
||||
getBit++;
|
||||
if (getBit == BitsPerByte)
|
||||
{
|
||||
readCrc16 = CRC16.Update(buffer[getByte], readCrc16);
|
||||
getByte++;
|
||||
getBit = 0;
|
||||
}
|
||||
availBits--;
|
||||
totalBitsRead++;
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peeks at the next bit and add it to the input integer.
|
||||
/// The bits of the input integer are shifted left and the
|
||||
/// bit is placed into bit 0.
|
||||
/// </summary>
|
||||
/// <param name="val">The input integer</param>
|
||||
/// <param name="bit">The bit to peek at</param>
|
||||
/// <returns>The updated integer value</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt32 PeekBitToUInt32(UInt32 val, int bit)
|
||||
{
|
||||
while (availBits <= 0)
|
||||
{
|
||||
ReadFromStream();
|
||||
}
|
||||
|
||||
val <<= 1;
|
||||
if ((getBit + bit) >= BitsPerByte)
|
||||
{
|
||||
bit = (getBit + bit) % BitsPerByte;
|
||||
val |= ((buffer[getByte + 1] & (0x80 >> bit)) != 0) ? 1u : 0u;
|
||||
}
|
||||
else
|
||||
{
|
||||
val |= ((buffer[getByte] & (0x80 >> (getBit + bit))) != 0) ? 1u : 0u;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a bit into a long value.
|
||||
/// The bits of the input integer are shifted left and the
|
||||
/// bit is placed into bit 0.
|
||||
/// </summary>
|
||||
/// <param name="val">The long to shift and add read bit</param>
|
||||
/// <returns>The updated long value</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt64 ReadBitToUInt64(UInt64 val)
|
||||
{
|
||||
while (availBits <= 0)
|
||||
{
|
||||
ReadFromStream();
|
||||
}
|
||||
|
||||
val <<= 1;
|
||||
val |= ((buffer[getByte] & (0x80 >> getBit)) != 0) ? 1u : 0u;
|
||||
getBit++;
|
||||
if (getBit == BitsPerByte)
|
||||
{
|
||||
readCrc16 = CRC16.Update(buffer[getByte], readCrc16);
|
||||
getByte++;
|
||||
getBit = 0;
|
||||
}
|
||||
availBits--;
|
||||
totalBitsRead++;
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read bits into an unsigned integer.
|
||||
/// </summary>
|
||||
/// <param name="bits">The number of bits to read</param>
|
||||
/// <returns>The bits as an unsigned integer</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt32 ReadRawUInt32(int bits)
|
||||
{
|
||||
UInt32 val = 0;
|
||||
for (int i = 0; i < bits; i++)
|
||||
{
|
||||
val = ReadBitToUInt32(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peek at bits into an unsigned integer without advancing the input stream.
|
||||
/// </summary>
|
||||
/// <param name="bits">The number of bits to read</param>
|
||||
/// <returns>The bits as an unsigned integer</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt32 PeekRawUInt32(int bits)
|
||||
{
|
||||
UInt32 val = 0;
|
||||
for (int i = 0; i < bits; i++)
|
||||
{
|
||||
val = PeekBitToUInt32(val, i);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read bits into an unsigned long.
|
||||
/// </summary>
|
||||
/// <param name="bits">The number of bits to read</param>
|
||||
/// <returns>The bits as an unsigned long</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt64 ReadRawUInt64(int bits)
|
||||
{
|
||||
UInt64 val = 0;
|
||||
for (int i = 0; i < bits; i++)
|
||||
{
|
||||
val = ReadBitToUInt64(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read bits into an unsigned little endian integer.
|
||||
/// </summary>
|
||||
/// <returns>The bits as an unsigned integer</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt32 ReadRawUInt32LittleEndian()
|
||||
{
|
||||
UInt32 val = ReadRawUInt32(8);
|
||||
UInt32 a = ReadRawUInt32(8);
|
||||
UInt32 b = ReadRawUInt32(8);
|
||||
UInt32 c = ReadRawUInt32(8);
|
||||
|
||||
return (val | (a << 8) | (b << 16) | (c << 24));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a block of bytes (aligned) without updating the CRC value.
|
||||
/// </summary>
|
||||
/// <param name="val">The array to receive the bytes. If null, no bytes are returned</param>
|
||||
/// <param name="nvals">The number of bytes to read</param>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public void ReadByteBlockAlignedNoCrc(byte[] val, int nvals)
|
||||
{
|
||||
int destlength = nvals;
|
||||
while (nvals > 0)
|
||||
{
|
||||
int chunk = Math.Min(nvals, putByte - getByte);
|
||||
if (chunk == 0)
|
||||
{
|
||||
ReadFromStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val != null)
|
||||
Array.Copy(buffer, getByte, val, destlength - nvals, chunk);
|
||||
|
||||
nvals -= chunk;
|
||||
getByte += chunk;
|
||||
availBits -= (chunk << BitsPerByteLog2);
|
||||
totalBitsRead += (chunk << BitsPerByteLog2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read and count the number of zero bits.
|
||||
/// </summary>
|
||||
/// <returns>The number of zero bits read</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public int ReadUnaryUnsigned()
|
||||
{
|
||||
int val = 0;
|
||||
int bit = ReadBit();
|
||||
while (bit == 0)
|
||||
{
|
||||
val++;
|
||||
bit = ReadBit();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Rice Signal Block.
|
||||
/// </summary>
|
||||
/// <param name="vals">The values to be returned</param>
|
||||
/// <param name="pos">The starting position in the vals array</param>
|
||||
/// <param name="nvals">The number of values to return</param>
|
||||
/// <param name="parameter">The Rice parameter</param>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public void ReadRiceSignedBlock(int[] vals, int pos, int nvals, int parameter)
|
||||
{
|
||||
int j, valI = 0;
|
||||
int cbits = 0, uval = 0, msbs = 0, lsbsLeft = 0;
|
||||
byte blurb, saveBlurb;
|
||||
int state = 0; // 0 = getting unary MSBs, 1 = getting binary LSBs
|
||||
int i = getByte;
|
||||
|
||||
long startBits = getByte * 8 + getBit;
|
||||
|
||||
if (nvals == 0)
|
||||
return;
|
||||
|
||||
// We unroll the main loop to take care of partially consumed blurbs here.
|
||||
if (getBit > 0)
|
||||
{
|
||||
saveBlurb = blurb = buffer[i];
|
||||
cbits = getBit;
|
||||
blurb <<= cbits;
|
||||
while (true)
|
||||
{
|
||||
if (state == 0)
|
||||
{
|
||||
if (blurb != 0)
|
||||
{
|
||||
for (j = 0; (blurb & ByteTopBitOne) == 0; j++)
|
||||
blurb <<= 1;
|
||||
msbs += j;
|
||||
|
||||
// dispose of the unary end bit
|
||||
blurb <<= 1;
|
||||
j++;
|
||||
cbits += j;
|
||||
uval = 0;
|
||||
lsbsLeft = parameter;
|
||||
state++;
|
||||
//totalBitsRead += msbs;
|
||||
if (cbits == BitsPerByte)
|
||||
{
|
||||
cbits = 0;
|
||||
readCrc16 = CRC16.Update(saveBlurb, readCrc16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msbs += BitsPerByte - cbits;
|
||||
cbits = 0;
|
||||
readCrc16 = CRC16.Update(saveBlurb, readCrc16);
|
||||
//totalBitsRead += msbs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int availableBits = BitsPerByte - cbits;
|
||||
if (lsbsLeft >= availableBits)
|
||||
{
|
||||
uval <<= availableBits;
|
||||
uval |= ((blurb & 0xff) >> cbits);
|
||||
cbits = 0;
|
||||
readCrc16 = CRC16.Update(saveBlurb, readCrc16);
|
||||
//totalBitsRead += availableBits;
|
||||
if (lsbsLeft == availableBits)
|
||||
{
|
||||
// compose the value
|
||||
uval |= (msbs << parameter);
|
||||
if ((uval & 1) != 0)
|
||||
vals[pos + valI++] = -((int)(uval >> 1)) - 1;
|
||||
else
|
||||
vals[pos + valI++] = (int)(uval >> 1);
|
||||
if (valI == nvals)
|
||||
break;
|
||||
msbs = 0;
|
||||
state = 0;
|
||||
}
|
||||
lsbsLeft -= availableBits;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
uval <<= lsbsLeft;
|
||||
uval |= ((blurb & 0xff) >> (BitsPerByte - lsbsLeft));
|
||||
blurb <<= lsbsLeft;
|
||||
cbits += lsbsLeft;
|
||||
//totalBitsRead += lsbsLeft;
|
||||
// compose the value
|
||||
uval |= (msbs << parameter);
|
||||
if ((uval & 1) != 0)
|
||||
vals[pos + valI++] = -((int)(uval >> 1)) - 1;
|
||||
else
|
||||
vals[pos + valI++] = (int)(uval >> 1);
|
||||
if (valI == nvals)
|
||||
{
|
||||
// back up one if we exited the for loop because we
|
||||
// read all nvals but the end came in the middle of
|
||||
// a blurb
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
msbs = 0;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
getByte = i;
|
||||
getBit = cbits;
|
||||
//totalConsumedBits = (i << BITS_PER_BLURB_LOG2) | cbits;
|
||||
//totalBitsRead += (BITS_PER_BLURB) | cbits;
|
||||
}
|
||||
|
||||
// Now that we are blurb-aligned the logic is slightly simpler
|
||||
while (valI < nvals)
|
||||
{
|
||||
for (; i < putByte && valI < nvals; i++)
|
||||
{
|
||||
saveBlurb = blurb = buffer[i];
|
||||
cbits = 0;
|
||||
while (true)
|
||||
{
|
||||
if (state == 0)
|
||||
{
|
||||
if (blurb != 0)
|
||||
{
|
||||
for (j = 0; (blurb & ByteTopBitOne) == 0; j++)
|
||||
blurb <<= 1;
|
||||
msbs += j;
|
||||
// dispose of the unary end bit
|
||||
blurb <<= 1;
|
||||
j++;
|
||||
cbits += j;
|
||||
uval = 0;
|
||||
lsbsLeft = parameter;
|
||||
state++;
|
||||
//totalBitsRead += msbs;
|
||||
if (cbits == BitsPerByte)
|
||||
{
|
||||
cbits = 0;
|
||||
readCrc16 = CRC16.Update(saveBlurb, readCrc16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msbs += BitsPerByte - cbits;
|
||||
cbits = 0;
|
||||
readCrc16 = CRC16.Update(saveBlurb, readCrc16);
|
||||
//totalBitsRead += msbs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int availableBits = BitsPerByte - cbits;
|
||||
if (lsbsLeft >= availableBits)
|
||||
{
|
||||
uval <<= availableBits;
|
||||
uval |= ((blurb & 0xff) >> cbits);
|
||||
cbits = 0;
|
||||
readCrc16 = CRC16.Update(saveBlurb, readCrc16);
|
||||
//totalBitsRead += availableBits;
|
||||
if (lsbsLeft == availableBits)
|
||||
{
|
||||
// compose the value
|
||||
uval |= (msbs << parameter);
|
||||
if ((uval & 1) != 0)
|
||||
vals[pos + valI++] = -((int)(uval >> 1)) - 1;
|
||||
else
|
||||
vals[pos + valI++] = (int)(uval >> 1);
|
||||
if (valI == nvals)
|
||||
break;
|
||||
msbs = 0;
|
||||
state = 0;
|
||||
}
|
||||
lsbsLeft -= availableBits;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
uval <<= lsbsLeft;
|
||||
uval |= ((blurb & 0xff) >> (BitsPerByte - lsbsLeft));
|
||||
blurb <<= lsbsLeft;
|
||||
cbits += lsbsLeft;
|
||||
//totalBitsRead += lsbsLeft;
|
||||
// compose the value
|
||||
uval |= (msbs << parameter);
|
||||
if ((uval & 1) != 0)
|
||||
vals[pos + valI++] = -((int)(uval >> 1)) - 1;
|
||||
else
|
||||
vals[pos + valI++] = (int)(uval >> 1);
|
||||
if (valI == nvals)
|
||||
{
|
||||
// back up one if we exited the for loop because
|
||||
// we read all nvals but the end came in the
|
||||
// middle of a blurb
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
msbs = 0;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getByte = i;
|
||||
getBit = cbits;
|
||||
//totalConsumedBits = (i << BITS_PER_BLURB_LOG2) | cbits;
|
||||
//totalBitsRead += (BITS_PER_BLURB) | cbits;
|
||||
if (valI < nvals)
|
||||
{
|
||||
long endBits = getByte * 8 + getBit;
|
||||
totalBitsRead += (int)(endBits - startBits);
|
||||
availBits -= (int)(endBits - startBits);
|
||||
ReadFromStream();
|
||||
// these must be zero because we can only get here if we got to
|
||||
// the end of the buffer
|
||||
i = 0;
|
||||
startBits = getByte * 8 + getBit;
|
||||
}
|
||||
}
|
||||
|
||||
long endBits2 = getByte * 8 + getBit;
|
||||
totalBitsRead += (int)(endBits2 - startBits);
|
||||
availBits -= (int)(endBits2 - startBits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read UTF8 integer.
|
||||
/// On return, if *val == 0xffffffff then the utf-8 sequence was invalid, but
|
||||
/// the return value will be true.
|
||||
/// </summary>
|
||||
/// <param name="raw">The raw bytes read (output). If null, no bytes are returned</param>
|
||||
/// <param name="rawCount">The raw bytes count.</param>
|
||||
/// <returns>The integer read</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt32 ReadUtf8UInt32(byte[] raw, out int rawCount)
|
||||
{
|
||||
UInt32 val, x;
|
||||
UInt32 v = 0, i;
|
||||
|
||||
x = ReadRawUInt32(8);
|
||||
rawCount = 0;
|
||||
|
||||
if (raw != null)
|
||||
raw[rawCount++] = (byte)x;
|
||||
|
||||
if ((x & 0x80) == 0)
|
||||
{ // 0xxxxxxx
|
||||
v = x;
|
||||
i = 0;
|
||||
}
|
||||
else if (((x & 0xC0) != 0) && ((x & 0x20) == 0))
|
||||
{ // 110xxxxx
|
||||
v = x & 0x1F;
|
||||
i = 1;
|
||||
}
|
||||
else if (((x & 0xE0) != 0) && ((x & 0x10) == 0))
|
||||
{ // 1110xxxx
|
||||
v = x & 0x0F;
|
||||
i = 2;
|
||||
}
|
||||
else if (((x & 0xF0) != 0) && ((x & 0x08) == 0))
|
||||
{ // 11110xxx
|
||||
v = x & 0x07;
|
||||
i = 3;
|
||||
}
|
||||
else if (((x & 0xF8) != 0) && ((x & 0x04) == 0))
|
||||
{ // 111110xx
|
||||
v = x & 0x03;
|
||||
i = 4;
|
||||
}
|
||||
else if (((x & 0xFC) != 0) && ((x & 0x02) == 0))
|
||||
{ // 1111110x
|
||||
v = x & 0x01;
|
||||
i = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = 0xffffffff;
|
||||
return val;
|
||||
}
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
x = PeekRawUInt32(8);
|
||||
if (((x & 0x80) == 0) || ((x & 0x40) != 0))
|
||||
{ // 10xxxxxx
|
||||
val = 0xffffffff;
|
||||
return val;
|
||||
}
|
||||
x = ReadRawUInt32(8);
|
||||
if (raw != null)
|
||||
raw[rawCount++] = (byte)x;
|
||||
|
||||
v <<= 6;
|
||||
v |= (x & 0x3F);
|
||||
}
|
||||
val = v;
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read UTF8 long.
|
||||
/// On return, if *val == 0xffffffffffffffff then the utf-8 sequence was invalid, but
|
||||
/// the return value will be true.
|
||||
/// </summary>
|
||||
/// <param name="raw">The raw bytes read (output). If null, no bytes are returned</param>
|
||||
/// <param name="rawCount">The raw bytes count.</param>
|
||||
/// <returns>The long read</returns>
|
||||
/// <exception cref="IOException">Thrown if error reading input stream</exception>
|
||||
public UInt64 ReadUtf8UInt64(byte[] raw, out int rawCount)
|
||||
{
|
||||
UInt64 val, v = 0;
|
||||
UInt32 x, i;
|
||||
|
||||
x = ReadRawUInt32(8);
|
||||
rawCount = 0;
|
||||
|
||||
if (raw != null)
|
||||
raw[rawCount++] = (byte)x;
|
||||
|
||||
if (((x & 0x80) == 0))
|
||||
{ // 0xxxxxxx
|
||||
v = x;
|
||||
i = 0;
|
||||
}
|
||||
else if (((x & 0xC0) != 0) && ((x & 0x20) == 0))
|
||||
{ // 110xxxxx
|
||||
v = x & 0x1F;
|
||||
i = 1;
|
||||
}
|
||||
else if (((x & 0xE0) != 0) && ((x & 0x10) == 0))
|
||||
{ // 1110xxxx
|
||||
v = x & 0x0F;
|
||||
i = 2;
|
||||
}
|
||||
else if (((x & 0xF0) != 0) && ((x & 0x08) == 0))
|
||||
{ // 11110xxx
|
||||
v = x & 0x07;
|
||||
i = 3;
|
||||
}
|
||||
else if (((x & 0xF8) != 0) && ((x & 0x04) == 0))
|
||||
{ // 111110xx
|
||||
v = x & 0x03;
|
||||
i = 4;
|
||||
}
|
||||
else if (((x & 0xFC) != 0) && ((x & 0x02) == 0))
|
||||
{ // 1111110x
|
||||
v = x & 0x01;
|
||||
i = 5;
|
||||
}
|
||||
else if (((x & 0xFE) != 0) && ((x & 0x01) == 0))
|
||||
{ // 11111110
|
||||
v = 0;
|
||||
i = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = 0xffffffffffffffffL;
|
||||
return val;
|
||||
}
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
x = PeekRawUInt32(8);
|
||||
if (((x & 0x80) == 0) || ((x & 0x40) != 0))
|
||||
{ // 10xxxxxx
|
||||
val = 0xffffffffffffffffL;
|
||||
return val;
|
||||
}
|
||||
x = ReadRawUInt32(8);
|
||||
|
||||
if (raw != null)
|
||||
raw[rawCount++] = (byte)x;
|
||||
v <<= 6;
|
||||
v |= (x & 0x3F);
|
||||
}
|
||||
|
||||
val = v;
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets total bytes read.
|
||||
/// </summary>
|
||||
public int TotalBytesRead
|
||||
{
|
||||
get
|
||||
{
|
||||
return (totalBitsRead + 7) / 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
Flac/Flac/Metadata/Application.cs
Normal file
39
Flac/Flac/Metadata/Application.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Application Metadata block.
|
||||
/// </summary>
|
||||
public class Application : Metadata
|
||||
{
|
||||
private const int IdLength = 32; // bits
|
||||
|
||||
private byte[] id = new byte[4];
|
||||
private byte[] data;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of application class.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public Application(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
read.ReadByteBlockAlignedNoCrc(id, IdLength / 8);
|
||||
length -= IdLength / 8;
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
data = new byte[length];
|
||||
read.ReadByteBlockAlignedNoCrc(data, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
Flac/Flac/Metadata/CueIndex.cs
Normal file
40
Flac/Flac/Metadata/CueIndex.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// An entry into the cue track.
|
||||
/// </summary>
|
||||
public class CueIndex
|
||||
{
|
||||
private const int OffsetLength = 64; // bits
|
||||
private const int NumberLength = 8; // bits
|
||||
private const int ReservedLength = 3 * 8; // bits
|
||||
|
||||
/// <summary>
|
||||
/// Offset in samples, relative to the track offset, of the index point.
|
||||
/// </summary>
|
||||
public UInt64 Offset { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// The index point number.
|
||||
/// </summary>
|
||||
public byte Number { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of CueIndex.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader.</exception>
|
||||
public CueIndex(BitReader read)
|
||||
{
|
||||
Offset = read.ReadRawUInt64(OffsetLength);
|
||||
Number = (byte)read.ReadRawUInt32(NumberLength);
|
||||
read.SkipBitsNoCrc(ReservedLength);
|
||||
}
|
||||
}
|
||||
}
|
137
Flac/Flac/Metadata/CueSheet.cs
Normal file
137
Flac/Flac/Metadata/CueSheet.cs
Normal file
@ -0,0 +1,137 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// CueSheet Metadata block.
|
||||
/// </summary>
|
||||
public class CueSheet : Metadata
|
||||
{
|
||||
#region Constants
|
||||
private const int MediaCatalogNumberLength = 128 * 8; // bits
|
||||
private const int LeadInLength = 64; // bits
|
||||
private const int IsCdLength = 1; // bits
|
||||
private const int ReservedLength = 7 + 258 * 8; // bits
|
||||
private const int TrackCountLength = 8; // bits
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Media catalog number.
|
||||
/// in ASCII printable characters 0x20-0x7e. In
|
||||
/// general, the media catalog number may be 0 to 128 bytes long; any
|
||||
/// unused characters should be right-padded with NUL characters.
|
||||
/// </summary>
|
||||
protected byte[] mediaCatalogNumber = new byte[129];
|
||||
|
||||
/// <summary>
|
||||
/// The number of lead-in samples.
|
||||
/// </summary>
|
||||
protected UInt64 leadIn = 0;
|
||||
|
||||
/// <summary>
|
||||
/// True if CueSheet corresponds to a Compact Disc, else false
|
||||
/// </summary>
|
||||
protected bool isCD = false;
|
||||
|
||||
/// <summary>
|
||||
/// The number of tracks.
|
||||
/// </summary>
|
||||
protected UInt32 trackCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// NULL if num_tracks == 0, else pointer to array of tracks.
|
||||
/// </summary>
|
||||
protected CueTrack[] tracks;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of CueSheet.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public CueSheet(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
// Read fields
|
||||
read.ReadByteBlockAlignedNoCrc(mediaCatalogNumber, MediaCatalogNumberLength / 8);
|
||||
leadIn = read.ReadRawUInt64(LeadInLength);
|
||||
isCD = (read.ReadRawUInt32(IsCdLength) != 0);
|
||||
read.SkipBitsNoCrc(ReservedLength);
|
||||
trackCount = read.ReadRawUInt32(TrackCountLength);
|
||||
|
||||
// Read cue tracks
|
||||
if (trackCount > 0)
|
||||
{
|
||||
tracks = new CueTrack[trackCount];
|
||||
for (int i = 0; i < trackCount; i++)
|
||||
tracks[i] = new CueTrack(read);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the Cue Sheet.
|
||||
/// </summary>
|
||||
/// <param name="checkCdDaSubset">True for check CD subset</param>
|
||||
/// <exception cref="ValidationException">Thrown if invalid Cue Sheet</exception>
|
||||
public void IsLegal(bool checkCdDaSubset)
|
||||
{
|
||||
|
||||
if (checkCdDaSubset)
|
||||
{
|
||||
if (leadIn < 2 * 44100)
|
||||
throw new ValidationException("CD-DA cue sheet must have a lead-in length of at least 2 seconds");
|
||||
|
||||
if (leadIn % 588 != 0)
|
||||
throw new ValidationException("CD-DA cue sheet lead-in length must be evenly divisible by 588 samples");
|
||||
}
|
||||
|
||||
if (trackCount == 0)
|
||||
throw new ValidationException("cue sheet must have at least one track (the lead-out)");
|
||||
|
||||
if (checkCdDaSubset && tracks[trackCount - 1].Number != 170)
|
||||
throw new ValidationException("CD-DA cue sheet must have a lead-out track number 170 (0xAA)");
|
||||
|
||||
for (int i = 0; i < trackCount; i++)
|
||||
{
|
||||
if (tracks[i].Number == 0)
|
||||
throw new ValidationException("cue sheet may not have a track number 0");
|
||||
|
||||
if (checkCdDaSubset)
|
||||
{
|
||||
if (!((tracks[i].Number >= 1 && tracks[i].Number <= 99)
|
||||
|| tracks[i].Number == 170))
|
||||
throw new ValidationException("CD-DA cue sheet track number must be 1-99 or 170");
|
||||
}
|
||||
|
||||
if (checkCdDaSubset && tracks[i].Offset % 588 != 0)
|
||||
throw new ValidationException("CD-DA cue sheet track offset must be evenly divisible by 588 samples");
|
||||
|
||||
if (i < trackCount - 1)
|
||||
{
|
||||
if (tracks[i].IndicesCount == 0)
|
||||
throw new ValidationException("cue sheet track must have at least one index point");
|
||||
|
||||
if (tracks[i].Indices[0].Number > 1)
|
||||
throw new ValidationException("cue sheet track's first index number must be 0 or 1");
|
||||
}
|
||||
|
||||
for (int j = 0; j < tracks[i].IndicesCount; j++)
|
||||
{
|
||||
if (checkCdDaSubset && tracks[i].Indices[j].Offset % 588 != 0)
|
||||
throw new ValidationException("CD-DA cue sheet track index offset must be evenly divisible by 588 samples");
|
||||
|
||||
if (j > 0)
|
||||
{
|
||||
if (tracks[i].Indices[j].Number != tracks[i].Indices[j - 1].Number + 1)
|
||||
throw new ValidationException("cue sheet track index numbers must increase by 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
85
Flac/Flac/Metadata/CueTrack.cs
Normal file
85
Flac/Flac/Metadata/CueTrack.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// An entry into the cue sheet.
|
||||
/// </summary>
|
||||
public class CueTrack
|
||||
{
|
||||
#region Constants
|
||||
private const int OffsetLength = 64;
|
||||
private const int NumberLength = 8;
|
||||
private const int IsrcLength = 12 * 8;
|
||||
private const int TypeLength = 1;
|
||||
private const int PreEmphasisLength = 1;
|
||||
private const int ReservedLength = 6 + 13 * 8;
|
||||
private const int IndicesCountLength = 8;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Track offset in samples, relative to the beginning of the FLAC audio stream.
|
||||
/// </summary>
|
||||
public UInt64 Offset { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// The track number.
|
||||
/// </summary>
|
||||
public byte Number { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Track ISRC. This is a 12-digit alphanumeric code plus a trailing '\0'
|
||||
/// </summary>
|
||||
protected byte[] isrc = new byte[13];
|
||||
|
||||
/// <summary>
|
||||
/// The track type: 0 for audio, 1 for non-audio.
|
||||
/// </summary>
|
||||
protected UInt32 type;
|
||||
|
||||
/// <summary>
|
||||
/// The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis.
|
||||
/// </summary>
|
||||
protected UInt32 preEmphasis;
|
||||
|
||||
/// <summary>
|
||||
/// The number of track index points.
|
||||
/// </summary>
|
||||
public byte IndicesCount { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// NULL if num_indices == 0, else pointer to array of index points.
|
||||
/// </summary>
|
||||
public CueIndex[] Indices { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of CueTrack.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public CueTrack(BitReader read)
|
||||
{
|
||||
// Read fields
|
||||
Offset = read.ReadRawUInt64(OffsetLength);
|
||||
Number = (byte)read.ReadRawUInt32(NumberLength);
|
||||
read.ReadByteBlockAlignedNoCrc(isrc, IsrcLength / 8);
|
||||
type = read.ReadRawUInt32(TypeLength);
|
||||
preEmphasis = read.ReadRawUInt32(PreEmphasisLength);
|
||||
read.SkipBitsNoCrc(ReservedLength);
|
||||
IndicesCount = (byte)read.ReadRawUInt32(IndicesCountLength);
|
||||
|
||||
// Read indices
|
||||
if (IndicesCount > 0)
|
||||
{
|
||||
Indices = new CueIndex[IndicesCount];
|
||||
|
||||
for (int i = 0; i < IndicesCount; i++)
|
||||
Indices[i] = new CueIndex(read);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
Flac/Flac/Metadata/Metadata.cs
Normal file
57
Flac/Flac/Metadata/Metadata.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata types.
|
||||
/// </summary>
|
||||
public enum MetadataType
|
||||
{
|
||||
StreamInfo = 0,
|
||||
Padding = 1,
|
||||
Application = 2,
|
||||
SeekTable = 3,
|
||||
VorbisComment = 4,
|
||||
CueSheet = 5,
|
||||
Picture = 6,
|
||||
Undefined = 7
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Root class for all Metadata subclasses.
|
||||
/// </summary>
|
||||
public abstract class Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata IsLast field length (bits).
|
||||
/// </summary>
|
||||
public const int StreamMetadataIsLastLength = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Metadata type field length (bits).
|
||||
/// </summary>
|
||||
public const int StreamMetadataTypeLength = 7;
|
||||
|
||||
/// <summary>
|
||||
/// Metadata length field length (bits).
|
||||
/// </summary>
|
||||
public const int StreamMetadataLengthLength = 24;
|
||||
|
||||
/// <summary>
|
||||
/// Test if this is the last metadata block.
|
||||
/// </summary>
|
||||
public bool IsLast { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of Metadata class.
|
||||
/// </summary>
|
||||
/// <param name="isLast">True if this is the last metadata block.</param>
|
||||
public Metadata(bool isLast)
|
||||
{
|
||||
IsLast = isLast;
|
||||
}
|
||||
}
|
||||
}
|
30
Flac/Flac/Metadata/Padding.cs
Normal file
30
Flac/Flac/Metadata/Padding.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Padding Metadata block.
|
||||
/// </summary>
|
||||
public class Padding : Metadata
|
||||
{
|
||||
private int length;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of Padding.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public Padding(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
this.length = length;
|
||||
read.ReadByteBlockAlignedNoCrc(null, length);
|
||||
}
|
||||
}
|
||||
}
|
95
Flac/Flac/Metadata/Picture.cs
Normal file
95
Flac/Flac/Metadata/Picture.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Picture Metadata block.
|
||||
/// </summary>
|
||||
public class Picture : Metadata
|
||||
{
|
||||
#region Constants
|
||||
private const int PictureTypeLength = 32;
|
||||
private const int MimeTypeByteCountLength = 32;
|
||||
private const int DescriptionByteCountLength = 32;
|
||||
private const int PicturePixelWidthLength = 32;
|
||||
private const int PicturePixelHeightLength = 32;
|
||||
private const int PictureBitsPerPixelLength = 32;
|
||||
private const int PictureColorCountLength = 32;
|
||||
private const int PictureByteCountLength = 32;
|
||||
#endregion
|
||||
|
||||
private UInt32 pictureType;
|
||||
private string mimeType;
|
||||
private string description;
|
||||
private int picPixelWidth;
|
||||
private int picPixelHeight;
|
||||
private int picBitsPerPixel;
|
||||
private int picColorCount;
|
||||
private byte[] image;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of Picture.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public Picture(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
int usedbits = 0;
|
||||
|
||||
// Read picture type
|
||||
pictureType = read.ReadRawUInt32(PictureTypeLength);
|
||||
usedbits += PictureTypeLength;
|
||||
|
||||
// Read mime type length
|
||||
int mimeTypeByteCount = (int)read.ReadRawUInt32(MimeTypeByteCountLength);
|
||||
usedbits += MimeTypeByteCountLength;
|
||||
|
||||
// Read mime type
|
||||
byte[] data = new byte[mimeTypeByteCount];
|
||||
read.ReadByteBlockAlignedNoCrc(data, mimeTypeByteCount);
|
||||
usedbits += mimeTypeByteCount * 8;
|
||||
mimeType = UTF8Encoding.UTF8.GetString(data, 0, mimeTypeByteCount);
|
||||
|
||||
// Description string length
|
||||
int descriptionByteCount = (int)read.ReadRawUInt32(DescriptionByteCountLength);
|
||||
usedbits += DescriptionByteCountLength;
|
||||
|
||||
// Description string
|
||||
data = new byte[descriptionByteCount];
|
||||
read.ReadByteBlockAlignedNoCrc(data, descriptionByteCount);
|
||||
usedbits += descriptionByteCount * 8;
|
||||
description = UTF8Encoding.UTF8.GetString(data, 0, descriptionByteCount);
|
||||
|
||||
// Picture stuff
|
||||
picPixelWidth = (int)read.ReadRawUInt32(PicturePixelWidthLength);
|
||||
picPixelHeight = (int)read.ReadRawUInt32(PicturePixelHeightLength);
|
||||
usedbits += PicturePixelWidthLength + PicturePixelHeightLength;
|
||||
|
||||
picBitsPerPixel = (int)read.ReadRawUInt32(PictureBitsPerPixelLength);
|
||||
usedbits += PictureBitsPerPixelLength;
|
||||
|
||||
picColorCount = (int)read.ReadRawUInt32(PictureColorCountLength);
|
||||
usedbits += PictureColorCountLength;
|
||||
|
||||
// Read data size
|
||||
int picByteCount = (int)read.ReadRawUInt32(PictureByteCountLength);
|
||||
usedbits += PictureByteCountLength;
|
||||
|
||||
// Read data
|
||||
image = new byte[picByteCount];
|
||||
read.ReadByteBlockAlignedNoCrc(image, picByteCount);
|
||||
usedbits += picByteCount * 8;
|
||||
|
||||
// Skip the rest of the block
|
||||
length -= (usedbits / 8);
|
||||
read.ReadByteBlockAlignedNoCrc(null, length);
|
||||
}
|
||||
}
|
||||
}
|
62
Flac/Flac/Metadata/SeekPoint.cs
Normal file
62
Flac/Flac/Metadata/SeekPoint.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// An entry into the seek table.
|
||||
/// </summary>
|
||||
public class SeekPoint
|
||||
{
|
||||
#region Constants
|
||||
private const int SampleNumberLength = 64;
|
||||
private const int StreamOffsetLength = 64;
|
||||
private const int FrameSamplesLength = 16;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The sample number of the target frame.
|
||||
/// </summary>
|
||||
public long SampleNumber { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The offset, in bytes, of the target frame with
|
||||
/// respect to beginning of the first frame.
|
||||
/// </summary>
|
||||
public long StreamOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of samples in the target frame.
|
||||
/// </summary>
|
||||
public int FrameSamples { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of SeekPoint.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public SeekPoint(BitReader read)
|
||||
{
|
||||
SampleNumber = (long)read.ReadRawUInt64(SampleNumberLength);
|
||||
StreamOffset = (long)read.ReadRawUInt64(StreamOffsetLength);
|
||||
FrameSamples = (int)read.ReadRawUInt32(FrameSamplesLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of SeekPoint.
|
||||
/// </summary>
|
||||
/// <param name="sampleNumber">The sample number of the target frame</param>
|
||||
/// <param name="streamOffset">The offset, in bytes, of the target frame with
|
||||
/// respect to beginning of the first frame</param>
|
||||
/// <param name="frameSamples">The number of samples in the target frame</param>
|
||||
public SeekPoint(long sampleNumber, long streamOffset, int frameSamples)
|
||||
{
|
||||
SampleNumber = sampleNumber;
|
||||
StreamOffset = streamOffset;
|
||||
FrameSamples = frameSamples;
|
||||
}
|
||||
}
|
||||
}
|
117
Flac/Flac/Metadata/SeekTable.cs
Normal file
117
Flac/Flac/Metadata/SeekTable.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// SeekTable metadata block.
|
||||
/// </summary>
|
||||
public class SeekTable : Metadata, IEnumerable<SeekPoint>
|
||||
{
|
||||
#region Constants
|
||||
private const int LengthBytes = 18;
|
||||
#endregion
|
||||
|
||||
private SeekPoint[] points;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the seek point count.
|
||||
/// </summary>
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
if (points != null)
|
||||
return points.Length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets length in bytes (metadata block size).
|
||||
/// </summary>
|
||||
public int RawLength
|
||||
{
|
||||
get
|
||||
{
|
||||
if (points != null)
|
||||
return points.Length * LengthBytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets iterator for this container
|
||||
/// </summary>
|
||||
/// <returns>The iterator</returns>
|
||||
public IEnumerator<SeekPoint> GetEnumerator()
|
||||
{
|
||||
foreach (var i in points)
|
||||
yield return i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets iterator for this container
|
||||
/// </summary>
|
||||
/// <returns>The iterator</returns>
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return points.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a seek point.
|
||||
/// </summary>
|
||||
/// <param name="index">Index of seek point.</param>
|
||||
/// <returns></returns>
|
||||
public SeekPoint this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return points[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of SeekTable.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public SeekTable(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
// Calculate seek point count
|
||||
int pointCount = length / LengthBytes;
|
||||
|
||||
// Create seek points
|
||||
points = new SeekPoint[pointCount];
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
points[i] = new SeekPoint(read);
|
||||
|
||||
// Skip rest of bytes
|
||||
length -= pointCount * LengthBytes;
|
||||
if (length > 0)
|
||||
read.ReadByteBlockAlignedNoCrc(null, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of SeekTable.
|
||||
/// </summary>
|
||||
/// <param name="points">Seek points</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
public SeekTable(SeekPoint[] points, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
147
Flac/Flac/Metadata/StreamInfo.cs
Normal file
147
Flac/Flac/Metadata/StreamInfo.cs
Normal file
@ -0,0 +1,147 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// StreamInfo Metadata block.
|
||||
/// </summary>
|
||||
public class StreamInfo : Metadata
|
||||
{
|
||||
#region Constants
|
||||
private const int MinBlockSizeLength = 16; // bits
|
||||
private const int MaxBlockSizeLength = 16; // bits
|
||||
private const int MinFrameSizeLength = 24; // bits
|
||||
private const int MaxFrameSizeLength = 24; // bits
|
||||
private const int SampleRateLength = 20; // bits
|
||||
private const int ChannelsLength = 3; // bits
|
||||
private const int BitsPerSampleLength = 5; // bits
|
||||
private const int TotalSamplesLength = 36; // bits
|
||||
private const int Md5SumLength = 128; // bits
|
||||
#endregion
|
||||
|
||||
private byte[] md5Sum = new byte[16];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MinBlockSize
|
||||
/// </summary>
|
||||
public UInt32 MinBlockSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MaxBlockSize
|
||||
/// </summary>
|
||||
public UInt32 MaxBlockSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MinFrameSize
|
||||
/// </summary>
|
||||
public UInt32 MinFrameSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MaxFrameSize
|
||||
/// </summary>
|
||||
public UInt32 MaxFrameSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate.
|
||||
/// </summary>
|
||||
public UInt32 SampleRate { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels.
|
||||
/// </summary>
|
||||
public UInt32 Channels { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bits per sample.
|
||||
/// </summary>
|
||||
public UInt32 BitsPerSample { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total number of samples.
|
||||
/// </summary>
|
||||
public UInt64 TotalSamples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of stream info class.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain.</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from InputBitStream</exception>
|
||||
public StreamInfo(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
int usedBits = 0;
|
||||
|
||||
MinBlockSize = read.ReadRawUInt32(MinBlockSizeLength);
|
||||
usedBits += MinBlockSizeLength;
|
||||
|
||||
MaxBlockSize = read.ReadRawUInt32(MaxBlockSizeLength);
|
||||
usedBits += MaxBlockSizeLength;
|
||||
|
||||
MinFrameSize = read.ReadRawUInt32(MinFrameSizeLength);
|
||||
usedBits += MinFrameSizeLength;
|
||||
|
||||
MaxFrameSize = read.ReadRawUInt32(MaxFrameSizeLength);
|
||||
usedBits += MaxFrameSizeLength;
|
||||
|
||||
SampleRate = read.ReadRawUInt32(SampleRateLength);
|
||||
usedBits += SampleRateLength;
|
||||
|
||||
Channels = read.ReadRawUInt32(ChannelsLength) + 1;
|
||||
usedBits += ChannelsLength;
|
||||
|
||||
BitsPerSample = read.ReadRawUInt32(BitsPerSampleLength) + 1;
|
||||
usedBits += BitsPerSampleLength;
|
||||
|
||||
TotalSamples = read.ReadRawUInt64(TotalSamplesLength);
|
||||
usedBits += TotalSamplesLength;
|
||||
|
||||
read.ReadByteBlockAlignedNoCrc(md5Sum, Md5SumLength / 8);
|
||||
usedBits += Md5SumLength;
|
||||
|
||||
// Skip the rest of the block
|
||||
length -= (usedBits / 8);
|
||||
read.ReadByteBlockAlignedNoCrc(null, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the metadata block size.
|
||||
/// </summary>
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
int bits = MinBlockSizeLength
|
||||
+ MaxBlockSizeLength
|
||||
+ MinFrameSizeLength
|
||||
+ MaxFrameSizeLength
|
||||
+ SampleRateLength
|
||||
+ ChannelsLength
|
||||
+ BitsPerSampleLength
|
||||
+ TotalSamplesLength
|
||||
+ Md5SumLength;
|
||||
|
||||
return (bits + 7) / 8;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for compatible StreamInfo.
|
||||
/// Checks if SampleRate, Channels, and BitsPerSample are equal
|
||||
/// </summary>
|
||||
/// <param name="info">The StreamInfo block to check</param>
|
||||
/// <returns>True if this and info are compatable</returns>
|
||||
public bool Compatible (StreamInfo info)
|
||||
{
|
||||
if (SampleRate != info.SampleRate) return false;
|
||||
if (Channels != info.Channels) return false;
|
||||
if (BitsPerSample != info.BitsPerSample) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
33
Flac/Flac/Metadata/Unknown.cs
Normal file
33
Flac/Flac/Metadata/Unknown.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Unknown metadata block
|
||||
/// </summary>
|
||||
public class Unknown : Metadata
|
||||
{
|
||||
private byte[] data;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of Unknown.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public Unknown(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
data = new byte[length];
|
||||
read.ReadByteBlockAlignedNoCrc(data, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
Flac/Flac/Metadata/ValidationException.cs
Normal file
42
Flac/Flac/Metadata/ValidationException.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata format validation exception
|
||||
/// </summary>
|
||||
public class ValidationException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of bad header exception.
|
||||
/// </summary>
|
||||
public ValidationException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of bad header exception with specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message</param>
|
||||
public ValidationException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of bad header exception with specified message
|
||||
/// and a reference to the inner exception that is the cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The message</param>
|
||||
/// <param name="innerException">The inner exception</param>
|
||||
public ValidationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
75
Flac/Flac/Metadata/VorbisComment.cs
Normal file
75
Flac/Flac/Metadata/VorbisComment.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using Flac.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Vorbis comment metadata block.
|
||||
/// </summary>
|
||||
public class VorbisComment : Metadata, IEnumerable<KeyValuePair<string, string>>
|
||||
{
|
||||
private string vendor;
|
||||
public Dictionary<string, string> Comments { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of VorbisComment.
|
||||
/// </summary>
|
||||
/// <param name="read">The BitReader</param>
|
||||
/// <param name="length">Length of the record</param>
|
||||
/// <param name="isLast">True if this is the last Metadata block in the chain</param>
|
||||
/// <exception cref="IOException">Thrown if error reading from BitReader</exception>
|
||||
public VorbisComment(BitReader read, int length, bool isLast)
|
||||
: base(isLast)
|
||||
{
|
||||
byte[] data;
|
||||
|
||||
// Read vendor string
|
||||
int vendorLength = (int)read.ReadRawUInt32LittleEndian();
|
||||
data = new byte[vendorLength];
|
||||
read.ReadByteBlockAlignedNoCrc(data, vendorLength);
|
||||
|
||||
vendor = UTF8Encoding.UTF8.GetString(data, 0, vendorLength);
|
||||
|
||||
// Read comments
|
||||
int commentsCount = (int)read.ReadRawUInt32LittleEndian();
|
||||
Comments = new Dictionary<string, string>(commentsCount);
|
||||
|
||||
for (int i = 0; i < commentsCount; i++)
|
||||
{
|
||||
// Get comment bytes
|
||||
int len = (int)read.ReadRawUInt32LittleEndian();
|
||||
data = new byte[len];
|
||||
read.ReadByteBlockAlignedNoCrc(data, len);
|
||||
|
||||
// Obtain string
|
||||
string str = UTF8Encoding.UTF8.GetString(data, 0, len);
|
||||
int equal = str.IndexOf('=');
|
||||
|
||||
// Add comment
|
||||
if (equal > 0)
|
||||
this.Comments.Add(str.Substring(0, equal), str.Substring(equal));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets iterator for this container
|
||||
/// </summary>
|
||||
/// <returns>The iterator</returns>
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return Comments.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets iterator for this container
|
||||
/// </summary>
|
||||
/// <returns>The iterator</returns>
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((System.Collections.IEnumerable)Comments).GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
36
Flac/Flac/Properties/AssemblyInfo.cs
Normal file
36
Flac/Flac/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Flac")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Flac")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bf99ae12-eb9b-46c7-9ebe-1e736bc674f4")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
319
Flac/Flac/Util/CRC16.cs
Normal file
319
Flac/Flac/Util/CRC16.cs
Normal file
@ -0,0 +1,319 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility class to calculate 16-bit CRC.
|
||||
/// </summary>
|
||||
public static class CRC16
|
||||
{
|
||||
#region private static UInt16[] Crc16Table
|
||||
|
||||
// CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0
|
||||
private static UInt16[] Crc16Table =
|
||||
new UInt16[] {
|
||||
(UInt16) 0x0000,
|
||||
(UInt16) 0x8005,
|
||||
(UInt16) 0x800f,
|
||||
(UInt16) 0x000a,
|
||||
(UInt16) 0x801b,
|
||||
(UInt16) 0x001e,
|
||||
(UInt16) 0x0014,
|
||||
(UInt16) 0x8011,
|
||||
(UInt16) 0x8033,
|
||||
(UInt16) 0x0036,
|
||||
(UInt16) 0x003c,
|
||||
(UInt16) 0x8039,
|
||||
(UInt16) 0x0028,
|
||||
(UInt16) 0x802d,
|
||||
(UInt16) 0x8027,
|
||||
(UInt16) 0x0022,
|
||||
(UInt16) 0x8063,
|
||||
(UInt16) 0x0066,
|
||||
(UInt16) 0x006c,
|
||||
(UInt16) 0x8069,
|
||||
(UInt16) 0x0078,
|
||||
(UInt16) 0x807d,
|
||||
(UInt16) 0x8077,
|
||||
(UInt16) 0x0072,
|
||||
(UInt16) 0x0050,
|
||||
(UInt16) 0x8055,
|
||||
(UInt16) 0x805f,
|
||||
(UInt16) 0x005a,
|
||||
(UInt16) 0x804b,
|
||||
(UInt16) 0x004e,
|
||||
(UInt16) 0x0044,
|
||||
(UInt16) 0x8041,
|
||||
(UInt16) 0x80c3,
|
||||
(UInt16) 0x00c6,
|
||||
(UInt16) 0x00cc,
|
||||
(UInt16) 0x80c9,
|
||||
(UInt16) 0x00d8,
|
||||
(UInt16) 0x80dd,
|
||||
(UInt16) 0x80d7,
|
||||
(UInt16) 0x00d2,
|
||||
(UInt16) 0x00f0,
|
||||
(UInt16) 0x80f5,
|
||||
(UInt16) 0x80ff,
|
||||
(UInt16) 0x00fa,
|
||||
(UInt16) 0x80eb,
|
||||
(UInt16) 0x00ee,
|
||||
(UInt16) 0x00e4,
|
||||
(UInt16) 0x80e1,
|
||||
(UInt16) 0x00a0,
|
||||
(UInt16) 0x80a5,
|
||||
(UInt16) 0x80af,
|
||||
(UInt16) 0x00aa,
|
||||
(UInt16) 0x80bb,
|
||||
(UInt16) 0x00be,
|
||||
(UInt16) 0x00b4,
|
||||
(UInt16) 0x80b1,
|
||||
(UInt16) 0x8093,
|
||||
(UInt16) 0x0096,
|
||||
(UInt16) 0x009c,
|
||||
(UInt16) 0x8099,
|
||||
(UInt16) 0x0088,
|
||||
(UInt16) 0x808d,
|
||||
(UInt16) 0x8087,
|
||||
(UInt16) 0x0082,
|
||||
(UInt16) 0x8183,
|
||||
(UInt16) 0x0186,
|
||||
(UInt16) 0x018c,
|
||||
(UInt16) 0x8189,
|
||||
(UInt16) 0x0198,
|
||||
(UInt16) 0x819d,
|
||||
(UInt16) 0x8197,
|
||||
(UInt16) 0x0192,
|
||||
(UInt16) 0x01b0,
|
||||
(UInt16) 0x81b5,
|
||||
(UInt16) 0x81bf,
|
||||
(UInt16) 0x01ba,
|
||||
(UInt16) 0x81ab,
|
||||
(UInt16) 0x01ae,
|
||||
(UInt16) 0x01a4,
|
||||
(UInt16) 0x81a1,
|
||||
(UInt16) 0x01e0,
|
||||
(UInt16) 0x81e5,
|
||||
(UInt16) 0x81ef,
|
||||
(UInt16) 0x01ea,
|
||||
(UInt16) 0x81fb,
|
||||
(UInt16) 0x01fe,
|
||||
(UInt16) 0x01f4,
|
||||
(UInt16) 0x81f1,
|
||||
(UInt16) 0x81d3,
|
||||
(UInt16) 0x01d6,
|
||||
(UInt16) 0x01dc,
|
||||
(UInt16) 0x81d9,
|
||||
(UInt16) 0x01c8,
|
||||
(UInt16) 0x81cd,
|
||||
(UInt16) 0x81c7,
|
||||
(UInt16) 0x01c2,
|
||||
(UInt16) 0x0140,
|
||||
(UInt16) 0x8145,
|
||||
(UInt16) 0x814f,
|
||||
(UInt16) 0x014a,
|
||||
(UInt16) 0x815b,
|
||||
(UInt16) 0x015e,
|
||||
(UInt16) 0x0154,
|
||||
(UInt16) 0x8151,
|
||||
(UInt16) 0x8173,
|
||||
(UInt16) 0x0176,
|
||||
(UInt16) 0x017c,
|
||||
(UInt16) 0x8179,
|
||||
(UInt16) 0x0168,
|
||||
(UInt16) 0x816d,
|
||||
(UInt16) 0x8167,
|
||||
(UInt16) 0x0162,
|
||||
(UInt16) 0x8123,
|
||||
(UInt16) 0x0126,
|
||||
(UInt16) 0x012c,
|
||||
(UInt16) 0x8129,
|
||||
(UInt16) 0x0138,
|
||||
(UInt16) 0x813d,
|
||||
(UInt16) 0x8137,
|
||||
(UInt16) 0x0132,
|
||||
(UInt16) 0x0110,
|
||||
(UInt16) 0x8115,
|
||||
(UInt16) 0x811f,
|
||||
(UInt16) 0x011a,
|
||||
(UInt16) 0x810b,
|
||||
(UInt16) 0x010e,
|
||||
(UInt16) 0x0104,
|
||||
(UInt16) 0x8101,
|
||||
(UInt16) 0x8303,
|
||||
(UInt16) 0x0306,
|
||||
(UInt16) 0x030c,
|
||||
(UInt16) 0x8309,
|
||||
(UInt16) 0x0318,
|
||||
(UInt16) 0x831d,
|
||||
(UInt16) 0x8317,
|
||||
(UInt16) 0x0312,
|
||||
(UInt16) 0x0330,
|
||||
(UInt16) 0x8335,
|
||||
(UInt16) 0x833f,
|
||||
(UInt16) 0x033a,
|
||||
(UInt16) 0x832b,
|
||||
(UInt16) 0x032e,
|
||||
(UInt16) 0x0324,
|
||||
(UInt16) 0x8321,
|
||||
(UInt16) 0x0360,
|
||||
(UInt16) 0x8365,
|
||||
(UInt16) 0x836f,
|
||||
(UInt16) 0x036a,
|
||||
(UInt16) 0x837b,
|
||||
(UInt16) 0x037e,
|
||||
(UInt16) 0x0374,
|
||||
(UInt16) 0x8371,
|
||||
(UInt16) 0x8353,
|
||||
(UInt16) 0x0356,
|
||||
(UInt16) 0x035c,
|
||||
(UInt16) 0x8359,
|
||||
(UInt16) 0x0348,
|
||||
(UInt16) 0x834d,
|
||||
(UInt16) 0x8347,
|
||||
(UInt16) 0x0342,
|
||||
(UInt16) 0x03c0,
|
||||
(UInt16) 0x83c5,
|
||||
(UInt16) 0x83cf,
|
||||
(UInt16) 0x03ca,
|
||||
(UInt16) 0x83db,
|
||||
(UInt16) 0x03de,
|
||||
(UInt16) 0x03d4,
|
||||
(UInt16) 0x83d1,
|
||||
(UInt16) 0x83f3,
|
||||
(UInt16) 0x03f6,
|
||||
(UInt16) 0x03fc,
|
||||
(UInt16) 0x83f9,
|
||||
(UInt16) 0x03e8,
|
||||
(UInt16) 0x83ed,
|
||||
(UInt16) 0x83e7,
|
||||
(UInt16) 0x03e2,
|
||||
(UInt16) 0x83a3,
|
||||
(UInt16) 0x03a6,
|
||||
(UInt16) 0x03ac,
|
||||
(UInt16) 0x83a9,
|
||||
(UInt16) 0x03b8,
|
||||
(UInt16) 0x83bd,
|
||||
(UInt16) 0x83b7,
|
||||
(UInt16) 0x03b2,
|
||||
(UInt16) 0x0390,
|
||||
(UInt16) 0x8395,
|
||||
(UInt16) 0x839f,
|
||||
(UInt16) 0x039a,
|
||||
(UInt16) 0x838b,
|
||||
(UInt16) 0x038e,
|
||||
(UInt16) 0x0384,
|
||||
(UInt16) 0x8381,
|
||||
(UInt16) 0x0280,
|
||||
(UInt16) 0x8285,
|
||||
(UInt16) 0x828f,
|
||||
(UInt16) 0x028a,
|
||||
(UInt16) 0x829b,
|
||||
(UInt16) 0x029e,
|
||||
(UInt16) 0x0294,
|
||||
(UInt16) 0x8291,
|
||||
(UInt16) 0x82b3,
|
||||
(UInt16) 0x02b6,
|
||||
(UInt16) 0x02bc,
|
||||
(UInt16) 0x82b9,
|
||||
(UInt16) 0x02a8,
|
||||
(UInt16) 0x82ad,
|
||||
(UInt16) 0x82a7,
|
||||
(UInt16) 0x02a2,
|
||||
(UInt16) 0x82e3,
|
||||
(UInt16) 0x02e6,
|
||||
(UInt16) 0x02ec,
|
||||
(UInt16) 0x82e9,
|
||||
(UInt16) 0x02f8,
|
||||
(UInt16) 0x82fd,
|
||||
(UInt16) 0x82f7,
|
||||
(UInt16) 0x02f2,
|
||||
(UInt16) 0x02d0,
|
||||
(UInt16) 0x82d5,
|
||||
(UInt16) 0x82df,
|
||||
(UInt16) 0x02da,
|
||||
(UInt16) 0x82cb,
|
||||
(UInt16) 0x02ce,
|
||||
(UInt16) 0x02c4,
|
||||
(UInt16) 0x82c1,
|
||||
(UInt16) 0x8243,
|
||||
(UInt16) 0x0246,
|
||||
(UInt16) 0x024c,
|
||||
(UInt16) 0x8249,
|
||||
(UInt16) 0x0258,
|
||||
(UInt16) 0x825d,
|
||||
(UInt16) 0x8257,
|
||||
(UInt16) 0x0252,
|
||||
(UInt16) 0x0270,
|
||||
(UInt16) 0x8275,
|
||||
(UInt16) 0x827f,
|
||||
(UInt16) 0x027a,
|
||||
(UInt16) 0x826b,
|
||||
(UInt16) 0x026e,
|
||||
(UInt16) 0x0264,
|
||||
(UInt16) 0x8261,
|
||||
(UInt16) 0x0220,
|
||||
(UInt16) 0x8225,
|
||||
(UInt16) 0x822f,
|
||||
(UInt16) 0x022a,
|
||||
(UInt16) 0x823b,
|
||||
(UInt16) 0x023e,
|
||||
(UInt16) 0x0234,
|
||||
(UInt16) 0x8231,
|
||||
(UInt16) 0x8213,
|
||||
(UInt16) 0x0216,
|
||||
(UInt16) 0x021c,
|
||||
(UInt16) 0x8219,
|
||||
(UInt16) 0x0208,
|
||||
(UInt16) 0x820d,
|
||||
(UInt16) 0x8207,
|
||||
(UInt16) 0x0202
|
||||
};
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Update the CRC with the byte data.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte data</param>
|
||||
/// <param name="crc">The starting CRC value</param>
|
||||
/// <returns>The updated CRC value</returns>
|
||||
public static UInt16 Update(byte data, UInt16 crc)
|
||||
{
|
||||
crc = (UInt16)((crc << 8) ^ Crc16Table[((crc >> 8) ^ data) & 0xff]);
|
||||
return crc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the CRC with the byte array data.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte array data</param>
|
||||
/// <param name="len">The byte array length</param>
|
||||
/// <param name="crc">The starting CRC value</param>
|
||||
/// <returns>The updated CRC value</returns>
|
||||
public static UInt16 UpdateBlock(byte[] data, int len, UInt16 crc)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
crc = (UInt16)((crc << 8) ^ Crc16Table[(crc >> 8) ^ data[i]]);
|
||||
return crc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the CRC over a byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte data</param>
|
||||
/// <param name="len">The byte array length</param>
|
||||
/// <returns>The calculated CRC value</returns>
|
||||
public static UInt16 Calculate(byte[] data, int len)
|
||||
{
|
||||
UInt16 crc = 0;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
crc = (UInt16)((crc << 8) ^ Crc16Table[(crc >> 8) ^ data[i]]);
|
||||
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
}
|
319
Flac/Flac/Util/CRC8.cs
Normal file
319
Flac/Flac/Util/CRC8.cs
Normal file
@ -0,0 +1,319 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Flac.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility class to calculate 8-bit CRC.
|
||||
/// </summary>
|
||||
public static class CRC8
|
||||
{
|
||||
#region private static UInt16[] Crc16Table
|
||||
|
||||
// CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0
|
||||
private static byte[] Crc8Table =
|
||||
new byte[] {
|
||||
(byte) 0x00,
|
||||
(byte) 0x07,
|
||||
(byte) 0x0E,
|
||||
(byte) 0x09,
|
||||
(byte) 0x1C,
|
||||
(byte) 0x1B,
|
||||
(byte) 0x12,
|
||||
(byte) 0x15,
|
||||
(byte) 0x38,
|
||||
(byte) 0x3F,
|
||||
(byte) 0x36,
|
||||
(byte) 0x31,
|
||||
(byte) 0x24,
|
||||
(byte) 0x23,
|
||||
(byte) 0x2A,
|
||||
(byte) 0x2D,
|
||||
(byte) 0x70,
|
||||
(byte) 0x77,
|
||||
(byte) 0x7E,
|
||||
(byte) 0x79,
|
||||
(byte) 0x6C,
|
||||
(byte) 0x6B,
|
||||
(byte) 0x62,
|
||||
(byte) 0x65,
|
||||
(byte) 0x48,
|
||||
(byte) 0x4F,
|
||||
(byte) 0x46,
|
||||
(byte) 0x41,
|
||||
(byte) 0x54,
|
||||
(byte) 0x53,
|
||||
(byte) 0x5A,
|
||||
(byte) 0x5D,
|
||||
(byte) 0xE0,
|
||||
(byte) 0xE7,
|
||||
(byte) 0xEE,
|
||||
(byte) 0xE9,
|
||||
(byte) 0xFC,
|
||||
(byte) 0xFB,
|
||||
(byte) 0xF2,
|
||||
(byte) 0xF5,
|
||||
(byte) 0xD8,
|
||||
(byte) 0xDF,
|
||||
(byte) 0xD6,
|
||||
(byte) 0xD1,
|
||||
(byte) 0xC4,
|
||||
(byte) 0xC3,
|
||||
(byte) 0xCA,
|
||||
(byte) 0xCD,
|
||||
(byte) 0x90,
|
||||
(byte) 0x97,
|
||||
(byte) 0x9E,
|
||||
(byte) 0x99,
|
||||
(byte) 0x8C,
|
||||
(byte) 0x8B,
|
||||
(byte) 0x82,
|
||||
(byte) 0x85,
|
||||
(byte) 0xA8,
|
||||
(byte) 0xAF,
|
||||
(byte) 0xA6,
|
||||
(byte) 0xA1,
|
||||
(byte) 0xB4,
|
||||
(byte) 0xB3,
|
||||
(byte) 0xBA,
|
||||
(byte) 0xBD,
|
||||
(byte) 0xC7,
|
||||
(byte) 0xC0,
|
||||
(byte) 0xC9,
|
||||
(byte) 0xCE,
|
||||
(byte) 0xDB,
|
||||
(byte) 0xDC,
|
||||
(byte) 0xD5,
|
||||
(byte) 0xD2,
|
||||
(byte) 0xFF,
|
||||
(byte) 0xF8,
|
||||
(byte) 0xF1,
|
||||
(byte) 0xF6,
|
||||
(byte) 0xE3,
|
||||
(byte) 0xE4,
|
||||
(byte) 0xED,
|
||||
(byte) 0xEA,
|
||||
(byte) 0xB7,
|
||||
(byte) 0xB0,
|
||||
(byte) 0xB9,
|
||||
(byte) 0xBE,
|
||||
(byte) 0xAB,
|
||||
(byte) 0xAC,
|
||||
(byte) 0xA5,
|
||||
(byte) 0xA2,
|
||||
(byte) 0x8F,
|
||||
(byte) 0x88,
|
||||
(byte) 0x81,
|
||||
(byte) 0x86,
|
||||
(byte) 0x93,
|
||||
(byte) 0x94,
|
||||
(byte) 0x9D,
|
||||
(byte) 0x9A,
|
||||
(byte) 0x27,
|
||||
(byte) 0x20,
|
||||
(byte) 0x29,
|
||||
(byte) 0x2E,
|
||||
(byte) 0x3B,
|
||||
(byte) 0x3C,
|
||||
(byte) 0x35,
|
||||
(byte) 0x32,
|
||||
(byte) 0x1F,
|
||||
(byte) 0x18,
|
||||
(byte) 0x11,
|
||||
(byte) 0x16,
|
||||
(byte) 0x03,
|
||||
(byte) 0x04,
|
||||
(byte) 0x0D,
|
||||
(byte) 0x0A,
|
||||
(byte) 0x57,
|
||||
(byte) 0x50,
|
||||
(byte) 0x59,
|
||||
(byte) 0x5E,
|
||||
(byte) 0x4B,
|
||||
(byte) 0x4C,
|
||||
(byte) 0x45,
|
||||
(byte) 0x42,
|
||||
(byte) 0x6F,
|
||||
(byte) 0x68,
|
||||
(byte) 0x61,
|
||||
(byte) 0x66,
|
||||
(byte) 0x73,
|
||||
(byte) 0x74,
|
||||
(byte) 0x7D,
|
||||
(byte) 0x7A,
|
||||
(byte) 0x89,
|
||||
(byte) 0x8E,
|
||||
(byte) 0x87,
|
||||
(byte) 0x80,
|
||||
(byte) 0x95,
|
||||
(byte) 0x92,
|
||||
(byte) 0x9B,
|
||||
(byte) 0x9C,
|
||||
(byte) 0xB1,
|
||||
(byte) 0xB6,
|
||||
(byte) 0xBF,
|
||||
(byte) 0xB8,
|
||||
(byte) 0xAD,
|
||||
(byte) 0xAA,
|
||||
(byte) 0xA3,
|
||||
(byte) 0xA4,
|
||||
(byte) 0xF9,
|
||||
(byte) 0xFE,
|
||||
(byte) 0xF7,
|
||||
(byte) 0xF0,
|
||||
(byte) 0xE5,
|
||||
(byte) 0xE2,
|
||||
(byte) 0xEB,
|
||||
(byte) 0xEC,
|
||||
(byte) 0xC1,
|
||||
(byte) 0xC6,
|
||||
(byte) 0xCF,
|
||||
(byte) 0xC8,
|
||||
(byte) 0xDD,
|
||||
(byte) 0xDA,
|
||||
(byte) 0xD3,
|
||||
(byte) 0xD4,
|
||||
(byte) 0x69,
|
||||
(byte) 0x6E,
|
||||
(byte) 0x67,
|
||||
(byte) 0x60,
|
||||
(byte) 0x75,
|
||||
(byte) 0x72,
|
||||
(byte) 0x7B,
|
||||
(byte) 0x7C,
|
||||
(byte) 0x51,
|
||||
(byte) 0x56,
|
||||
(byte) 0x5F,
|
||||
(byte) 0x58,
|
||||
(byte) 0x4D,
|
||||
(byte) 0x4A,
|
||||
(byte) 0x43,
|
||||
(byte) 0x44,
|
||||
(byte) 0x19,
|
||||
(byte) 0x1E,
|
||||
(byte) 0x17,
|
||||
(byte) 0x10,
|
||||
(byte) 0x05,
|
||||
(byte) 0x02,
|
||||
(byte) 0x0B,
|
||||
(byte) 0x0C,
|
||||
(byte) 0x21,
|
||||
(byte) 0x26,
|
||||
(byte) 0x2F,
|
||||
(byte) 0x28,
|
||||
(byte) 0x3D,
|
||||
(byte) 0x3A,
|
||||
(byte) 0x33,
|
||||
(byte) 0x34,
|
||||
(byte) 0x4E,
|
||||
(byte) 0x49,
|
||||
(byte) 0x40,
|
||||
(byte) 0x47,
|
||||
(byte) 0x52,
|
||||
(byte) 0x55,
|
||||
(byte) 0x5C,
|
||||
(byte) 0x5B,
|
||||
(byte) 0x76,
|
||||
(byte) 0x71,
|
||||
(byte) 0x78,
|
||||
(byte) 0x7F,
|
||||
(byte) 0x6A,
|
||||
(byte) 0x6D,
|
||||
(byte) 0x64,
|
||||
(byte) 0x63,
|
||||
(byte) 0x3E,
|
||||
(byte) 0x39,
|
||||
(byte) 0x30,
|
||||
(byte) 0x37,
|
||||
(byte) 0x22,
|
||||
(byte) 0x25,
|
||||
(byte) 0x2C,
|
||||
(byte) 0x2B,
|
||||
(byte) 0x06,
|
||||
(byte) 0x01,
|
||||
(byte) 0x08,
|
||||
(byte) 0x0F,
|
||||
(byte) 0x1A,
|
||||
(byte) 0x1D,
|
||||
(byte) 0x14,
|
||||
(byte) 0x13,
|
||||
(byte) 0xAE,
|
||||
(byte) 0xA9,
|
||||
(byte) 0xA0,
|
||||
(byte) 0xA7,
|
||||
(byte) 0xB2,
|
||||
(byte) 0xB5,
|
||||
(byte) 0xBC,
|
||||
(byte) 0xBB,
|
||||
(byte) 0x96,
|
||||
(byte) 0x91,
|
||||
(byte) 0x98,
|
||||
(byte) 0x9F,
|
||||
(byte) 0x8A,
|
||||
(byte) 0x8D,
|
||||
(byte) 0x84,
|
||||
(byte) 0x83,
|
||||
(byte) 0xDE,
|
||||
(byte) 0xD9,
|
||||
(byte) 0xD0,
|
||||
(byte) 0xD7,
|
||||
(byte) 0xC2,
|
||||
(byte) 0xC5,
|
||||
(byte) 0xCC,
|
||||
(byte) 0xCB,
|
||||
(byte) 0xE6,
|
||||
(byte) 0xE1,
|
||||
(byte) 0xE8,
|
||||
(byte) 0xEF,
|
||||
(byte) 0xFA,
|
||||
(byte) 0xFD,
|
||||
(byte) 0xF4,
|
||||
(byte) 0xF3
|
||||
};
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Update the CRC with the byte data.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte data</param>
|
||||
/// <param name="crc">The starting CRC value</param>
|
||||
/// <returns>The updated CRC value</returns>
|
||||
public static byte Update(byte data, byte crc)
|
||||
{
|
||||
return Crc8Table[crc ^ data];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the CRC with the byte array data.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte array data</param>
|
||||
/// <param name="len">The byte array length</param>
|
||||
/// <param name="crc">The starting CRC value</param>
|
||||
/// <returns>The updated CRC value</returns>
|
||||
public static byte UpdateBlock(byte[] data, int len, byte crc)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
crc = Crc8Table[crc ^ data[i]];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the CRC over a byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte data</param>
|
||||
/// <param name="len">The byte array length</param>
|
||||
/// <returns>The calculated CRC value</returns>
|
||||
public static byte Calculate(byte[] data, int len)
|
||||
{
|
||||
byte crc = 0;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
crc = Crc8Table[crc ^ data[i]];
|
||||
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
}
|
350
LICENSE
350
LICENSE
@ -1,339 +1,17 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
libFLAC - Free Lossless Audio Codec library
|
||||
Copyright (C) 2000,2001,2002,2003 Josh Coalson
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
Preamble
|
||||
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
|
||||
Library General Public License for more details.
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
You should have received a copy of the GNU Library 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.
|
Loading…
Reference in New Issue
Block a user