Added code to detect, interleave and deinterleave subchannels.

This commit is contained in:
2015-10-01 23:29:47 +01:00
parent a24e60bfdc
commit 9fda4d448c
2 changed files with 111 additions and 8 deletions

View File

@@ -1,3 +1,9 @@
2015-10-01 Natalia Portillo <claunia@claunia.com>
* Program.cs:
Added code to detect, interleave and deinterleave
subchannels.
2015-09-22 Natalia Portillo <claunia@claunia.com> 2015-09-22 Natalia Portillo <claunia@claunia.com>
* Program.cs: * Program.cs:

View File

@@ -60,7 +60,7 @@ namespace SubChannelDecoder
public static void Main(string[] args) public static void Main(string[] args)
{ {
Console.WriteLine("SubChannelDecoder 0.02"); Console.WriteLine("SubChannelDecoder 0.03");
Console.WriteLine("© 2015 Natalia Portillo"); Console.WriteLine("© 2015 Natalia Portillo");
Console.WriteLine(); Console.WriteLine();
@@ -83,6 +83,8 @@ namespace SubChannelDecoder
if(args.Length == 1) if(args.Length == 1)
{ {
bool? interleaved = null;
int sectors = (int)(fs.Length / 96); int sectors = (int)(fs.Length / 96);
for(int sector = 0; sector < sectors; sector++) for(int sector = 0; sector < sectors; sector++)
{ {
@@ -91,7 +93,21 @@ namespace SubChannelDecoder
fs.Seek(sector*96, SeekOrigin.Begin); fs.Seek(sector*96, SeekOrigin.Begin);
fs.Read(sectorBytes, 0, 96); fs.Read(sectorBytes, 0, 96);
Subchannel sub = DeinterleaveSubchannel(sectorBytes); if(interleaved == null)
{
if(CheckQCRC(DeinterleaveSubchannel(sectorBytes).q))
{
Console.WriteLine("Subchannel is interleaved.");
interleaved = true;
}
else if(CheckQCRC(UnpackSubchannel(sectorBytes).q))
{
Console.WriteLine("Subchannel is not interleaved.");
interleaved = true;
}
}
Subchannel sub = UnpackSubchannel(sectorBytes, interleaved);
Console.WriteLine("Sector {0}", sector); Console.WriteLine("Sector {0}", sector);
Console.WriteLine("\tP: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}{10:X2}{11:X2}", Console.WriteLine("\tP: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}{10:X2}{11:X2}",
@@ -131,6 +147,8 @@ namespace SubChannelDecoder
} }
else else
{ {
bool? interleaved = null;
int sector; int sector;
if(!int.TryParse(args[1], out sector)) if(!int.TryParse(args[1], out sector))
{ {
@@ -151,7 +169,21 @@ namespace SubChannelDecoder
fs.Seek(sector*96, SeekOrigin.Begin); fs.Seek(sector*96, SeekOrigin.Begin);
fs.Read(sectorBytes, 0, 96); fs.Read(sectorBytes, 0, 96);
Subchannel sub = DeinterleaveSubchannel(sectorBytes); if(interleaved == null)
{
if(CheckQCRC(DeinterleaveSubchannel(sectorBytes).q))
{
Console.WriteLine("Subchannel is interleaved.");
interleaved = true;
}
else if(CheckQCRC(UnpackSubchannel(sectorBytes).q))
{
Console.WriteLine("Subchannel is not interleaved.");
interleaved = true;
}
}
Subchannel sub = UnpackSubchannel(sectorBytes, interleaved);
Console.WriteLine("Sector {0}", sector); Console.WriteLine("Sector {0}", sector);
Console.WriteLine("\tP: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}{10:X2}{11:X2}", Console.WriteLine("\tP: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}{10:X2}{11:X2}",
@@ -424,17 +456,28 @@ namespace SubChannelDecoder
else else
Console.WriteLine("Unknown Q Mode {0}", (q[0] & 0x0F)); Console.WriteLine("Unknown Q Mode {0}", (q[0] & 0x0F));
if (CheckQCRC(q))
Console.WriteLine("Q CRC = 0x{0:X2}{1:X2} (OK)", q[10], q[11]);
else
Console.WriteLine("Q CRC = 0x{0:X2}{1:X2} (BAD)", q[10], q[11]);
}
public static bool CheckQCRC(byte[] q)
{
byte[] QCalculatedCrc; byte[] QCalculatedCrc;
CRC16CCITTContext.Data(q, 10, out QCalculatedCrc); CRC16CCITTContext.Data(q, 10, out QCalculatedCrc);
if(q[10] != QCalculatedCrc[0] || q[11] != QCalculatedCrc[1]) return q[10] == QCalculatedCrc[0] && q[11] == QCalculatedCrc[1];
Console.WriteLine("Q CRC = 0x{0:X2}{1:X2} (BAD: Expected 0x{2:X2}{3:X2})", q[10], q[11], QCalculatedCrc[0], QCalculatedCrc[1]);
else
Console.WriteLine("Q CRC = 0x{0:X2}{1:X2} (OK)", q[10], q[11]);
} }
public static Subchannel UnpackSubchannel(byte[] subchannel, bool? interleaved)
{
if (interleaved == null || interleaved == true)
return DeinterleaveSubchannel(subchannel);
return UnpackSubchannel(subchannel);
}
public static Subchannel DeinterleaveSubchannel(byte[] subchannel) public static Subchannel UnpackSubchannel(byte[] subchannel)
{ {
Subchannel sub = new Subchannel(); Subchannel sub = new Subchannel();
@@ -450,6 +493,60 @@ namespace SubChannelDecoder
return sub; return sub;
} }
public static Subchannel DeinterleaveSubchannel(byte[] subchannel)
{
Subchannel sub = new Subchannel();
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 8; j++)
{
sub.p[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x80), j);
sub.q[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x40), j-1);
sub.r[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x20), j-2);
sub.s[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x10), j-3);
sub.t[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x8), j-4);
sub.u[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x4), j-5);
sub.v[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x2), j-6);
sub.w[i] += ShiftRight((byte)(subchannel[j + i * 8] & 0x1), j-7);
}
}
return sub;
}
public static byte[] InterleaveSubchannel(Subchannel sub)
{
byte[] subchannel = new byte[96];
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 8; j++)
{
subchannel[j + i * 8] += ShiftLeft((byte)(sub.p[i] & (0x80 >> j)), j);
subchannel[j + i * 8] += ShiftLeft((byte)(sub.q[i] & (0x80 >> j)), j-1);
subchannel[j + i * 8] += ShiftLeft((byte)(sub.r[i] & (0x80 >> j)), j-2);
subchannel[j + i * 8] += ShiftLeft((byte)(sub.s[i] & (0x80 >> j)), j-3);
subchannel[j + i * 8] += ShiftLeft((byte)(sub.t[i] & (0x80 >> j)), j-4);
subchannel[j + i * 8] += ShiftLeft((byte)(sub.u[i] & (0x80 >> j)), j-5);
subchannel[j + i * 8] += ShiftLeft((byte)(sub.v[i] & (0x80 >> j)), j-6);
subchannel[j + i * 8] += ShiftLeft((byte)(sub.w[i] & (0x80 >> j)), j-7);
}
}
return subchannel;
}
public static byte ShiftRight(byte value, int shifted)
{
return shifted < 0 ? (byte)(value << Math.Abs(shifted)) : (byte)(value >> shifted);
}
public static byte ShiftLeft(byte value, int shifted)
{
return shifted < 0 ? (byte)(value >> Math.Abs(shifted)) : (byte)(value << shifted);
}
public static void Usage() public static void Usage()
{ {
Console.WriteLine(); Console.WriteLine();