diff --git a/CdgLib/CDGFile.cs b/CdgLib/CDGFile.cs index e38217d..cfcc6b9 100644 --- a/CdgLib/CDGFile.cs +++ b/CdgLib/CDGFile.cs @@ -2,46 +2,16 @@ using System.Drawing; using System.Drawing.Imaging; using System.IO; +using System.Linq; +using System.Threading.Tasks; using System.Xml.Schema; namespace CdgLib { - public class CdgFile : IDisposable + public class CdgFile : FileStream { private const int ColourTableSize = 16; - - // To detect redundant calls - private bool _disposedValue; - - public void Dispose() - { - - Dispose(true); - GC.SuppressFinalize(this); - } - - - // IDisposable - protected virtual void Dispose(bool disposing) - { - if (!_disposedValue) - { - if (disposing) - { - _mPStream.Close(); - } - _mPStream = null; - _mPSurface = null; - } - _disposedValue = true; - } - - #region "Constants" - - //CDG Command Code - private const byte CdgCommand = 0x9; - //CDG Instruction Codes private const int CdgInstMemoryPreset = 1; private const int CdgInstBorderPreset = 2; private const int CdgInstTileBlock = 6; @@ -50,51 +20,27 @@ namespace CdgLib private const int CdgInstDefTranspCol = 28; private const int CdgInstLoadColTblLo = 30; private const int CdgInstLoadColTblHigh = 31; - private const int CdgInstTileBlockXor = 38; - //Bitmask for all CDG fields private const byte CdgMask = 0x3f; private const int CdgPacketSize = 24; private const int TileHeight = 12; - private const int TileWidth = 6; - //This is the size of the display as defined by the CDG specification. - //The pixels in this region can be painted, and scrolling operations - //rotate through this number of pixels. public const int CdgFullWidth = 300; - public const int CdgFullHeight = 216; - //This is the size of the screen that is actually intended to be - //visible. It is the center area of CDG_FULL. private const int CdgDisplayWidth = 294; - private const int CdgDisplayHeight = 204; - - #endregion - - #region "Private Declarations" - private readonly byte[,] _mPixelColours = new byte[CdgFullHeight, CdgFullWidth]; private readonly int[] _mColourTable = new int[ColourTableSize]; private int _mPresetColourIndex; private int _mBorderColourIndex; - private int _mTransparentColour; private int _mHOffset; - private int _mVOffset; private CdgFileIoStream _mPStream; private Surface _mPSurface; - private long _mPositionMs; - + private long _previousPosition; private long _mDuration; - private Bitmap _mImage; - - #endregion - - #region "Properties" - public bool Transparent => true; public Image RgbImage @@ -129,10 +75,6 @@ namespace CdgLib } } - #endregion - - #region "Public Methods" - //Png Export public void SavePng(string filename) { @@ -140,170 +82,107 @@ namespace CdgLib } //New - public CdgFile(string cdgFileName) + public CdgFile(string path, FileMode mode, FileAccess fileAccess) : base(path, mode, fileAccess) { - _mPStream = new CdgFileIoStream(); - _mPStream.Open(cdgFileName); _mPSurface = new Surface(); - if (_mPStream != null && _mPSurface != null) - { - Reset(); - _mDuration = _mPStream.Getsize()/CdgPacketSize*1000/300; - } } + + private long Duration => Length / CdgPacketSize * 1000 / 300; + public long GetTotalDuration() { return _mDuration; } - public bool RenderAtPosition(long ms) + public async Task RenderAtPosition(long position) { - var pack = new CdgPacket(); - long numPacks = 0; - var res = true; - - if (_mPStream == null) + long numberOfSubCodePackets = 0; + + if (position < _previousPosition) { - return false; - } - - if (ms < _mPositionMs) - { - if (_mPStream.Seek(0, SeekOrigin.Begin) < 0) - return false; - _mPositionMs = 0; + Position = 0; + _previousPosition = 0; } //duration of one packet is 1/300 seconds (4 packets per sector, 75 sectors per second) - - numPacks = ms - _mPositionMs; - numPacks /= 10; - - _mPositionMs += numPacks*10; - numPacks *= 3; + //300p/s == 300p/1000ms == 3p/10 + var timeToRender = position - _previousPosition; + _previousPosition += timeToRender; + numberOfSubCodePackets=(timeToRender*3)/10; //TODO: double check logic due to inline while loop fucntionality //AndAlso m_pSurface.rgbData Is Nothing - while (numPacks > 0) + while (numberOfSubCodePackets > 0) { - res = ReadPacket(ref pack); - ProcessPacket(ref pack); - numPacks -= 1; + var pack = await ReadSubCode(); + ProcessPacket(pack); + numberOfSubCodePackets -= 1; } Render(); - return res; + return true; } - #endregion - - #region "Private Methods" - - private void Reset() + private async Task ReadSubCode() { - Array.Clear(_mPixelColours, 0, _mPixelColours.Length); - Array.Clear(_mColourTable, 0, _mColourTable.Length); + var subCode = new SubCodePacket(); + byte[] buffer = new byte[24]; + var bytesRead = await ReadAsync(buffer, 0, 24); - _mPresetColourIndex = 0; - _mBorderColourIndex = 0; - _mTransparentColour = 0; - _mHOffset = 0; - _mVOffset = 0; - - _mDuration = 0; - _mPositionMs = 0; - - //clear surface - if (_mPSurface.RgbData != null) + if (bytesRead < 24) { - Array.Clear(_mPSurface.RgbData, 0, _mPSurface.RgbData.Length); - } - } - - private bool ReadPacket(ref CdgPacket pack) - { - if (_mPStream == null || _mPStream.Eof()) - { - return false; + return new SubCodePacket(); } - var read = 0; + Array.Copy(buffer, 0, subCode.Command, 0, 1); + Array.Copy(buffer, 1, subCode.Instruction, 0, 1); + Array.Copy(buffer, 2, subCode.ParityQ, 0, 2); + Array.Copy(buffer, 4, subCode.Data, 0, 16); + Array.Copy(buffer, 20, subCode.ParityP, 0, 4); - read += _mPStream.Read(ref pack.Command, 1); - read += _mPStream.Read(ref pack.Instruction, 1); - read += _mPStream.Read(ref pack.ParityQ, 2); - read += _mPStream.Read(ref pack.Data, 16); - read += _mPStream.Read(ref pack.ParityP, 4); - - return read == 24; + return subCode; } - private void ProcessPacket(ref CdgPacket pack) + private void ProcessPacket(SubCodePacket subCodePacketPacket) { - var instCode = 0; - - if ((pack.Command[0] & CdgMask) == CdgCommand) + if ((subCodePacketPacket.Command[0] & CdgMask) != CdgCommand) return; + var instructionCode = subCodePacketPacket.Instruction[0] & CdgMask; + switch (instructionCode) { - instCode = pack.Instruction[0] & CdgMask; - switch (instCode) - { - case CdgInstMemoryPreset: - MemoryPreset(ref pack); - - - break; - case CdgInstBorderPreset: - BorderPreset(ref pack); - - - break; - case CdgInstTileBlock: - TileBlock(ref pack, false); - - - break; - case CdgInstScrollPreset: - Scroll(ref pack, false); - - - break; - case CdgInstScrollCopy: - Scroll(ref pack, true); - - - break; - case CdgInstDefTranspCol: - DefineTransparentColour(ref pack); - - - break; - case CdgInstLoadColTblLo: - LoadColorTable(ref pack, 0); - - - break; - case CdgInstLoadColTblHigh: - LoadColorTable(ref pack, 1); - - - break; - case CdgInstTileBlockXor: - TileBlock(ref pack, true); - - - break; - default: - //Ignore the unsupported commands - - break; - } + case CdgInstMemoryPreset: + MemoryPreset(ref subCodePacketPacket); + break; + case CdgInstBorderPreset: + BorderPreset(ref subCodePacketPacket); + break; + case CdgInstTileBlock: + TileBlock(ref subCodePacketPacket, false); + break; + case CdgInstScrollPreset: + Scroll(ref subCodePacketPacket, false); + break; + case CdgInstScrollCopy: + Scroll(ref subCodePacketPacket, true); + break; + case CdgInstDefTranspCol: + DefineTransparentColour(ref subCodePacketPacket); + break; + case CdgInstLoadColTblLo: + LoadColorTable(ref subCodePacketPacket, 0); + break; + case CdgInstLoadColTblHigh: + LoadColorTable(ref subCodePacketPacket, 1); + break; + case CdgInstTileBlockXor: + TileBlock(ref subCodePacketPacket, true); + break; } } - private void MemoryPreset(ref CdgPacket pack) + private void MemoryPreset(ref SubCodePacket pack) { var colour = 0; var ri = 0; @@ -336,14 +215,14 @@ namespace CdgLib { for (ci = 0; ci <= CdgFullWidth - 1; ci++) { - _mPixelColours[ri, ci] = (byte) colour; + _mPixelColours[ri, ci] = (byte)colour; } } } } - private void BorderPreset(ref CdgPacket pack) + private void BorderPreset(ref SubCodePacket pack) { var colour = 0; var ri = 0; @@ -360,12 +239,12 @@ namespace CdgLib { for (ci = 0; ci <= 5; ci++) { - _mPixelColours[ri, ci] = (byte) colour; + _mPixelColours[ri, ci] = (byte)colour; } for (ci = CdgFullWidth - 6; ci <= CdgFullWidth - 1; ci++) { - _mPixelColours[ri, ci] = (byte) colour; + _mPixelColours[ri, ci] = (byte)colour; } } @@ -373,18 +252,18 @@ namespace CdgLib { for (ri = 0; ri <= 11; ri++) { - _mPixelColours[ri, ci] = (byte) colour; + _mPixelColours[ri, ci] = (byte)colour; } for (ri = CdgFullHeight - 12; ri <= CdgFullHeight - 1; ri++) { - _mPixelColours[ri, ci] = (byte) colour; + _mPixelColours[ri, ci] = (byte)colour; } } } - private void LoadColorTable(ref CdgPacket pack, int table) + private void LoadColorTable(ref SubCodePacket pack, int table) { for (var i = 0; i <= 7; i++) { @@ -392,8 +271,8 @@ namespace CdgLib //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 - var byte0 = pack.Data[2*i]; - var byte1 = pack.Data[2*i + 1]; + var byte0 = pack.Data[2 * i]; + var byte1 = pack.Data[2 * i + 1]; var red = (byte0 & 0x3f) >> 2; var green = ((byte0 & 0x3) << 2) | ((byte1 & 0x3f) >> 4); var blue = byte1 & 0xf; @@ -404,13 +283,13 @@ namespace CdgLib if (_mPSurface != null) { - _mColourTable[i + table*8] = _mPSurface.MapRgbColour(red, green, blue); + _mColourTable[i + table * 8] = _mPSurface.MapRgbColour(red, green, blue); } } } - private void TileBlock(ref CdgPacket pack, bool bXor) + private void TileBlock(ref SubCodePacket pack, bool bXor) { var colour0 = 0; var colour1 = 0; @@ -424,8 +303,8 @@ namespace CdgLib colour0 = pack.Data[0] & 0xf; colour1 = pack.Data[1] & 0xf; - rowIndex = (pack.Data[2] & 0x1f)*12; - columnIndex = (pack.Data[3] & 0x3f)*6; + rowIndex = (pack.Data[2] & 0x1f) * 12; + columnIndex = (pack.Data[3] & 0x3f) * 6; if (rowIndex > CdgFullHeight - TileHeight) return; @@ -475,18 +354,18 @@ namespace CdgLib //Set the pixel with the new colour. We set both the surfarray //containing actual RGB values, as well as our array containing //the colour indexes into our colour table. - _mPixelColours[rowIndex + i, columnIndex + j] = (byte) newCol; + _mPixelColours[rowIndex + i, columnIndex + j] = (byte)newCol; } } } - private void DefineTransparentColour(ref CdgPacket pack) + private void DefineTransparentColour(ref SubCodePacket pack) { _mTransparentColour = pack.Data[0] & 0xf; } - private void Scroll(ref CdgPacket pack, bool copy) + private void Scroll(ref SubCodePacket pack, bool copy) { var colour = 0; var hScroll = 0; @@ -555,7 +434,7 @@ namespace CdgLib { for (ci = 0; ci <= CdgFullWidth - 1; ci++) { - temp[(ri + vInc)%CdgFullHeight, (ci + hInc)%CdgFullWidth] = _mPixelColours[ri, ci]; + temp[(ri + vInc) % CdgFullHeight, (ci + hInc) % CdgFullWidth] = _mPixelColours[ri, ci]; } } @@ -572,7 +451,7 @@ namespace CdgLib { for (ri = 0; ri <= vScrollPixels - 1; ri++) { - temp[ri, ci] = (byte) colour; + temp[ri, ci] = (byte)colour; } } } @@ -582,7 +461,7 @@ namespace CdgLib { for (ri = CdgFullHeight + vScrollPixels; ri <= CdgFullHeight - 1; ri++) { - temp[ri, ci] = (byte) colour; + temp[ri, ci] = (byte)colour; } } } @@ -594,7 +473,7 @@ namespace CdgLib { for (ri = 0; ri <= CdgFullHeight - 1; ri++) { - temp[ri, ci] = (byte) colour; + temp[ri, ci] = (byte)colour; } } } @@ -604,7 +483,7 @@ namespace CdgLib { for (ri = 0; ri <= CdgFullHeight - 1; ri++) { - temp[ri, ci] = (byte) colour; + temp[ri, ci] = (byte)colour; } } } @@ -621,7 +500,6 @@ namespace CdgLib } } - private void Render() { if (_mPSurface == null) @@ -643,6 +521,5 @@ namespace CdgLib } } - #endregion } } \ No newline at end of file diff --git a/CdgLib/CdgFileIoStream.cs b/CdgLib/CdgFileIoStream.cs index 91a4ff0..624a033 100644 --- a/CdgLib/CdgFileIoStream.cs +++ b/CdgLib/CdgFileIoStream.cs @@ -75,7 +75,7 @@ namespace CdgLib public bool Open(string filename) { Close(); - _cdgFile = new FileStream(filename, FileMode.Open); + _cdgFile = new FileStream(filename, FileMode.Open, FileAccess.Read); return _cdgFile != null; } diff --git a/CdgLib/CdgLib.csproj b/CdgLib/CdgLib.csproj index a516b92..56f3a50 100644 --- a/CdgLib/CdgLib.csproj +++ b/CdgLib/CdgLib.csproj @@ -44,7 +44,7 @@ - + diff --git a/CdgLib/cdgPacket.cs b/CdgLib/SubCodePacket.cs similarity index 89% rename from CdgLib/cdgPacket.cs rename to CdgLib/SubCodePacket.cs index 636686c..9bf23bf 100644 --- a/CdgLib/cdgPacket.cs +++ b/CdgLib/SubCodePacket.cs @@ -1,6 +1,6 @@ namespace CdgLib { - public class CdgPacket + public class SubCodePacket { public byte[] Command = new byte[1]; public byte[] Data = new byte[16]; diff --git a/KaraokeConverter/ExportAVI.cs b/KaraokeConverter/ExportAVI.cs index 782cf7f..44bfd96 100644 --- a/KaraokeConverter/ExportAVI.cs +++ b/KaraokeConverter/ExportAVI.cs @@ -1,5 +1,6 @@ using System; using System.Drawing; +using System.IO; using System.Text.RegularExpressions; using System.Windows.Forms; using AviFile; @@ -18,7 +19,7 @@ namespace KaraokeConverter Bitmap backgroundBmp = null; Bitmap mergedBMP = null; VideoStream aviStream = null; - var myCDGFile = new CdgFile(cdgFileName); + var myCDGFile = new CdgFile(cdgFileName, FileMode.Open, FileAccess.Read); myCDGFile.RenderAtPosition(0); var bitmap__1 = (Bitmap) myCDGFile.RgbImage; if (!string.IsNullOrEmpty(backgroundFileName)) diff --git a/KaraokePlayer/KaraokeVideoPlayer.cs b/KaraokePlayer/KaraokeVideoPlayer.cs index a4d1e16..98f7d06 100644 --- a/KaraokePlayer/KaraokeVideoPlayer.cs +++ b/KaraokePlayer/KaraokeVideoPlayer.cs @@ -22,20 +22,19 @@ namespace KaraokePlayer public KaraokeVideoPlayer() { InitializeComponent(); - _lyricTimer.Interval = 30; + _lyricTimer.Interval = 50; _lyricTimer.Elapsed += LyricTimerOnElapsed; } private async void LyricTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs) { - System.Diagnostics.Debug.Print(DateTime.Now.Millisecond.ToString()); + System.Diagnostics.Debug.Print((DateTime.Now - _startTime).TotalMilliseconds.ToString()); if (vlcPlayer.IsPlaying) { - await Task.Run(() => - { - _cdgFile.RenderAtPosition( + + await _cdgFile.RenderAtPosition( (long)(DateTime.Now - _startTime).TotalMilliseconds); - }); + Invoke((MethodInvoker)(() => @@ -53,7 +52,7 @@ namespace KaraokePlayer public void Play(Uri file) { vlcPlayer.SetMedia(file); - _cdgFile = new CdgFile(Path.ChangeExtension(file.LocalPath, "cdg")); + _cdgFile = new CdgFile(Path.ChangeExtension(file.LocalPath, "cdg"), FileMode.Open, FileAccess.Read); vlcPlayer.Play(); }