refactoring progress

This commit is contained in:
Brett Sanderson 2016-03-04 14:11:49 -05:00
parent 5b227c39ae
commit 9e9ff00e2b
10 changed files with 150 additions and 181 deletions

View File

@ -42,9 +42,12 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="CdgFile.cs" /> <Compile Include="SubCode\Command.cs" />
<Compile Include="SubCode\Instruction.cs" />
<Compile Include="GraphicsFile.cs" />
<Compile Include="CdgFileIoStream.cs" /> <Compile Include="CdgFileIoStream.cs" />
<Compile Include="SubCodePacket.cs" /> <Compile Include="Graphic.cs" />
<Compile Include="SubCode\Packet.cs" />
<Compile Include="GraphicUtil.cs" /> <Compile Include="GraphicUtil.cs" />
<Compile Include="Surface.cs" /> <Compile Include="Surface.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -1,80 +1,40 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using CdgLib.SubCode;
namespace CdgLib namespace CdgLib
{ {
public class CdgFile : FileStream public class Graphic
{ {
private const int ColourTableSize = 16; private int _mPresetColourIndex;
private const byte CdgCommand = 0x9;
private const int CdgInstMemoryPreset = 1;
private const int CdgInstBorderPreset = 2;
private const int CdgInstTileBlock = 6;
private const int CdgInstScrollPreset = 20;
private const int CdgInstScrollCopy = 24;
private const int CdgInstDefTranspCol = 28;
private const int CdgInstLoadColTblLo = 30;
private const int CdgInstLoadColTblHigh = 31;
private const int CdgInstTileBlockXor = 38;
private const byte CdgMask = 0x3f;
private const int CdgPacketSize = 24;
private const int TileHeight = 12;
private const int TileWidth = 6;
public const int FullWidth = 300;
public const int FullHeight = 216;
private const int CdgDisplayWidth = 294;
private const int CdgDisplayHeight = 204;
private readonly int[] _mColourTable = new int[ColourTableSize];
private readonly byte[,] _mPixelColours = new byte[FullHeight, FullWidth];
private int _mBorderColourIndex; private int _mBorderColourIndex;
private long _mDuration; private long _mDuration;
private int _mHOffset; private int _mHOffset;
private Bitmap _mImage; private Bitmap _mImage;
private int _mPresetColourIndex;
private CdgFileIoStream _mPStream; private CdgFileIoStream _mPStream;
private readonly Surface _mPSurface; private readonly Surface _mPSurface;
private int _mTransparentColour; private int _mTransparentColour;
private int _mVOffset; private int _mVOffset;
private long _previousPosition;
public CdgFile(string path, FileMode mode, FileAccess fileAccess) : base(path, mode, fileAccess, FileShare.Read) private const byte Command = 0x9;
private const byte CdgMask = 0x3f;
private const int CdgDisplayWidth = 294;
private const int CdgDisplayHeight = 204;
private int[,] _graphicData;
public Graphic(IEnumerable<Packet> packets)
{ {
_mPSurface = new Surface();
} }
public bool Transparent => true; public Bitmap ToBitmap()
public long Duration => Length/CdgPacketSize*1000/300;
public async Task<Bitmap> Render(long position = -1)
{ {
if (position < 0)
{
position = _previousPosition + CdgPacketSize;
}
if (position < _previousPosition)
{
Reset();
}
//duration of one packet is 1/300 seconds (4 packets per sector, 75 sectors per second)
//p=t*3/10 t=p*10/3 t=milliseconds, p=packets
var timeToRender = position - _previousPosition;
_previousPosition += timeToRender;
var numberOfSubCodePackets = timeToRender*3/10;
var subCodePackets = await ReadSubCodeAsync(numberOfSubCodePackets);
foreach (var subCodePacket in subCodePackets)
{
ProcessPacket(subCodePacket);
}
RenderSurface();
Bitmap myBitmap; Bitmap myBitmap;
using (var bitmapStream = new MemoryStream()) using (var bitmapStream = new MemoryStream())
{ {
@ -85,95 +45,50 @@ namespace CdgLib
} }
myBitmap = GraphicUtil.StreamToBitmap(bitmapStream, FullWidth, FullHeight); myBitmap = GraphicUtil.StreamToBitmap(bitmapStream, FullWidth, FullHeight);
} }
myBitmap.MakeTransparent(myBitmap.GetPixel(1, 1));
if (Transparent)
{
myBitmap.MakeTransparent(myBitmap.GetPixel(1, 1));
}
return myBitmap; return myBitmap;
}
private void Reset()
{
Position = 0;
Array.Clear(_mPixelColours, 0, _mPixelColours.Length);
Array.Clear(_mColourTable, 0, _mColourTable.Length);
_mPresetColourIndex = 0;
_mBorderColourIndex = 0;
_mTransparentColour = 0;
_mHOffset = 0;
_mVOffset = 0;
_mDuration = 0;
_previousPosition = 0;
//clear surface
if (_mPSurface.RgbData != null)
{
Array.Clear(_mPSurface.RgbData, 0, _mPSurface.RgbData.Length);
}
}
private async Task<IEnumerable<SubCodePacket>> ReadSubCodeAsync(long numberOfPackets)
{
var subCodePackets = new List<SubCodePacket>();
var buffer = new byte[CdgPacketSize*numberOfPackets];
var bytesRead = await ReadAsync(buffer, 0, buffer.Length);
for (var i = 0; i < bytesRead/CdgPacketSize; i++)
{
var subCodePacket = new SubCodePacket();
Array.Copy(buffer, i*CdgPacketSize + 0, subCodePacket.Command, 0, 1);
Array.Copy(buffer, i*CdgPacketSize + 1, subCodePacket.Instruction, 0, 1);
Array.Copy(buffer, i*CdgPacketSize + 2, subCodePacket.ParityQ, 0, 2);
Array.Copy(buffer, i*CdgPacketSize + 4, subCodePacket.Data, 0, 16);
Array.Copy(buffer, i*CdgPacketSize + 20, subCodePacket.ParityP, 0, 4);
subCodePackets.Add(subCodePacket);
}
return subCodePackets;
} }
private void ProcessPacket(SubCodePacket subCodePacketPacket) private void ProcessPacket(Packet packetPacket)
{ {
if ((subCodePacketPacket.Command[0] & CdgMask) != CdgCommand) return; if ((packetPacket.Command[0] & CdgMask) != Command) return;
var instructionCode = subCodePacketPacket.Instruction[0] & CdgMask; var instructionCode = (Instruction)(packetPacket.Instruction[0] & CdgMask);
switch (instructionCode) switch (instructionCode)
{ {
case CdgInstMemoryPreset: case Instruction.MemoryPreset:
MemoryPreset(subCodePacketPacket); MemoryPreset(packetPacket);
break; break;
case CdgInstBorderPreset: case Instruction.BorderPreset:
BorderPreset(subCodePacketPacket); BorderPreset(packetPacket);
break; break;
case CdgInstTileBlock: case Instruction.TileBlockNormal:
TileBlock(subCodePacketPacket, false); TileBlock(packetPacket, false);
break; break;
case CdgInstScrollPreset: case Instruction.ScrollPreset:
Scroll(subCodePacketPacket, false); Scroll(packetPacket, false);
break; break;
case CdgInstScrollCopy: case Instruction.ScrollCopy:
Scroll(subCodePacketPacket, true); Scroll(packetPacket, true);
break; break;
case CdgInstDefTranspCol: case Instruction.DefineTransparentColor:
DefineTransparentColour(subCodePacketPacket); DefineTransparentColour(packetPacket);
break; break;
case CdgInstLoadColTblLo: case Instruction.LoadColorTableLower:
LoadColorTable(subCodePacketPacket, 0); LoadColorTable(packetPacket, 0);
break; break;
case CdgInstLoadColTblHigh: case Instruction.LoadColorTableUpper:
LoadColorTable(subCodePacketPacket, 1); LoadColorTable(packetPacket, 1);
break; break;
case CdgInstTileBlockXor: case Instruction.TileBlockXor:
TileBlock(subCodePacketPacket, true); TileBlock(packetPacket, true);
break; break;
} }
} }
private void MemoryPreset(SubCodePacket pack) private void MemoryPreset(Packet pack)
{ {
var colour = 0; var colour = 0;
var ri = 0; var ri = 0;
@ -206,14 +121,34 @@ namespace CdgLib
{ {
for (ci = 0; ci <= FullWidth - 1; ci++) for (ci = 0; ci <= FullWidth - 1; ci++)
{ {
_mPixelColours[ri, ci] = (byte) colour; _mPixelColours[ri, ci] = (byte)colour;
} }
} }
} }
} }
private void Reset()
{
Position = 0;
Array.Clear(_mPixelColours, 0, _mPixelColours.Length);
Array.Clear(_mColourTable, 0, _mColourTable.Length);
private void BorderPreset(SubCodePacket pack) _mBorderColourIndex = 0;
_mTransparentColour = 0;
_mHOffset = 0;
_mVOffset = 0;
_mDuration = 0;
_previousPosition = 0;
//clear surface
if (_mPSurface.RgbData != null)
{
Array.Clear(_mPSurface.RgbData, 0, _mPSurface.RgbData.Length);
}
}
private void BorderPreset(Packet pack)
{ {
var colour = 0; var colour = 0;
var ri = 0; var ri = 0;
@ -230,12 +165,12 @@ namespace CdgLib
{ {
for (ci = 0; ci <= 5; ci++) for (ci = 0; ci <= 5; ci++)
{ {
_mPixelColours[ri, ci] = (byte) colour; _mPixelColours[ri, ci] = (byte)colour;
} }
for (ci = FullWidth - 6; ci <= FullWidth - 1; ci++) for (ci = FullWidth - 6; ci <= FullWidth - 1; ci++)
{ {
_mPixelColours[ri, ci] = (byte) colour; _mPixelColours[ri, ci] = (byte)colour;
} }
} }
@ -243,18 +178,18 @@ namespace CdgLib
{ {
for (ri = 0; ri <= 11; ri++) for (ri = 0; ri <= 11; ri++)
{ {
_mPixelColours[ri, ci] = (byte) colour; _mPixelColours[ri, ci] = (byte)colour;
} }
for (ri = FullHeight - 12; ri <= FullHeight - 1; ri++) for (ri = FullHeight - 12; ri <= FullHeight - 1; ri++)
{ {
_mPixelColours[ri, ci] = (byte) colour; _mPixelColours[ri, ci] = (byte)colour;
} }
} }
} }
private void LoadColorTable(SubCodePacket pack, int table) private void LoadColorTable(Packet pack, int table)
{ {
for (var i = 0; i <= 7; i++) for (var i = 0; i <= 7; i++)
{ {
@ -262,8 +197,8 @@ namespace CdgLib
//7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 //7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
//X X r r r r g g X X g g b b b b //X X r r r r g g X X g g b b b b
var byte0 = pack.Data[2*i]; var byte0 = pack.Data[2 * i];
var byte1 = pack.Data[2*i + 1]; var byte1 = pack.Data[2 * i + 1];
var red = (byte0 & 0x3f) >> 2; var red = (byte0 & 0x3f) >> 2;
var green = ((byte0 & 0x3) << 2) | ((byte1 & 0x3f) >> 4); var green = ((byte0 & 0x3) << 2) | ((byte1 & 0x3f) >> 4);
var blue = byte1 & 0xf; var blue = byte1 & 0xf;
@ -274,13 +209,13 @@ namespace CdgLib
if (_mPSurface != null) if (_mPSurface != null)
{ {
_mColourTable[i + table*8] = _mPSurface.MapRgbColour(red, green, blue); _mColourTable[i + table * 8] = _mPSurface.MapRgbColour(red, green, blue);
} }
} }
} }
private void TileBlock(SubCodePacket pack, bool bXor) private void TileBlock(Packet pack, bool bXor)
{ {
var colour0 = 0; var colour0 = 0;
var colour1 = 0; var colour1 = 0;
@ -294,8 +229,8 @@ namespace CdgLib
colour0 = pack.Data[0] & 0xf; colour0 = pack.Data[0] & 0xf;
colour1 = pack.Data[1] & 0xf; colour1 = pack.Data[1] & 0xf;
rowIndex = (pack.Data[2] & 0x1f)*12; rowIndex = (pack.Data[2] & 0x1f) * 12;
columnIndex = (pack.Data[3] & 0x3f)*6; columnIndex = (pack.Data[3] & 0x3f) * 6;
if (rowIndex > FullHeight - TileHeight) if (rowIndex > FullHeight - TileHeight)
return; return;
@ -345,18 +280,18 @@ namespace CdgLib
//Set the pixel with the new colour. We set both the surfarray //Set the pixel with the new colour. We set both the surfarray
//containing actual RGB values, as well as our array containing //containing actual RGB values, as well as our array containing
//the colour indexes into our colour table. //the colour indexes into our colour table.
_mPixelColours[rowIndex + i, columnIndex + j] = (byte) newCol; _mPixelColours[rowIndex + i, columnIndex + j] = (byte)newCol;
} }
} }
} }
private void DefineTransparentColour(SubCodePacket pack) private void DefineTransparentColour(Packet pack)
{ {
_mTransparentColour = pack.Data[0] & 0xf; _mTransparentColour = pack.Data[0] & 0xf;
} }
private void Scroll(SubCodePacket pack, bool copy) private void Scroll(Packet pack, bool copy)
{ {
var colour = 0; var colour = 0;
var hScroll = 0; var hScroll = 0;
@ -425,7 +360,7 @@ namespace CdgLib
{ {
for (ci = 0; ci <= FullWidth - 1; ci++) for (ci = 0; ci <= FullWidth - 1; ci++)
{ {
temp[(ri + vInc)%FullHeight, (ci + hInc)%FullWidth] = _mPixelColours[ri, ci]; temp[(ri + vInc) % FullHeight, (ci + hInc) % FullWidth] = _mPixelColours[ri, ci];
} }
} }
@ -442,7 +377,7 @@ namespace CdgLib
{ {
for (ri = 0; ri <= vScrollPixels - 1; ri++) for (ri = 0; ri <= vScrollPixels - 1; ri++)
{ {
temp[ri, ci] = (byte) colour; temp[ri, ci] = (byte)colour;
} }
} }
} }
@ -452,7 +387,7 @@ namespace CdgLib
{ {
for (ri = FullHeight + vScrollPixels; ri <= FullHeight - 1; ri++) for (ri = FullHeight + vScrollPixels; ri <= FullHeight - 1; ri++)
{ {
temp[ri, ci] = (byte) colour; temp[ri, ci] = (byte)colour;
} }
} }
} }
@ -464,7 +399,7 @@ namespace CdgLib
{ {
for (ri = 0; ri <= FullHeight - 1; ri++) for (ri = 0; ri <= FullHeight - 1; ri++)
{ {
temp[ri, ci] = (byte) colour; temp[ri, ci] = (byte)colour;
} }
} }
} }
@ -474,7 +409,7 @@ namespace CdgLib
{ {
for (ri = 0; ri <= FullHeight - 1; ri++) for (ri = 0; ri <= FullHeight - 1; ri++)
{ {
temp[ri, ci] = (byte) colour; temp[ri, ci] = (byte)colour;
} }
} }
} }
@ -490,26 +425,5 @@ namespace CdgLib
} }
} }
} }
private void RenderSurface()
{
if (_mPSurface == null)
return;
for (var ri = 0; ri <= FullHeight - 1; ri++)
{
for (var ci = 0; ci <= FullWidth - 1; ci++)
{
if (ri < TileHeight || ri >= FullHeight - TileHeight || ci < TileWidth ||
ci >= FullWidth - TileWidth)
{
_mPSurface.RgbData[ri, ci] = _mColourTable[_mBorderColourIndex];
}
else
{
_mPSurface.RgbData[ri, ci] = _mColourTable[_mPixelColours[ri + _mVOffset, ci + _mHOffset]];
}
}
}
}
} }
} }

View File

@ -61,7 +61,7 @@ namespace CdgLib
public static Bitmap GetCdgSizeBitmap(string filename) public static Bitmap GetCdgSizeBitmap(string filename)
{ {
var bm = new Bitmap(filename); var bm = new Bitmap(filename);
return ResizeBitmap(ref bm, CdgFile.FullWidth, CdgFile.FullHeight); return ResizeBitmap(ref bm, GraphicsFile.FullWidth, GraphicsFile.FullHeight);
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,7 @@
namespace CdgLib.SubCode
{
internal enum Command : byte
{
Graphic = 0x9
}
}

View File

@ -0,0 +1,45 @@
namespace CdgLib.SubCode
{
/// <summary>
///
/// </summary>
internal enum Instruction
{
/// <summary>
/// Set the screen to a particular color.
/// </summary>
MemoryPreset = 1,
/// <summary>
/// Set the border of the screen to a particular color.
/// </summary>
BorderPreset = 2,
/// <summary>
/// Load a 12 x 6, 2 color tile and display it normally.
/// </summary>
TileBlockNormal = 6,
/// <summary>
/// Scroll the image, filling in the new area with a color.
/// </summary>
ScrollPreset = 20,
/// <summary>
/// Scroll the image, rotating the bits back around.
/// </summary>
ScrollCopy = 24,
/// <summary>
/// Define a specific color as being transparent.
/// </summary>
DefineTransparentColor = 28,
/// <summary>
/// (entries 0-7) Load in the lower 8 entries of the color table.
/// </summary>
LoadColorTableLower = 30,
/// <summary>
/// (entries 8-15) Load in the upper 8 entries of the color table.
/// </summary>
LoadColorTableUpper = 31,
/// <summary>
/// Load a 12 x 6, 2 color tile and display it using the XOR method.
/// </summary>
TileBlockXor = 38
}
}

View File

@ -1,6 +1,6 @@
namespace CdgLib namespace CdgLib.SubCode
{ {
public class SubCodePacket public class Packet
{ {
public byte[] Command = new byte[1]; public byte[] Command = new byte[1];
public byte[] Data = new byte[16]; public byte[] Data = new byte[16];

View File

@ -4,7 +4,7 @@ namespace CdgLib
{ {
public class Surface public class Surface
{ {
public int[,] RgbData = new int[CdgFile.FullHeight, CdgFile.FullWidth]; public int[,] RgbData = new int[GraphicsFile.FullHeight, GraphicsFile.FullWidth];
public int MapRgbColour(int red, int green, int blue) public int MapRgbColour(int red, int green, int blue)
{ {

View File

@ -19,7 +19,7 @@ namespace KaraokeConverter
Bitmap backgroundBmp = null; Bitmap backgroundBmp = null;
Bitmap mergedBMP = null; Bitmap mergedBMP = null;
VideoStream aviStream = null; VideoStream aviStream = null;
var myCDGFile = new CdgFile(cdgFileName, FileMode.Open, FileAccess.Read); var myCDGFile = new GraphicsFile(cdgFileName, FileMode.Open, FileAccess.Read);
myCDGFile.RenderAtPosition(0); myCDGFile.RenderAtPosition(0);
var bitmap__1 = (Bitmap) myCDGFile.RgbImage; var bitmap__1 = (Bitmap) myCDGFile.RgbImage;
if (!string.IsNullOrEmpty(backgroundFileName)) if (!string.IsNullOrEmpty(backgroundFileName))
@ -27,8 +27,8 @@ namespace KaraokeConverter
try try
{ {
if (IsMovie(backgroundFileName)) if (IsMovie(backgroundFileName))
backgroundBmp = MovieFrameExtractor.GetBitmap(0, backgroundFileName, CdgFile.FullWidth, backgroundBmp = MovieFrameExtractor.GetBitmap(0, backgroundFileName, GraphicsFile.FullWidth,
CdgFile.FullHeight); GraphicsFile.FullHeight);
if (IsGraphic(backgroundFileName)) if (IsGraphic(backgroundFileName))
backgroundBmp = GraphicUtil.GetCdgSizeBitmap(backgroundFileName); backgroundBmp = GraphicUtil.GetCdgSizeBitmap(backgroundFileName);
} }
@ -64,7 +64,7 @@ namespace KaraokeConverter
{ {
if (IsMovie(backgroundFileName)) if (IsMovie(backgroundFileName))
backgroundBmp = MovieFrameExtractor.GetBitmap(position/1000, backgroundFileName, backgroundBmp = MovieFrameExtractor.GetBitmap(position/1000, backgroundFileName,
CdgFile.FullWidth, CdgFile.FullHeight); GraphicsFile.FullWidth, GraphicsFile.FullHeight);
} }
if (backgroundBmp != null) if (backgroundBmp != null)
{ {

View File

@ -25,7 +25,7 @@ namespace KaraokeConverter
#region "Private Declarations" #region "Private Declarations"
private CdgFile mCDGFile; private GraphicsFile mCDGFile;
private CdgFileIoStream mCDGStream; private CdgFileIoStream mCDGStream;
private string mCDGFileName; private string mCDGFileName;
private string mMP3FileName; private string mMP3FileName;

View File

@ -16,7 +16,7 @@ namespace KaraokePlayer
public partial class KaraokeVideoPlayer : UserControl public partial class KaraokeVideoPlayer : UserControl
{ {
private readonly PictureBox _lyrics = new PictureBox {Dock = DockStyle.Fill}; private readonly PictureBox _lyrics = new PictureBox {Dock = DockStyle.Fill};
private CdgFile _cdgFile; private GraphicsFile _cdgFile;
private Image _lyricImage; private Image _lyricImage;
private OverlayForm _overlayForm; private OverlayForm _overlayForm;
private DateTime _startTime; private DateTime _startTime;
@ -39,7 +39,7 @@ namespace KaraokePlayer
public void Play(Uri file) public void Play(Uri file)
{ {
vlcPlayer.SetMedia(file); vlcPlayer.SetMedia(file);
_cdgFile = new CdgFile(Path.ChangeExtension(file.LocalPath, "cdg"), FileMode.Open, FileAccess.Read); _cdgFile = new GraphicsFile(Path.ChangeExtension(file.LocalPath, "cdg"), FileMode.Open, FileAccess.Read);
vlcPlayer.Play(); vlcPlayer.Play();
} }
@ -52,7 +52,7 @@ namespace KaraokePlayer
{ {
var stopwatch = new Stopwatch(); var stopwatch = new Stopwatch();
stopwatch.Start(); stopwatch.Start();
var picture = await _cdgFile.Render((long) (DateTime.Now - _startTime).TotalMilliseconds); var picture = await _cdgFile.RenderAtTime((long) (DateTime.Now - _startTime).TotalMilliseconds);
stopwatch.Reset(); stopwatch.Reset();
Debug.Print(stopwatch.ElapsedMilliseconds.ToString()); Debug.Print(stopwatch.ElapsedMilliseconds.ToString());