mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
IAudioTitleSet
This commit is contained in:
@@ -6,7 +6,7 @@ using static CUETools.Codecs.AudioPCMConfig;
|
|||||||
|
|
||||||
namespace CUETools.Codecs.MPEG.ATSI
|
namespace CUETools.Codecs.MPEG.ATSI
|
||||||
{
|
{
|
||||||
public class AudioDecoder : IAudioSource, IAudioContainer
|
public class AudioDecoder : IAudioSource, IAudioTitleSet
|
||||||
{
|
{
|
||||||
public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO)
|
public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO)
|
||||||
{
|
{
|
||||||
@@ -331,7 +331,7 @@ namespace CUETools.Codecs.MPEG.ATSI
|
|||||||
public ushort codec;
|
public ushort codec;
|
||||||
public uint format;
|
public uint format;
|
||||||
|
|
||||||
public byte StreamId
|
public int StreamId
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -342,64 +342,6 @@ namespace CUETools.Codecs.MPEG.ATSI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CodecString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamId)
|
|
||||||
{
|
|
||||||
case DVDA.PCM_STREAM_ID: return "RAW/PCM";
|
|
||||||
case DVDA.MLP_STREAM_ID: return "MLP";
|
|
||||||
default: return StreamId.ToString();
|
|
||||||
}
|
|
||||||
//switch (codec)
|
|
||||||
//{
|
|
||||||
// case 0x000: return "RAW/PCM";
|
|
||||||
// case 0x100: return "MLP";
|
|
||||||
// default: return codec.ToString();
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AudioPCMConfig PCM
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (track_sector.Count < 1) return null;
|
|
||||||
if (track_sector[0].dvdaBlock == null) return null;
|
|
||||||
return new AudioPCMConfig(
|
|
||||||
track_sector[0].dvdaBlock.gr1_bits,
|
|
||||||
track_sector[0].dvdaBlock.channels,
|
|
||||||
track_sector[0].dvdaBlock.gr1_frequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string RateString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var sr = PCM.SampleRate;
|
|
||||||
if (sr % 1000 == 0) return $"{sr / 1000}KHz";
|
|
||||||
if (sr % 100 == 0) return $"{sr / 100}.{(sr / 100) % 10}KHz";
|
|
||||||
return $"{sr}Hz";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FormatString
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (track_sector.Count < 1) return "?";
|
|
||||||
if (track_sector[0].dvdaBlock == null) return "?";
|
|
||||||
switch (track_sector[0].dvdaBlock.ch_assignment)
|
|
||||||
{
|
|
||||||
case 0: return "mono";
|
|
||||||
case 1: return "stereo";
|
|
||||||
default: return "multi-channel";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TimeSpan> Chapters
|
public List<TimeSpan> Chapters
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -436,6 +378,40 @@ namespace CUETools.Codecs.MPEG.ATSI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AudioPCMConfig PCM
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (track_sector.Count < 1) return null;
|
||||||
|
if (track_sector[0].dvdaBlock == null) return null;
|
||||||
|
return new AudioPCMConfig(
|
||||||
|
track_sector[0].dvdaBlock.gr1_bits,
|
||||||
|
track_sector[0].dvdaBlock.channels,
|
||||||
|
track_sector[0].dvdaBlock.gr1_frequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Codec
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (StreamId)
|
||||||
|
{
|
||||||
|
case DVDA.PCM_STREAM_ID: return "RAW/PCM";
|
||||||
|
case DVDA.MLP_STREAM_ID: return "MLP";
|
||||||
|
default: return StreamId.ToString();
|
||||||
|
}
|
||||||
|
//switch (codec)
|
||||||
|
//{
|
||||||
|
// case 0x000: return "RAW/PCM";
|
||||||
|
// case 0x100: return "MLP";
|
||||||
|
// default: return codec.ToString();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Language => "";
|
||||||
|
|
||||||
public List<ATSITrackTimestamp> track_timestamp;
|
public List<ATSITrackTimestamp> track_timestamp;
|
||||||
public List<ATSITrackSector> track_sector;
|
public List<ATSITrackSector> track_sector;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.IO;
|
|||||||
|
|
||||||
namespace CUETools.Codecs.MPEG.MPLS
|
namespace CUETools.Codecs.MPEG.MPLS
|
||||||
{
|
{
|
||||||
public class AudioDecoder : IAudioSource, IAudioContainer
|
public class AudioDecoder : IAudioSource, IAudioTitleSet
|
||||||
{
|
{
|
||||||
public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO)
|
public unsafe AudioDecoder(DecoderSettings settings, string path, Stream IO)
|
||||||
{
|
{
|
||||||
@@ -392,7 +392,7 @@ namespace CUETools.Codecs.MPEG.MPLS
|
|||||||
foreach (var item in hdr_m.play_item)
|
foreach (var item in hdr_m.play_item)
|
||||||
foreach (var audio in item.audio)
|
foreach (var audio in item.audio)
|
||||||
{
|
{
|
||||||
if (audio.coding_type != 0x80 /* LPCM */) continue;
|
//if (audio.coding_type != 0x80 /* LPCM */) continue;
|
||||||
titles.Add(new AudioTitle(this, audio.pid));
|
titles.Add(new AudioTitle(this, audio.pid));
|
||||||
}
|
}
|
||||||
return titles;
|
return titles;
|
||||||
@@ -461,6 +461,44 @@ namespace CUETools.Codecs.MPEG.MPLS
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<TimeSpan> Chapters => source.Chapters;
|
public List<TimeSpan> Chapters => source.Chapters;
|
||||||
|
public AudioPCMConfig PCM
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var s = FirstStream;
|
||||||
|
int channelCount = s.format == 1 ? 1 : s.format == 3 ? 2 : s.format == 6 ? 5 : 0;
|
||||||
|
int sampleRate = s.rate == 1 ? 48000 : s.rate == 4 ? 96000 : s.rate == 5 ? 192000 : s.rate == 12 ? 192000 : s.rate == 14 ? 96000 : 0;
|
||||||
|
int bitsPerSample = 0;
|
||||||
|
return new AudioPCMConfig(bitsPerSample, channelCount, sampleRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Codec
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var s = FirstStream;
|
||||||
|
return s != null ? s.CodecString : "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Language
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var s = FirstStream;
|
||||||
|
return s != null ? s.LanguageString : "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int StreamId => pid;
|
||||||
|
|
||||||
|
MPLSStream FirstStream
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
MPLSStream result = null;
|
||||||
|
source.MPLSHeader.play_item.ForEach(i => i.audio.FindAll(a => a.pid == pid).ForEach(x => result = x));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AudioDecoder source;
|
AudioDecoder source;
|
||||||
int pid;
|
int pid;
|
||||||
@@ -476,7 +514,7 @@ namespace CUETools.Codecs.MPEG.MPLS
|
|||||||
public uint duration;
|
public uint duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct MPLSStream
|
public class MPLSStream
|
||||||
{
|
{
|
||||||
public byte stream_type;
|
public byte stream_type;
|
||||||
public byte coding_type;
|
public byte coding_type;
|
||||||
|
|||||||
@@ -56,13 +56,4 @@ namespace CUETools.Codecs.MPEG
|
|||||||
savedBufferSize = 0;
|
savedBufferSize = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public class AudioDescription
|
|
||||||
{
|
|
||||||
public int StreamId;
|
|
||||||
public string CodecString;
|
|
||||||
public string LanguageString;
|
|
||||||
public string FormatString;
|
|
||||||
public string RateString;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,25 +22,61 @@ namespace CUETools.Codecs
|
|||||||
public interface IAudioTitle
|
public interface IAudioTitle
|
||||||
{
|
{
|
||||||
List<TimeSpan> Chapters { get; }
|
List<TimeSpan> Chapters { get; }
|
||||||
|
AudioPCMConfig PCM { get; }
|
||||||
|
string Codec { get; }
|
||||||
|
string Language { get; }
|
||||||
|
int StreamId { get; }
|
||||||
//IAudioSource Open { get; }
|
//IAudioSource Open { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IAudioContainer
|
public interface IAudioTitleSet
|
||||||
{
|
{
|
||||||
List<IAudioTitle> AudioTitles { get; }
|
List<IAudioTitle> AudioTitles { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NoContainerAudioTitle : IAudioTitle
|
public static class IAudioTitleExtensions
|
||||||
{
|
{
|
||||||
public NoContainerAudioTitle(IAudioSource source) { this.source = source; }
|
public static TimeSpan GetDuration(this IAudioTitle title)
|
||||||
|
{
|
||||||
|
var chapters = title.Chapters;
|
||||||
|
return chapters[chapters.Count - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string GetRateString(this IAudioTitle title)
|
||||||
|
{
|
||||||
|
var sr = title.PCM.SampleRate;
|
||||||
|
if (sr % 1000 == 0) return $"{sr / 1000}KHz";
|
||||||
|
if (sr % 100 == 0) return $"{sr / 100}.{(sr / 100) % 10}KHz";
|
||||||
|
return $"{sr}Hz";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFormatString(this IAudioTitle title)
|
||||||
|
{
|
||||||
|
switch (title.PCM.ChannelCount)
|
||||||
|
{
|
||||||
|
case 1: return "mono";
|
||||||
|
case 2: return "stereo";
|
||||||
|
default: return "multi-channel";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SingleAudioTitle : IAudioTitle
|
||||||
|
{
|
||||||
|
public SingleAudioTitle(IAudioSource source) { this.source = source; }
|
||||||
public List<TimeSpan> Chapters => new List<TimeSpan> { TimeSpan.Zero, source.Duration };
|
public List<TimeSpan> Chapters => new List<TimeSpan> { TimeSpan.Zero, source.Duration };
|
||||||
|
public AudioPCMConfig PCM => source.PCM;
|
||||||
|
public string Codec => source.Settings.Extension;
|
||||||
|
public string Language => "";
|
||||||
|
public int StreamId => 0;
|
||||||
IAudioSource source;
|
IAudioSource source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NoContainer : IAudioContainer
|
public class SingleAudioTitleSet : IAudioTitleSet
|
||||||
{
|
{
|
||||||
public NoContainer(IAudioSource source) { this.source = source; }
|
public SingleAudioTitleSet(IAudioSource source) { this.source = source; }
|
||||||
public List<IAudioTitle> AudioTitles => new List<IAudioTitle> { new NoContainerAudioTitle(source) };
|
public List<IAudioTitle> AudioTitles => new List<IAudioTitle> { new SingleAudioTitle(source) };
|
||||||
IAudioSource source;
|
IAudioSource source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,10 +130,10 @@ namespace CUETools.eac3to
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
IAudioSource audioSource = null;
|
IAudioSource audioSource = null;
|
||||||
IAudioContainer audioContainer = null;
|
IAudioTitleSet audioContainer = null;
|
||||||
IAudioDest audioDest = null;
|
IAudioDest audioDest = null;
|
||||||
var videos = new List<Codecs.MPEG.MPLS.MPLSStream>();
|
var videos = new List<Codecs.MPEG.MPLS.MPLSStream>();
|
||||||
var audios = new List<Codecs.MPEG.AudioDescription>();
|
List<IAudioTitle> audios = null;
|
||||||
List<TimeSpan> chapters = null;
|
List<TimeSpan> chapters = null;
|
||||||
TagLib.UserDefined.AdditionalFileTypes.Config = config;
|
TagLib.UserDefined.AdditionalFileTypes.Config = config;
|
||||||
|
|
||||||
@@ -160,29 +160,23 @@ namespace CUETools.eac3to
|
|||||||
TypeDescriptor.GetConverter(property.PropertyType).ConvertFromString(decOpt.Value));
|
TypeDescriptor.GetConverter(property.PropertyType).ConvertFromString(decOpt.Value));
|
||||||
}
|
}
|
||||||
audioSource = decoderSettings.Open(sourceFile);
|
audioSource = decoderSettings.Open(sourceFile);
|
||||||
audioContainer = audioSource as IAudioContainer;
|
audioContainer = audioSource as IAudioTitleSet;
|
||||||
if (audioContainer == null) audioContainer = new NoContainer(audioSource);
|
if (audioContainer == null) audioContainer = new SingleAudioTitleSet(audioSource);
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
int frameRate = 0;
|
int frameRate = 0;
|
||||||
bool interlaced = false;
|
bool interlaced = false;
|
||||||
audioContainer.AudioTitles.ForEach(t => chapters = t.Chapters);
|
audios = audioContainer.AudioTitles;
|
||||||
|
audios.ForEach(t => chapters = t.Chapters);
|
||||||
if (audioSource is Codecs.MPEG.MPLS.AudioDecoder)
|
if (audioSource is Codecs.MPEG.MPLS.AudioDecoder)
|
||||||
{
|
{
|
||||||
var mpls = audioSource as Codecs.MPEG.MPLS.AudioDecoder;
|
var mpls = audioSource as Codecs.MPEG.MPLS.AudioDecoder;
|
||||||
mpls.MPLSHeader.play_item.ForEach(i => i.video.ForEach(v => { if (!videos.Exists(v1 => v1.pid == v.pid)) videos.Add(v); }));
|
mpls.MPLSHeader.play_item.ForEach(i => i.video.ForEach(v => { if (!videos.Exists(v1 => v1.pid == v.pid)) videos.Add(v); }));
|
||||||
mpls.MPLSHeader.play_item.ForEach(i => i.audio.ForEach(v => { if (!audios.Exists(v1 => v1.StreamId == v.pid)) audios.Add(new Codecs.MPEG.AudioDescription() { StreamId = v.pid, CodecString = v.CodecString, LanguageString = v.LanguageString, FormatString = v.FormatString, RateString = v.RateString }); }));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (audioSource is Codecs.MPEG.ATSI.AudioDecoder)
|
|
||||||
{
|
|
||||||
var atsi = audioSource as Codecs.MPEG.ATSI.AudioDecoder;
|
|
||||||
atsi.ATSIHeader.titles.ForEach(t => audios.Add(new Codecs.MPEG.AudioDescription() { StreamId = 0/*!*/, CodecString = t.CodecString, FormatString = t.FormatString, RateString = t.RateString }));
|
|
||||||
}
|
}
|
||||||
videos.ForEach(v => { frameRate = v.FrameRate; interlaced = v.Interlaced; });
|
videos.ForEach(v => { frameRate = v.FrameRate; interlaced = v.Interlaced; });
|
||||||
Console.Error.Write($@"M2TS, {
|
Console.Error.Write($@"M2TS, {
|
||||||
videos.Count} video track{(videos.Count != 1 ? "s" : "")}, {
|
videos.Count} video track{(videos.Count != 1 ? "s" : "")}, {
|
||||||
audios.Count} audio track{(audios.Count != 1 ? "s" : "")}, {
|
audios.Count} audio track{(audios.Count != 1 ? "s" : "")}, {
|
||||||
CDImageLayout.TimeToString(audioSource.Duration, "{0:0}:{1:00}:{2:00}")}, {
|
CDImageLayout.TimeToString(audios[0].GetDuration(), "{0:0}:{1:00}:{2:00}")}, {
|
||||||
(frameRate * (interlaced ? 2 : 1))}{
|
(frameRate * (interlaced ? 2 : 1))}{
|
||||||
(interlaced ? "i" : "p")}");
|
(interlaced ? "i" : "p")}");
|
||||||
Console.Error.WriteLine();
|
Console.Error.WriteLine();
|
||||||
@@ -213,7 +207,7 @@ namespace CUETools.eac3to
|
|||||||
Console.Error.Write(id++);
|
Console.Error.Write(id++);
|
||||||
Console.Error.Write(": ");
|
Console.Error.Write(": ");
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
Console.Error.WriteLine("{0}, {1}, {2}, {3}", audio.CodecString, audio.LanguageString, audio.FormatString, audio.RateString);
|
Console.Error.WriteLine("{0}, {1}, {2}, {3}", audio.Codec, audio.Language, audio.GetFormatString(), audio.GetRateString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user