193 lines
5.2 KiB
C#
193 lines
5.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using Vocaluxe.Base;
|
|
using Vocaluxe.Lib.Video.Acinerella;
|
|
|
|
namespace Vocaluxe.Lib.Sound.Decoder
|
|
{
|
|
class CAudioDecoderFFmpeg : CAudioDecoder, IDisposable
|
|
{
|
|
private IntPtr _instance = IntPtr.Zero;
|
|
private IntPtr _audiodecoder = IntPtr.Zero;
|
|
|
|
private AC_instance _Instance;
|
|
private FormatInfo _FormatInfo;
|
|
private float _CurrentTime;
|
|
|
|
private string _FileName;
|
|
private bool _FileOpened;
|
|
|
|
public override void Init()
|
|
{
|
|
_FileOpened = false;
|
|
_Initialized = true;
|
|
}
|
|
|
|
public override void Open(string FileName, bool Loop)
|
|
{
|
|
if (!_Initialized)
|
|
return;
|
|
|
|
_FileName = FileName;
|
|
|
|
try
|
|
{
|
|
_instance = CAcinerella.ac_init();
|
|
CAcinerella.ac_open2(_instance, _FileName);
|
|
_Instance = (AC_instance)Marshal.PtrToStructure(_instance, typeof(AC_instance));
|
|
}
|
|
catch (Exception)
|
|
{
|
|
CLog.LogError("Error opening audio file: " + _FileName);
|
|
return;
|
|
}
|
|
|
|
|
|
if (!_Instance.opened)
|
|
{
|
|
//Free();
|
|
return;
|
|
}
|
|
|
|
int AudioStreamIndex = -1;
|
|
AC_decoder Audiodecoder;
|
|
try
|
|
{
|
|
_audiodecoder = CAcinerella.ac_create_audio_decoder(_instance);
|
|
Audiodecoder = (AC_decoder)Marshal.PtrToStructure(_audiodecoder, typeof(AC_decoder));
|
|
AudioStreamIndex = Audiodecoder.stream_index;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
CLog.LogError("Error opening audio file (can't find decoder): " + _FileName);
|
|
return;
|
|
}
|
|
|
|
if (AudioStreamIndex < 0)
|
|
{
|
|
//Free();
|
|
return;
|
|
}
|
|
|
|
_FormatInfo = new FormatInfo();
|
|
|
|
_FormatInfo.SamplesPerSecond = Audiodecoder.stream_info.audio_info.samples_per_second;
|
|
_FormatInfo.BitDepth = Audiodecoder.stream_info.audio_info.bit_depth;
|
|
_FormatInfo.ChannelCount = Audiodecoder.stream_info.audio_info.channel_count;
|
|
|
|
_CurrentTime = 0f;
|
|
|
|
if (_FormatInfo.BitDepth != 16)
|
|
{
|
|
CLog.LogError("Unsupported BitDepth in file " + FileName);
|
|
return;
|
|
}
|
|
_FileOpened = true;
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
if (!_Initialized)
|
|
return;
|
|
|
|
_Initialized = false;
|
|
|
|
if (!_FileOpened)
|
|
return;
|
|
|
|
if (_audiodecoder != IntPtr.Zero)
|
|
CAcinerella.ac_free_decoder(_audiodecoder);
|
|
|
|
if (_instance != IntPtr.Zero)
|
|
CAcinerella.ac_close(_instance);
|
|
|
|
if (_instance != IntPtr.Zero)
|
|
CAcinerella.ac_free(_instance);
|
|
|
|
_FileOpened = false;
|
|
}
|
|
|
|
public override FormatInfo GetFormatInfo()
|
|
{
|
|
if (!_Initialized && !_FileOpened)
|
|
return new FormatInfo();
|
|
|
|
return _FormatInfo;
|
|
}
|
|
|
|
public override float GetLength()
|
|
{
|
|
if (!_Initialized && !_FileOpened)
|
|
return 0f;
|
|
|
|
return _Instance.info.duration / 1000f;
|
|
}
|
|
|
|
public override void SetPosition(float Time)
|
|
{
|
|
if (!_Initialized && !_FileOpened)
|
|
return;
|
|
|
|
try
|
|
{
|
|
CAcinerella.ac_seek(_audiodecoder, 0, (Int64)(Time * 1000f));
|
|
}
|
|
catch (Exception)
|
|
{
|
|
CLog.LogError("Error seeking in file: " + _FileName);
|
|
Close();
|
|
}
|
|
}
|
|
|
|
public override float GetPosition()
|
|
{
|
|
if (!_Initialized && !_FileOpened)
|
|
return 0f;
|
|
|
|
return _CurrentTime;
|
|
}
|
|
|
|
public override void Decode(out byte[] Buffer, out float TimeStamp)
|
|
{
|
|
if (!_Initialized && !_FileOpened)
|
|
{
|
|
Buffer = null;
|
|
TimeStamp = 0f;
|
|
return;
|
|
}
|
|
|
|
int FrameFinished = 0;
|
|
try
|
|
{
|
|
FrameFinished = CAcinerella.ac_get_audio_frame(_instance, _audiodecoder);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
FrameFinished = 0;
|
|
}
|
|
|
|
if (FrameFinished == 1)
|
|
{
|
|
AC_decoder Decoder = (AC_decoder)Marshal.PtrToStructure(_audiodecoder, typeof(AC_decoder));
|
|
|
|
TimeStamp = (float)Decoder.timecode;
|
|
_CurrentTime = TimeStamp;
|
|
//Console.WriteLine(_CurrentTime.ToString("#0.000") + " Buffer size: " + Decoder.buffer_size.ToString());
|
|
Buffer = new byte[Decoder.buffer_size];
|
|
|
|
if (Decoder.buffer_size > 0)
|
|
Marshal.Copy(Decoder.buffer, Buffer, 0, Buffer.Length);
|
|
|
|
return;
|
|
}
|
|
|
|
Buffer = null;
|
|
TimeStamp = 0f;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
}
|
|
} |