mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 10:04:24 +00:00
Use libFLAC_dynamic.dll instead of using a static library. Update libFLAC to 1.3.2
This commit is contained in:
29
CUETools.Codecs.libFLAC/CUETools.Codecs.libFLAC.csproj
Normal file
29
CUETools.Codecs.libFLAC/CUETools.Codecs.libFLAC.csproj
Normal file
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net40;net20;netstandard2.0</TargetFrameworks>
|
||||
<Version>2.1.6.0</Version>
|
||||
<AssemblyName>CUETools.Codecs.libFLAC</AssemblyName>
|
||||
<RootNamespace>CUETools.Codecs.libFLAC</RootNamespace>
|
||||
<Product>CUETools</Product>
|
||||
<Description>A library for encoding flac using official encoder.</Description>
|
||||
<Copyright>Copyright (c) 2008-2018 Grigory Chudov</Copyright>
|
||||
<Authors>Grigory Chudov</Authors>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<OutputPath>..\bin\$(Configuration)\plugins</OutputPath>
|
||||
<RepositoryUrl>https://github.com/gchudov/cuetools.net</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<Company />
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ProjectReference>
|
||||
<Private>False</Private>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
166
CUETools.Codecs.libFLAC/FLACDLL.cs
Normal file
166
CUETools.Codecs.libFLAC/FLACDLL.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CUETools.Codecs.libFLAC
|
||||
{
|
||||
internal unsafe static class FLACDLL
|
||||
{
|
||||
internal const string libFLACDll = "libFLAC_dynamic";
|
||||
internal const CallingConvention libFLACCallingConvention = CallingConvention.Cdecl;
|
||||
internal const int FLAC__MAX_CHANNELS = 8;
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr LoadLibrary(string dllToLoad);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamDecoderReadStatus FLAC__StreamDecoderReadCallback(IntPtr decoder, byte* buffer, ref long bytes, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamDecoderSeekStatus FLAC__StreamDecoderSeekCallback(IntPtr decoder, long absolute_byte_offset, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamDecoderTellStatus FLAC__StreamDecoderTellCallback(IntPtr decoder, out long absolute_byte_offset, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamDecoderLengthStatus FLAC__StreamDecoderLengthCallback(IntPtr decoder, out long stream_length, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate int FLAC__StreamDecoderEofCallback(IntPtr decoder, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamDecoderWriteStatus FLAC__StreamDecoderWriteCallback(IntPtr decoder, FLAC__Frame* frame, int** buffer, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FLAC__StreamDecoderMetadataCallback(IntPtr decoder, FLAC__StreamMetadata* metadata, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FLAC__StreamDecoderErrorCallback(IntPtr decoder, FLAC__StreamDecoderErrorStatus status, void* client_data);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern IntPtr FLAC__stream_decoder_new();
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_decoder_set_metadata_respond(IntPtr decoder, FLAC__MetadataType type);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_decoder_process_until_end_of_metadata(IntPtr decoder);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
|
||||
IntPtr decoder,
|
||||
FLAC__StreamDecoderReadCallback read_callback,
|
||||
FLAC__StreamDecoderSeekCallback seek_callback,
|
||||
FLAC__StreamDecoderTellCallback tell_callback,
|
||||
FLAC__StreamDecoderLengthCallback length_callback,
|
||||
FLAC__StreamDecoderEofCallback eof_callback,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void* client_data
|
||||
);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_decoder_finish(IntPtr decoder);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_decoder_delete(IntPtr decoder);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_decoder_seek_absolute(IntPtr decoder, long sample);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern FLAC__StreamDecoderState FLAC__stream_decoder_get_state(IntPtr decoder);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_decoder_process_single(IntPtr decoder);
|
||||
|
||||
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern IntPtr FLAC__stream_encoder_new();
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_bits_per_sample(IntPtr encoder, uint value);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_sample_rate(IntPtr encoder, uint value);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_channels(IntPtr encoder, uint value);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_finish(IntPtr encoder);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_delete(IntPtr encoder);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_process_interleaved(IntPtr encoder, int* buffer, int samples);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern FLAC__StreamEncoderState FLAC__stream_encoder_get_state(IntPtr encoder);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern void FLAC__stream_encoder_get_verify_decoder_error_stats(IntPtr encoder, out ulong absolute_sample, out uint frame_number, out uint channel, out uint sample, out int expected, out int got);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern FLAC__StreamMetadata* FLAC__metadata_object_new(FLAC__MetadataType type);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata* metadata, int samples, long total_samples);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata* metadata, int compact);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_metadata(IntPtr encoder, FLAC__StreamMetadata** metadata, int num_blocks);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_verify(IntPtr encoder, int value);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_do_md5(IntPtr encoder, int value);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_total_samples_estimate(IntPtr encoder, long value);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_compression_level(IntPtr encoder, int value);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern int FLAC__stream_encoder_set_blocksize(IntPtr encoder, int value);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamEncoderWriteStatus FLAC__StreamEncoderWriteCallback(IntPtr encoder, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer, long bytes, int samples, int current_frame, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamEncoderSeekStatus FLAC__StreamEncoderSeekCallback(IntPtr encoder, long absolute_byte_offset, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate FLAC__StreamEncoderTellStatus FLAC__StreamEncoderTellCallback(IntPtr encoder, out long absolute_byte_offset, void* client_data);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void FLAC__StreamEncoderMetadataCallback(IntPtr encoder, FLAC__StreamMetadata* metadata, void* client_data);
|
||||
|
||||
[DllImport(libFLACDll, CallingConvention = libFLACCallingConvention)]
|
||||
internal static extern FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(IntPtr encoder,
|
||||
FLAC__StreamEncoderWriteCallback write_callback,
|
||||
FLAC__StreamEncoderSeekCallback seek_callback,
|
||||
FLAC__StreamEncoderTellCallback tell_callback,
|
||||
FLAC__StreamEncoderMetadataCallback metadata_callback,
|
||||
void* client_data);
|
||||
|
||||
static FLACDLL()
|
||||
{
|
||||
var myPath = new Uri(typeof(FLACDLL).Assembly.CodeBase).LocalPath;
|
||||
var myFolder = System.IO.Path.GetDirectoryName(myPath);
|
||||
var is64 = IntPtr.Size == 8;
|
||||
var subfolder = is64 ? "plugins (x64)" : "plugins (win32)";
|
||||
#if NET40
|
||||
LoadLibrary(System.IO.Path.Combine(myFolder, "..", subfolder, libFLACDll + ".dll"));
|
||||
#else
|
||||
LoadLibrary(System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(myFolder, ".."), subfolder), libFLACDll + ".dll"));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
364
CUETools.Codecs.libFLAC/Reader.cs
Normal file
364
CUETools.Codecs.libFLAC/Reader.cs
Normal file
@@ -0,0 +1,364 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using CUETools.Codecs;
|
||||
|
||||
namespace CUETools.Codecs.libFLAC.Reader
|
||||
{
|
||||
[AudioDecoderClass("libFLAC", "flac", 1)]
|
||||
public unsafe class Reader : IAudioSource
|
||||
{
|
||||
public Reader(string path, Stream IO)
|
||||
{
|
||||
m_writeCallback = WriteCallback;
|
||||
m_metadataCallback = MetadataCallback;
|
||||
m_errorCallback = ErrorCallback;
|
||||
m_readCallback = ReadCallback;
|
||||
m_seekCallback = SeekCallback;
|
||||
m_tellCallback = TellCallback;
|
||||
m_lengthCallback = LengthCallback;
|
||||
m_eofCallback = EofCallback;
|
||||
|
||||
m_decoderActive = false;
|
||||
|
||||
m_sampleOffset = 0;
|
||||
m_sampleBuffer = null;
|
||||
m_path = path;
|
||||
m_bufferOffset = 0;
|
||||
m_bufferLength = 0;
|
||||
|
||||
m_stream = (IO != null) ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
|
||||
m_decoder = FLACDLL.FLAC__stream_decoder_new();
|
||||
|
||||
if (0 == FLACDLL.FLAC__stream_decoder_set_metadata_respond(m_decoder, FLAC__MetadataType.FLAC__METADATA_TYPE_VORBIS_COMMENT))
|
||||
throw new Exception("unable to setup the decoder");
|
||||
|
||||
FLAC__StreamDecoderInitStatus st = FLACDLL.FLAC__stream_decoder_init_stream(
|
||||
m_decoder, m_readCallback,
|
||||
m_stream.CanSeek ? m_seekCallback : null,
|
||||
m_stream.CanSeek ? m_tellCallback : null,
|
||||
m_stream.CanSeek ? m_lengthCallback : null,
|
||||
m_stream.CanSeek ? m_eofCallback : null,
|
||||
m_writeCallback, m_metadataCallback, m_errorCallback, null);
|
||||
|
||||
if (st != FLAC__StreamDecoderInitStatus.FLAC__STREAM_DECODER_INIT_STATUS_OK)
|
||||
throw new Exception(string.Format("unable to initialize the decoder: {0}", st));
|
||||
|
||||
m_decoderActive = true;
|
||||
|
||||
if (0 == FLACDLL.FLAC__stream_decoder_process_until_end_of_metadata(m_decoder))
|
||||
throw new Exception("unable to retrieve metadata");
|
||||
}
|
||||
|
||||
#if SUPPORTMETADATA
|
||||
bool UpdateTags (bool preserveTime)
|
||||
{
|
||||
Close ();
|
||||
|
||||
FLAC__Metadata_Chain* chain = FLAC__metadata_chain_new ();
|
||||
if (!chain) return false;
|
||||
|
||||
IntPtr pathChars = Marshal::StringToHGlobalAnsi(_path);
|
||||
int res = FLAC__metadata_chain_read (chain, (const char*)pathChars.ToPointer());
|
||||
Marshal::FreeHGlobal(pathChars);
|
||||
if (!res) {
|
||||
FLAC__metadata_chain_delete (chain);
|
||||
return false;
|
||||
}
|
||||
FLAC__Metadata_Iterator* i = FLAC__metadata_iterator_new ();
|
||||
FLAC__metadata_iterator_init (i, chain);
|
||||
do {
|
||||
FLAC__StreamMetadata* metadata = FLAC__metadata_iterator_get_block (i);
|
||||
if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
|
||||
FLAC__metadata_iterator_delete_block (i, false);
|
||||
} while (FLAC__metadata_iterator_next (i));
|
||||
|
||||
FLAC__StreamMetadata * vorbiscomment = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
for (int tagno = 0; tagno <_tags->Count; tagno++)
|
||||
{
|
||||
String ^ tag_name = _tags->GetKey(tagno);
|
||||
int tag_len = tag_name->Length;
|
||||
char * tag = new char [tag_len + 1];
|
||||
IntPtr nameChars = Marshal::StringToHGlobalAnsi(tag_name);
|
||||
memcpy (tag, (const char*)nameChars.ToPointer(), tag_len);
|
||||
Marshal::FreeHGlobal(nameChars);
|
||||
tag[tag_len] = 0;
|
||||
|
||||
array<string>^ tag_values = _tags->GetValues(tagno);
|
||||
for (int valno = 0; valno < tag_values->Length; valno++)
|
||||
{
|
||||
UTF8Encoding^ enc = new UTF8Encoding();
|
||||
array<Byte>^ value_array = enc->GetBytes (tag_values[valno]);
|
||||
int value_len = value_array->Length;
|
||||
char * value = new char [value_len + 1];
|
||||
Marshal::Copy (value_array, 0, (IntPtr) value, value_len);
|
||||
value[value_len] = 0;
|
||||
|
||||
FLAC__StreamMetadata_VorbisComment_Entry entry;
|
||||
/* create and entry and append it */
|
||||
if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, tag, value)) {
|
||||
throw new Exception("Unable to add tags, must be valid utf8.");
|
||||
}
|
||||
if(!FLAC__metadata_object_vorbiscomment_append_comment(vorbiscomment, entry, /*copy=*/false)) {
|
||||
throw new Exception("Unable to add tags.");
|
||||
}
|
||||
delete [] value;
|
||||
}
|
||||
delete [] tag;
|
||||
}
|
||||
|
||||
FLAC__metadata_iterator_insert_block_after (i, vorbiscomment);
|
||||
FLAC__metadata_iterator_delete (i);
|
||||
FLAC__metadata_chain_sort_padding (chain);
|
||||
res = FLAC__metadata_chain_write (chain, true, preserveTime);
|
||||
FLAC__metadata_chain_delete (chain);
|
||||
return 0 != res;
|
||||
}
|
||||
#endif
|
||||
|
||||
FLAC__StreamDecoderWriteStatus WriteCallback(IntPtr decoder,
|
||||
FLAC__Frame* frame, int** buffer, void* client_data)
|
||||
{
|
||||
int sampleCount = frame->header.blocksize;
|
||||
|
||||
if (m_bufferLength > 0)
|
||||
throw new Exception("received unrequested samples");
|
||||
|
||||
if ((frame->header.bits_per_sample != m_pcm.BitsPerSample) ||
|
||||
(frame->header.channels != m_pcm.ChannelCount) ||
|
||||
(frame->header.sample_rate != m_pcm.SampleRate))
|
||||
throw new Exception("format changes within a file are not allowed");
|
||||
|
||||
if (m_bufferOffset != 0)
|
||||
throw new Exception("internal buffer error");
|
||||
|
||||
if (m_sampleBuffer == null || m_sampleBuffer.Size < sampleCount)
|
||||
m_sampleBuffer = new AudioBuffer(m_pcm, sampleCount);
|
||||
m_sampleBuffer.Length = sampleCount;
|
||||
|
||||
if (m_pcm.ChannelCount == 2)
|
||||
m_sampleBuffer.Interlace(0, (int*)buffer[0], (int*)buffer[1], sampleCount);
|
||||
else
|
||||
{
|
||||
int _channelCount = m_pcm.ChannelCount;
|
||||
for (Int32 iChan = 0; iChan < _channelCount; iChan++)
|
||||
{
|
||||
fixed (int* pMyBuffer = &m_sampleBuffer.Samples[0, iChan])
|
||||
{
|
||||
int* pMyBufferPtr = pMyBuffer;
|
||||
int* pFLACBuffer = buffer[iChan];
|
||||
int* pFLACBufferEnd = pFLACBuffer + sampleCount;
|
||||
while (pFLACBuffer < pFLACBufferEnd)
|
||||
{
|
||||
*pMyBufferPtr = *pFLACBuffer;
|
||||
pMyBufferPtr += _channelCount;
|
||||
pFLACBuffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_bufferLength = sampleCount;
|
||||
m_sampleOffset += m_bufferLength;
|
||||
return FLAC__StreamDecoderWriteStatus.FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
void MetadataCallback(IntPtr decoder,
|
||||
FLAC__StreamMetadata *metadata, void *client_data)
|
||||
{
|
||||
if (metadata->type == FLAC__MetadataType.FLAC__METADATA_TYPE_STREAMINFO)
|
||||
{
|
||||
m_pcm = new AudioPCMConfig(
|
||||
metadata->stream_info.bits_per_sample,
|
||||
metadata->stream_info.channels,
|
||||
metadata->stream_info.sample_rate,
|
||||
(AudioPCMConfig.SpeakerConfig)0);
|
||||
m_sampleCount = metadata->stream_info.total_samples;
|
||||
}
|
||||
#if SUPPORTMETADATA
|
||||
if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
|
||||
{
|
||||
for (int tagno = 0; tagno < metadata->vorbis_comment.num_comments; tagno ++)
|
||||
{
|
||||
char * field_name, * field_value;
|
||||
if(!FLACDLL.FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(metadata->vorbis_comment.comments[tagno], &field_name, &field_value))
|
||||
throw new Exception("Unable to parse vorbis comment.");
|
||||
string name = Marshal::PtrToStringAnsi ((IntPtr) field_name);
|
||||
free (field_name);
|
||||
array<Byte>^ bvalue = new array<Byte>((int) strlen (field_value));
|
||||
Marshal.Copy ((IntPtr) field_value, bvalue, 0, (int) strlen (field_value));
|
||||
free (field_value);
|
||||
UTF8Encoding enc = new UTF8Encoding();
|
||||
string value = enc.GetString(bvalue);
|
||||
_tags.Add(name, value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ErrorCallback(IntPtr decoder,
|
||||
FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case FLAC__StreamDecoderErrorStatus.FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
|
||||
throw new Exception("synchronization was lost");
|
||||
case FLAC__StreamDecoderErrorStatus.FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
|
||||
throw new Exception("encountered a corrupted frame header");
|
||||
case FLAC__StreamDecoderErrorStatus.FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
|
||||
throw new Exception("frame CRC mismatch");
|
||||
default:
|
||||
throw new Exception("an unknown error has occurred");
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderReadStatus ReadCallback(IntPtr decoder, byte* buffer, ref long bytes, void* client_data)
|
||||
{
|
||||
if (bytes <= 0 || bytes > int.MaxValue)
|
||||
return FLAC__StreamDecoderReadStatus.FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
|
||||
|
||||
if (m_readBuffer == null || m_readBuffer.Length < bytes)
|
||||
m_readBuffer = new byte[Math.Max(bytes, 0x4000)];
|
||||
|
||||
bytes = m_stream.Read(m_readBuffer, 0, (int)bytes);
|
||||
//if(ferror(decoder->private_->file))
|
||||
//return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
//else
|
||||
if (bytes == 0)
|
||||
return FLAC__StreamDecoderReadStatus.FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
|
||||
Marshal.Copy(m_readBuffer, 0, (IntPtr)buffer, (int)bytes);
|
||||
return FLAC__StreamDecoderReadStatus.FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderSeekStatus SeekCallback(IntPtr decoder, long absolute_byte_offset, void* client_data)
|
||||
{
|
||||
//if (!_IO.CanSeek)
|
||||
// return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
|
||||
m_stream.Position = absolute_byte_offset;
|
||||
//catch(Exception) {
|
||||
// return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
//}
|
||||
return FLAC__StreamDecoderSeekStatus.FLAC__STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderTellStatus TellCallback(IntPtr decoder, out long absolute_byte_offset, void* client_data)
|
||||
{
|
||||
//if (!_IO.CanSeek)
|
||||
// return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
|
||||
absolute_byte_offset = m_stream.Position;
|
||||
// if (_IO.Position < 0)
|
||||
// return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
return FLAC__StreamDecoderTellStatus.FLAC__STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderLengthStatus LengthCallback(IntPtr decoder, out long stream_length, void* client_data)
|
||||
{
|
||||
//if (!_IO.CanSeek)
|
||||
// return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
|
||||
// if (_IO.Length < 0)
|
||||
// return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
stream_length = m_stream.Length;
|
||||
return FLAC__StreamDecoderLengthStatus.FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
|
||||
int EofCallback (IntPtr decoder, void *client_data)
|
||||
{
|
||||
return m_stream.Position == m_stream.Length ? 1 : 0;
|
||||
}
|
||||
|
||||
public AudioDecoderSettings Settings => null;
|
||||
|
||||
public AudioPCMConfig PCM => m_pcm;
|
||||
|
||||
public string Path => m_path;
|
||||
|
||||
public long Length => m_sampleCount;
|
||||
|
||||
private int SamplesInBuffer => m_bufferLength - m_bufferOffset;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get => m_sampleOffset - SamplesInBuffer;
|
||||
|
||||
set
|
||||
{
|
||||
m_sampleOffset = value;
|
||||
m_bufferOffset = 0;
|
||||
m_bufferLength = 0;
|
||||
if (0 == FLACDLL.FLAC__stream_decoder_seek_absolute(m_decoder, value))
|
||||
throw new Exception("unable to seek");
|
||||
}
|
||||
}
|
||||
|
||||
public long Remaining { get => m_sampleCount - Position; }
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (m_decoderActive)
|
||||
{
|
||||
FLACDLL.FLAC__stream_decoder_finish(m_decoder);
|
||||
FLACDLL.FLAC__stream_decoder_delete(m_decoder);
|
||||
m_decoderActive = false;
|
||||
}
|
||||
if (m_stream != null)
|
||||
{
|
||||
m_stream.Close();
|
||||
m_stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
buff.Prepare(this, maxLength);
|
||||
int buffOffset = 0;
|
||||
int samplesNeeded = buff.Length;
|
||||
|
||||
while (samplesNeeded != 0)
|
||||
{
|
||||
if (SamplesInBuffer == 0)
|
||||
{
|
||||
m_bufferOffset = 0;
|
||||
m_bufferLength = 0;
|
||||
do
|
||||
{
|
||||
if (FLACDLL.FLAC__stream_decoder_get_state(m_decoder) == FLAC__StreamDecoderState.FLAC__STREAM_DECODER_END_OF_STREAM)
|
||||
{
|
||||
buff.Length -= samplesNeeded;
|
||||
return buff.Length;
|
||||
}
|
||||
if (0 == FLACDLL.FLAC__stream_decoder_process_single(m_decoder))
|
||||
throw new Exception(string.Format("an error occurred while decoding: {0}", FLACDLL.FLAC__stream_decoder_get_state(m_decoder)));
|
||||
} while (m_bufferLength == 0);
|
||||
}
|
||||
int copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
|
||||
Array.Copy(m_sampleBuffer.Bytes, m_bufferOffset * m_pcm.BlockAlign, buff.Bytes, buffOffset * m_pcm.BlockAlign, copyCount * m_pcm.BlockAlign);
|
||||
samplesNeeded -= copyCount;
|
||||
buffOffset += copyCount;
|
||||
m_bufferOffset += copyCount;
|
||||
}
|
||||
return buff.Length;
|
||||
}
|
||||
|
||||
AudioBuffer m_sampleBuffer;
|
||||
byte[] m_readBuffer;
|
||||
long m_sampleCount, m_sampleOffset;
|
||||
int m_bufferOffset, m_bufferLength;
|
||||
IntPtr m_decoder;
|
||||
string m_path;
|
||||
Stream m_stream;
|
||||
bool m_decoderActive;
|
||||
AudioPCMConfig m_pcm;
|
||||
FLACDLL.FLAC__StreamDecoderReadCallback m_readCallback;
|
||||
FLACDLL.FLAC__StreamDecoderSeekCallback m_seekCallback;
|
||||
FLACDLL.FLAC__StreamDecoderTellCallback m_tellCallback;
|
||||
FLACDLL.FLAC__StreamDecoderLengthCallback m_lengthCallback;
|
||||
FLACDLL.FLAC__StreamDecoderEofCallback m_eofCallback;
|
||||
FLACDLL.FLAC__StreamDecoderWriteCallback m_writeCallback;
|
||||
FLACDLL.FLAC__StreamDecoderMetadataCallback m_metadataCallback;
|
||||
FLACDLL.FLAC__StreamDecoderErrorCallback m_errorCallback;
|
||||
}
|
||||
}
|
||||
251
CUETools.Codecs.libFLAC/Writer.cs
Normal file
251
CUETools.Codecs.libFLAC/Writer.cs
Normal file
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using CUETools.Codecs;
|
||||
|
||||
namespace CUETools.Codecs.libFLAC.Writer
|
||||
{
|
||||
public class WriterSettings : AudioEncoderSettings
|
||||
{
|
||||
public WriterSettings()
|
||||
: base("0 1 2 3 4 5 6 7 8", "5")
|
||||
{
|
||||
}
|
||||
|
||||
[DefaultValue(false)]
|
||||
[DisplayName("Verify")]
|
||||
[Description("Decode each frame and compare with original")]
|
||||
public bool Verify { get; set; }
|
||||
|
||||
[DefaultValue(true)]
|
||||
[DisplayName("MD5")]
|
||||
[Description("Calculate MD5 hash for audio stream")]
|
||||
public bool MD5Sum { get; set; }
|
||||
};
|
||||
|
||||
[AudioEncoderClass("libFLAC", "flac", true, 2, typeof(WriterSettings))]
|
||||
public unsafe class Writer : IAudioDest
|
||||
{
|
||||
public Writer(string path, Stream output, WriterSettings settings)
|
||||
{
|
||||
m_path = path;
|
||||
m_stream = output;
|
||||
m_settings = settings;
|
||||
m_streamGiven = output != null;
|
||||
m_initialized = false;
|
||||
m_finalSampleCount = 0;
|
||||
m_samplesWritten = 0;
|
||||
m_write_callback = StreamEncoderWriteCallback;
|
||||
m_seek_callback = StreamEncoderSeekCallback;
|
||||
m_tell_callback = StreamEncoderTellCallback;
|
||||
|
||||
if (m_settings.PCM.BitsPerSample < 16 || m_settings.PCM.BitsPerSample > 24)
|
||||
throw new Exception("bits per sample must be 16..24");
|
||||
|
||||
m_encoder = FLACDLL.FLAC__stream_encoder_new();
|
||||
|
||||
FLACDLL.FLAC__stream_encoder_set_bits_per_sample(m_encoder, (uint)m_settings.PCM.BitsPerSample);
|
||||
FLACDLL.FLAC__stream_encoder_set_channels(m_encoder, (uint)m_settings.PCM.ChannelCount);
|
||||
FLACDLL.FLAC__stream_encoder_set_sample_rate(m_encoder, (uint)m_settings.PCM.SampleRate);
|
||||
}
|
||||
|
||||
public Writer(string path, WriterSettings settings)
|
||||
: this(path, null, settings)
|
||||
{
|
||||
}
|
||||
|
||||
public AudioEncoderSettings Settings => m_settings;
|
||||
|
||||
public string Path { get => m_path; }
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
get => m_finalSampleCount;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
throw new Exception("invalid final sample count");
|
||||
if (m_initialized)
|
||||
throw new Exception("final sample count cannot be changed after encoding begins");
|
||||
m_finalSampleCount = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (m_initialized)
|
||||
{
|
||||
FLACDLL.FLAC__stream_encoder_finish(m_encoder);
|
||||
FLACDLL.FLAC__stream_encoder_delete(m_encoder);
|
||||
m_encoder = IntPtr.Zero;
|
||||
m_initialized = false;
|
||||
}
|
||||
if (m_stream != null)
|
||||
{
|
||||
m_stream.Close();
|
||||
m_stream = null;
|
||||
}
|
||||
if ((m_finalSampleCount != 0) && (m_samplesWritten != m_finalSampleCount))
|
||||
throw new Exception("samples written differs from the expected sample count");
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_initialized)
|
||||
{
|
||||
FLACDLL.FLAC__stream_encoder_delete(m_encoder);
|
||||
m_encoder = IntPtr.Zero;
|
||||
m_initialized = false;
|
||||
}
|
||||
if (m_stream != null)
|
||||
{
|
||||
m_stream.Close();
|
||||
m_stream = null;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
if (m_path != "")
|
||||
File.Delete(m_path);
|
||||
}
|
||||
|
||||
public void Write(AudioBuffer sampleBuffer)
|
||||
{
|
||||
if (!m_initialized) Initialize();
|
||||
|
||||
sampleBuffer.Prepare(this);
|
||||
|
||||
fixed (int* pSampleBuffer = &sampleBuffer.Samples[0, 0])
|
||||
{
|
||||
if (0 == FLACDLL.FLAC__stream_encoder_process_interleaved(m_encoder,
|
||||
pSampleBuffer, sampleBuffer.Length))
|
||||
{
|
||||
var state = FLACDLL.FLAC__stream_encoder_get_state(m_encoder);
|
||||
string status = state.ToString();
|
||||
if (state == FLAC__StreamEncoderState.FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
|
||||
{
|
||||
ulong absolute_sample;
|
||||
uint frame_number;
|
||||
uint channel;
|
||||
uint sample;
|
||||
int expected, got;
|
||||
FLACDLL.FLAC__stream_encoder_get_verify_decoder_error_stats(m_encoder, out absolute_sample, out frame_number, out channel, out sample, out expected, out got);
|
||||
status = status + String.Format("({0:x} instead of {1:x} @{2:x})", got, expected, absolute_sample);
|
||||
}
|
||||
throw new Exception("an error occurred while encoding: " + status);
|
||||
}
|
||||
}
|
||||
|
||||
m_samplesWritten += sampleBuffer.Length;
|
||||
}
|
||||
|
||||
internal FLAC__StreamEncoderWriteStatus StreamEncoderWriteCallback(IntPtr encoder, byte[] buffer, long bytes, int samples, int current_frame, void* client_data)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_stream.Write(buffer, 0, (int)bytes);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return FLAC__StreamEncoderWriteStatus.FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
return FLAC__StreamEncoderWriteStatus.FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
|
||||
}
|
||||
|
||||
internal FLAC__StreamEncoderSeekStatus StreamEncoderSeekCallback(IntPtr encoder, long absolute_byte_offset, void* client_data)
|
||||
{
|
||||
if (!m_stream.CanSeek) return FLAC__StreamEncoderSeekStatus.FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
|
||||
try
|
||||
{
|
||||
m_stream.Position = absolute_byte_offset;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return FLAC__StreamEncoderSeekStatus.FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
return FLAC__StreamEncoderSeekStatus.FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
internal FLAC__StreamEncoderTellStatus StreamEncoderTellCallback(IntPtr encoder, out long absolute_byte_offset, void* client_data)
|
||||
{
|
||||
if (!m_stream.CanSeek)
|
||||
{
|
||||
absolute_byte_offset = -1;
|
||||
return FLAC__StreamEncoderTellStatus.FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
|
||||
}
|
||||
try
|
||||
{
|
||||
absolute_byte_offset = m_stream.Position;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
absolute_byte_offset = -1;
|
||||
return FLAC__StreamEncoderTellStatus.FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
|
||||
}
|
||||
return FLAC__StreamEncoderTellStatus.FLAC__STREAM_ENCODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
if (m_stream == null)
|
||||
m_stream = new FileStream(m_path, FileMode.Create, FileAccess.Write, FileShare.Read, 0x10000);
|
||||
|
||||
var metadata = stackalloc FLAC__StreamMetadata*[4];
|
||||
int metadataCount = 0;
|
||||
FLAC__StreamMetadata* padding, seektable, vorbiscomment;
|
||||
|
||||
if (m_finalSampleCount != 0)
|
||||
{
|
||||
seektable = FLACDLL.FLAC__metadata_object_new(FLAC__MetadataType.FLAC__METADATA_TYPE_SEEKTABLE);
|
||||
FLACDLL.FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(
|
||||
seektable, m_settings.PCM.SampleRate * 10, m_finalSampleCount);
|
||||
FLACDLL.FLAC__metadata_object_seektable_template_sort(seektable, 1);
|
||||
metadata[metadataCount++] = seektable;
|
||||
}
|
||||
|
||||
vorbiscomment = FLACDLL.FLAC__metadata_object_new(FLAC__MetadataType.FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
metadata[metadataCount++] = vorbiscomment;
|
||||
|
||||
if (m_settings.Padding != 0)
|
||||
{
|
||||
padding = FLACDLL.FLAC__metadata_object_new(FLAC__MetadataType.FLAC__METADATA_TYPE_PADDING);
|
||||
padding->length = (uint)m_settings.Padding;
|
||||
metadata[metadataCount++] = padding;
|
||||
}
|
||||
|
||||
FLACDLL.FLAC__stream_encoder_set_metadata(m_encoder, metadata, metadataCount);
|
||||
FLACDLL.FLAC__stream_encoder_set_verify(m_encoder, m_settings.Verify ? 1 : 0);
|
||||
FLACDLL.FLAC__stream_encoder_set_do_md5(m_encoder, m_settings.MD5Sum ? 1 : 0);
|
||||
FLACDLL.FLAC__stream_encoder_set_compression_level(m_encoder, m_settings.EncoderModeIndex);
|
||||
if (m_finalSampleCount != 0)
|
||||
FLACDLL.FLAC__stream_encoder_set_total_samples_estimate(m_encoder, m_finalSampleCount);
|
||||
if (m_settings.BlockSize > 0)
|
||||
FLACDLL.FLAC__stream_encoder_set_blocksize(m_encoder, m_settings.BlockSize);
|
||||
|
||||
FLAC__StreamEncoderInitStatus st = FLACDLL.FLAC__stream_encoder_init_stream(
|
||||
m_encoder, m_write_callback, m_stream.CanSeek ? m_seek_callback : null,
|
||||
m_stream.CanSeek ? m_tell_callback : null, null, null);
|
||||
if (st != FLAC__StreamEncoderInitStatus.FLAC__STREAM_ENCODER_INIT_STATUS_OK)
|
||||
throw new Exception(string.Format("unable to initialize the encoder: {0}", st));
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
WriterSettings m_settings;
|
||||
Stream m_stream;
|
||||
bool m_streamGiven;
|
||||
IntPtr m_encoder;
|
||||
bool m_initialized;
|
||||
string m_path;
|
||||
Int64 m_finalSampleCount, m_samplesWritten;
|
||||
FLACDLL.FLAC__StreamEncoderWriteCallback m_write_callback;
|
||||
FLACDLL.FLAC__StreamEncoderSeekCallback m_seek_callback;
|
||||
FLACDLL.FLAC__StreamEncoderTellCallback m_tell_callback;
|
||||
}
|
||||
}
|
||||
221
CUETools.Codecs.libFLAC/libFLAC.cs
Normal file
221
CUETools.Codecs.libFLAC/libFLAC.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CUETools.Codecs.libFLAC
|
||||
{
|
||||
internal struct FLAC__FrameHeader
|
||||
{
|
||||
internal int blocksize;
|
||||
internal int sample_rate;
|
||||
internal int channels;
|
||||
internal FLAC__ChannelAssignment channel_assignment;
|
||||
internal int bits_per_sample;
|
||||
internal FLAC__FrameNumberType number_type;
|
||||
internal ulong sample_number; // can be uint frame_number depending on number_type
|
||||
internal byte crc;
|
||||
};
|
||||
|
||||
//internal struct FLAC__Subframe
|
||||
//{
|
||||
// FLAC__SubframeType type;
|
||||
// [FieldOffset(4)]
|
||||
// FLAC__Subframe_Constant data_constant;
|
||||
// [FieldOffset(4)]
|
||||
// FLAC__Subframe_Fixed data_fixed;
|
||||
// [FieldOffset(4)]
|
||||
// FLAC__Subframe_LPC data_lpc;
|
||||
// [FieldOffset(4)]
|
||||
// FLAC__Subframe_Verbatim data_verbatim;
|
||||
// uint wasted_bits;
|
||||
//};
|
||||
|
||||
internal unsafe struct FLAC__Frame
|
||||
{
|
||||
internal FLAC__FrameHeader header;
|
||||
//fixed FLAC__Subframe subframes[FLACDLL.FLAC__MAX_CHANNELS];
|
||||
//FLAC__FrameFooter footer;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Explicit), Serializable]
|
||||
internal struct FLAC__StreamMetadata
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
internal FLAC__MetadataType type;
|
||||
[FieldOffset(4)]
|
||||
internal int is_last;
|
||||
[FieldOffset(8)]
|
||||
internal uint length;
|
||||
[FieldOffset(16)]
|
||||
internal FLAC__StreamMetadata_StreamInfo stream_info;
|
||||
// [FieldOffset(16)]
|
||||
// internal FLAC__StreamMetadata_Padding padding;
|
||||
// [FieldOffset(16)]
|
||||
// internal FLAC__StreamMetadata_Application application;
|
||||
// [FieldOffset(16)]
|
||||
// internal FLAC__StreamMetadata_SeekTable seek_table;
|
||||
// [FieldOffset(16)]
|
||||
// internal FLAC__StreamMetadata_VorbisComment vorbis_comment;
|
||||
// [FieldOffset(16)]
|
||||
// internal FLAC__StreamMetadata_CueSheet cue_sheet;
|
||||
// [FieldOffset(16)]
|
||||
// internal FLAC__StreamMetadata_Picture picture;
|
||||
// [FieldOffset(16)]
|
||||
// internal FLAC__StreamMetadata_Unknown unknown;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential), Serializable]
|
||||
internal unsafe struct FLAC__StreamMetadata_StreamInfo
|
||||
{
|
||||
internal int min_blocksize, max_blocksize;
|
||||
internal int min_framesize, max_framesize;
|
||||
internal int sample_rate;
|
||||
internal int channels;
|
||||
internal int bits_per_sample;
|
||||
internal long total_samples;
|
||||
internal fixed byte md5sum[16];
|
||||
};
|
||||
|
||||
internal enum FLAC__ChannelAssignment
|
||||
{
|
||||
FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT = 0,
|
||||
FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE = 1,
|
||||
FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE = 2,
|
||||
FLAC__CHANNEL_ASSIGNMENT_MID_SIDE = 3
|
||||
};
|
||||
|
||||
internal enum FLAC__FrameNumberType
|
||||
{
|
||||
FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER,
|
||||
FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderInitStatus
|
||||
{
|
||||
FLAC__STREAM_DECODER_INIT_STATUS_OK = 0,
|
||||
FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER,
|
||||
FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS,
|
||||
FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR,
|
||||
FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE,
|
||||
FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderWriteStatus
|
||||
{
|
||||
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE,
|
||||
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderReadStatus
|
||||
{
|
||||
FLAC__STREAM_DECODER_READ_STATUS_CONTINUE,
|
||||
FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM,
|
||||
FLAC__STREAM_DECODER_READ_STATUS_ABORT
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderSeekStatus
|
||||
{
|
||||
FLAC__STREAM_DECODER_SEEK_STATUS_OK,
|
||||
FLAC__STREAM_DECODER_SEEK_STATUS_ERROR,
|
||||
FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderTellStatus
|
||||
{
|
||||
FLAC__STREAM_DECODER_TELL_STATUS_OK,
|
||||
FLAC__STREAM_DECODER_TELL_STATUS_ERROR,
|
||||
FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderLengthStatus
|
||||
{
|
||||
FLAC__STREAM_DECODER_LENGTH_STATUS_OK,
|
||||
FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR,
|
||||
FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderErrorStatus
|
||||
{
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC,
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER,
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH,
|
||||
FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamDecoderState
|
||||
{
|
||||
FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0,
|
||||
FLAC__STREAM_DECODER_READ_METADATA,
|
||||
FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC,
|
||||
FLAC__STREAM_DECODER_READ_FRAME,
|
||||
FLAC__STREAM_DECODER_END_OF_STREAM,
|
||||
FLAC__STREAM_DECODER_OGG_ERROR,
|
||||
FLAC__STREAM_DECODER_SEEK_ERROR,
|
||||
FLAC__STREAM_DECODER_ABORTED,
|
||||
FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
|
||||
FLAC__STREAM_DECODER_UNINITIALIZED
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamEncoderState : int
|
||||
{
|
||||
FLAC__STREAM_ENCODER_OK = 0,
|
||||
FLAC__STREAM_ENCODER_UNINITIALIZED,
|
||||
FLAC__STREAM_ENCODER_OGG_ERROR,
|
||||
FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR,
|
||||
FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA,
|
||||
FLAC__STREAM_ENCODER_CLIENT_ERROR,
|
||||
FLAC__STREAM_ENCODER_IO_ERROR,
|
||||
FLAC__STREAM_ENCODER_FRAMING_ERROR,
|
||||
FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamEncoderInitStatus
|
||||
{
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_OK = 0,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA,
|
||||
FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED
|
||||
};
|
||||
|
||||
internal enum FLAC__MetadataType : int
|
||||
{
|
||||
FLAC__METADATA_TYPE_STREAMINFO = 0,
|
||||
FLAC__METADATA_TYPE_PADDING = 1,
|
||||
FLAC__METADATA_TYPE_APPLICATION = 2,
|
||||
FLAC__METADATA_TYPE_SEEKTABLE = 3,
|
||||
FLAC__METADATA_TYPE_VORBIS_COMMENT = 4,
|
||||
FLAC__METADATA_TYPE_CUESHEET = 5,
|
||||
FLAC__METADATA_TYPE_PICTURE = 6,
|
||||
FLAC__METADATA_TYPE_UNDEFINED = 7,
|
||||
FLAC__MAX_METADATA_TYPE = 126,
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamEncoderWriteStatus
|
||||
{
|
||||
FLAC__STREAM_ENCODER_WRITE_STATUS_OK = 0,
|
||||
FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamEncoderSeekStatus
|
||||
{
|
||||
FLAC__STREAM_ENCODER_SEEK_STATUS_OK,
|
||||
FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR,
|
||||
FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED
|
||||
};
|
||||
|
||||
internal enum FLAC__StreamEncoderTellStatus
|
||||
{
|
||||
FLAC__STREAM_ENCODER_TELL_STATUS_OK,
|
||||
FLAC__STREAM_ENCODER_TELL_STATUS_ERROR,
|
||||
FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED
|
||||
};
|
||||
}
|
||||
BIN
ThirdParty/Win32/libFLAC_dynamic.dll
vendored
Normal file
BIN
ThirdParty/Win32/libFLAC_dynamic.dll
vendored
Normal file
Binary file not shown.
BIN
ThirdParty/x64/libFLAC_dynamic.dll
vendored
Normal file
BIN
ThirdParty/x64/libFLAC_dynamic.dll
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user