diff --git a/CdgLib/CDGFile.cs b/CdgLib/CDGFile.cs
new file mode 100644
index 0000000..71ba040
--- /dev/null
+++ b/CdgLib/CDGFile.cs
@@ -0,0 +1,677 @@
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+
+namespace CdgLib
+{
+ public class CDGFile : IDisposable
+ {
+ private const int COLOUR_TABLE_SIZE = 16;
+
+ // To detect redundant calls
+ private bool disposedValue;
+
+ #region " IDisposable Support "
+
+ // This code added by Visual Basic to correctly implement the disposable pattern.
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ // IDisposable
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ m_pStream.Close();
+ }
+ m_pStream = null;
+ m_pSurface = null;
+ }
+ disposedValue = true;
+ }
+
+ #region "Constants"
+
+ //CDG Command Code
+
+ private const byte CDG_COMMAND = 0x9;
+ //CDG Instruction Codes
+ private const int CDG_INST_MEMORY_PRESET = 1;
+ private const int CDG_INST_BORDER_PRESET = 2;
+ private const int CDG_INST_TILE_BLOCK = 6;
+ private const int CDG_INST_SCROLL_PRESET = 20;
+ private const int CDG_INST_SCROLL_COPY = 24;
+ private const int CDG_INST_DEF_TRANSP_COL = 28;
+ private const int CDG_INST_LOAD_COL_TBL_LO = 30;
+ private const int CDG_INST_LOAD_COL_TBL_HIGH = 31;
+
+ private const int CDG_INST_TILE_BLOCK_XOR = 38;
+ //Bitmask for all CDG fields
+ private const byte CDG_MASK = 0x3f;
+ private const int CDG_PACKET_SIZE = 24;
+ private const int TILE_HEIGHT = 12;
+
+ private const int TILE_WIDTH = 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 CDG_FULL_WIDTH = 300;
+
+ public const int CDG_FULL_HEIGHT = 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 CDG_DISPLAY_WIDTH = 294;
+
+ private const int CDG_DISPLAY_HEIGHT = 204;
+
+ #endregion
+
+ #region "Private Declarations"
+
+ private readonly byte[,] m_pixelColours = new byte[CDG_FULL_HEIGHT, CDG_FULL_WIDTH];
+ private readonly int[] m_colourTable = new int[COLOUR_TABLE_SIZE];
+ private int m_presetColourIndex;
+ private int m_borderColourIndex;
+
+ private int m_transparentColour;
+ private int m_hOffset;
+
+ private int m_vOffset;
+ private CdgFileIoStream m_pStream;
+ private ISurface m_pSurface;
+ private long m_positionMs;
+
+ private long m_duration;
+
+ private Bitmap mImage;
+
+ #endregion
+
+ #region "Properties"
+
+ public bool Transparent { get; set; }
+
+ public Image RgbImage
+ {
+ get
+ {
+ Stream temp = new MemoryStream();
+ try
+ {
+ var i = 0;
+ for (var ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ for (var ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ var ARGBInt = m_pSurface.rgbData[ri, ci];
+ var myByte = new byte[4];
+ myByte = BitConverter.GetBytes(ARGBInt);
+ temp.Write(myByte, 0, 4);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ //Do nothing (empty bitmap will be returned)
+ }
+ var myBitmap = GraphicUtil.StreamToBitmap(ref temp, CDG_FULL_WIDTH, CDG_FULL_HEIGHT);
+ if (Transparent)
+ {
+ myBitmap.MakeTransparent(myBitmap.GetPixel(1, 1));
+ }
+ return myBitmap;
+ }
+ }
+
+ #endregion
+
+ #region "Public Methods"
+
+ //Png Export
+ public void SavePng(string filename)
+ {
+ RgbImage.Save(filename, ImageFormat.Png);
+ }
+
+ //New
+ public CDGFile(string cdgFileName)
+ {
+ m_pStream = new CdgFileIoStream();
+ m_pStream.Open(cdgFileName);
+ m_pSurface = new ISurface();
+ if (m_pStream != null && m_pSurface != null)
+ {
+ reset();
+ m_duration = m_pStream.Getsize() / CDG_PACKET_SIZE * 1000 / 300;
+ }
+ }
+
+ public long getTotalDuration()
+ {
+ return m_duration;
+ }
+
+ public bool renderAtPosition(long ms)
+ {
+ var pack = new CdgPacket();
+ long numPacks = 0;
+ var res = true;
+
+ if (m_pStream == null)
+ {
+ return false;
+ }
+
+ if (ms < m_positionMs)
+ {
+ if (m_pStream.Seek(0, SeekOrigin.Begin) < 0)
+ return false;
+ m_positionMs = 0;
+ }
+
+ //duration of one packet is 1/300 seconds (4 packets per sector, 75 sectors per second)
+
+ numPacks = ms - m_positionMs;
+ numPacks /= 10;
+
+ m_positionMs += numPacks * 10;
+ numPacks *= 3;
+
+ //TODO: double check logic due to inline while loop fucntionality
+ //AndAlso m_pSurface.rgbData Is Nothing
+ while (numPacks > 0)
+ {
+ res = readPacket(ref pack);
+ processPacket(ref pack);
+ numPacks -= 1;
+ }
+
+ render();
+ return res;
+ }
+
+ #endregion
+
+ #region "Private Methods"
+
+ private void reset()
+ {
+ Array.Clear(m_pixelColours, 0, m_pixelColours.Length);
+ Array.Clear(m_colourTable, 0, m_colourTable.Length);
+
+ m_presetColourIndex = 0;
+ m_borderColourIndex = 0;
+ m_transparentColour = 0;
+ m_hOffset = 0;
+ m_vOffset = 0;
+
+ m_duration = 0;
+ m_positionMs = 0;
+
+ //clear surface
+ if (m_pSurface.rgbData != null)
+ {
+ Array.Clear(m_pSurface.rgbData, 0, m_pSurface.rgbData.Length);
+ }
+ }
+
+ private bool readPacket(ref CdgPacket pack)
+ {
+ if (m_pStream == null || m_pStream.Eof())
+ {
+ return false;
+ }
+
+ var read = 0;
+
+ read += m_pStream.Read(ref pack.command, 1);
+ read += m_pStream.Read(ref pack.instruction, 1);
+ read += m_pStream.Read(ref pack.parityQ, 2);
+ read += m_pStream.Read(ref pack.data, 16);
+ read += m_pStream.Read(ref pack.parityP, 4);
+
+ return read == 24;
+ }
+
+
+ private void processPacket(ref CdgPacket pack)
+ {
+ var inst_code = 0;
+
+ if ((pack.command[0] & CDG_MASK) == CDG_COMMAND)
+ {
+ inst_code = pack.instruction[0] & CDG_MASK;
+ switch (inst_code)
+ {
+ case CDG_INST_MEMORY_PRESET:
+ memoryPreset(ref pack);
+
+
+ break;
+ case CDG_INST_BORDER_PRESET:
+ borderPreset(ref pack);
+
+
+ break;
+ case CDG_INST_TILE_BLOCK:
+ tileBlock(ref pack, false);
+
+
+ break;
+ case CDG_INST_SCROLL_PRESET:
+ scroll(ref pack, false);
+
+
+ break;
+ case CDG_INST_SCROLL_COPY:
+ scroll(ref pack, true);
+
+
+ break;
+ case CDG_INST_DEF_TRANSP_COL:
+ defineTransparentColour(ref pack);
+
+
+ break;
+ case CDG_INST_LOAD_COL_TBL_LO:
+ loadColorTable(ref pack, 0);
+
+
+ break;
+ case CDG_INST_LOAD_COL_TBL_HIGH:
+ loadColorTable(ref pack, 1);
+
+
+ break;
+ case CDG_INST_TILE_BLOCK_XOR:
+ tileBlock(ref pack, true);
+
+
+ break;
+ default:
+ //Ignore the unsupported commands
+
+ break;
+ }
+ }
+ }
+
+
+ private void memoryPreset(ref CdgPacket pack)
+ {
+ var colour = 0;
+ var ri = 0;
+ var ci = 0;
+ var repeat = 0;
+
+ colour = pack.data[0] & 0xf;
+ repeat = pack.data[1] & 0xf;
+
+ //Our new interpretation of CD+G Revealed is that memory preset
+ //commands should also change the border
+ m_presetColourIndex = colour;
+ m_borderColourIndex = colour;
+
+ //we have a reliable data stream, so the repeat command
+ //is executed only the first time
+
+
+ if (repeat == 0)
+ {
+ //Note that this may be done before any load colour table
+ //commands by some CDGs. So the load colour table itself
+ //actual recalculates the RGB values for all pixels when
+ //the colour table changes.
+
+ //Set the preset colour for every pixel. Must be stored in
+ //the pixel colour table indeces array
+
+ for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ m_pixelColours[ri, ci] = (byte)colour;
+ }
+ }
+ }
+ }
+
+
+ private void borderPreset(ref CdgPacket pack)
+ {
+ var colour = 0;
+ var ri = 0;
+ var ci = 0;
+
+ colour = pack.data[0] & 0xf;
+ m_borderColourIndex = colour;
+
+ //The border area is the area contained with a rectangle
+ //defined by (0,0,300,216) minus the interior pixels which are contained
+ //within a rectangle defined by (6,12,294,204).
+
+ for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ for (ci = 0; ci <= 5; ci++)
+ {
+ m_pixelColours[ri, ci] = (byte)colour;
+ }
+
+ for (ci = CDG_FULL_WIDTH - 6; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ m_pixelColours[ri, ci] = (byte)colour;
+ }
+ }
+
+ for (ci = 6; ci <= CDG_FULL_WIDTH - 7; ci++)
+ {
+ for (ri = 0; ri <= 11; ri++)
+ {
+ m_pixelColours[ri, ci] = (byte)colour;
+ }
+
+ for (ri = CDG_FULL_HEIGHT - 12; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ m_pixelColours[ri, ci] = (byte)colour;
+ }
+ }
+ }
+
+
+ private void loadColorTable(ref CdgPacket pack, int table)
+ {
+ for (var i = 0; i <= 7; i++)
+ {
+ //[---high byte---] [---low byte----]
+ //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 red = (byte0 & 0x3f) >> 2;
+ var green = ((byte0 & 0x3) << 2) | ((byte1 & 0x3f) >> 4);
+ var blue = byte1 & 0xf;
+
+ red *= 17;
+ green *= 17;
+ blue *= 17;
+
+ if (m_pSurface != null)
+ {
+ m_colourTable[i + table * 8] = m_pSurface.MapRGBColour(red, green, blue);
+ }
+ }
+ }
+
+
+ private void tileBlock(ref CdgPacket pack, bool bXor)
+ {
+ var colour0 = 0;
+ var colour1 = 0;
+ var column_index = 0;
+ var row_index = 0;
+ var myByte = 0;
+ var pixel = 0;
+ var xor_col = 0;
+ var currentColourIndex = 0;
+ var new_col = 0;
+
+ colour0 = pack.data[0] & 0xf;
+ colour1 = pack.data[1] & 0xf;
+ row_index = (pack.data[2] & 0x1f) * 12;
+ column_index = (pack.data[3] & 0x3f) * 6;
+
+ if (row_index > CDG_FULL_HEIGHT - TILE_HEIGHT)
+ return;
+ if (column_index > CDG_FULL_WIDTH - TILE_WIDTH)
+ return;
+
+ //Set the pixel array for each of the pixels in the 12x6 tile.
+ //Normal = Set the colour to either colour0 or colour1 depending
+ //on whether the pixel value is 0 or 1.
+ //XOR = XOR the colour with the colour index currently there.
+
+
+ for (var i = 0; i <= 11; i++)
+ {
+ myByte = pack.data[4 + i] & 0x3f;
+ for (var j = 0; j <= 5; j++)
+ {
+ pixel = (myByte >> (5 - j)) & 0x1;
+ if (bXor)
+ {
+ //Tile Block XOR
+ if (pixel == 0)
+ {
+ xor_col = colour0;
+ }
+ else
+ {
+ xor_col = colour1;
+ }
+
+ //Get the colour index currently at this location, and xor with it
+ currentColourIndex = m_pixelColours[row_index + i, column_index + j];
+ new_col = currentColourIndex ^ xor_col;
+ }
+ else
+ {
+ if (pixel == 0)
+ {
+ new_col = colour0;
+ }
+ else
+ {
+ new_col = colour1;
+ }
+ }
+
+ //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.
+ m_pixelColours[row_index + i, column_index + j] = (byte)new_col;
+ }
+ }
+ }
+
+ private void defineTransparentColour(ref CdgPacket pack)
+ {
+ m_transparentColour = pack.data[0] & 0xf;
+ }
+
+
+ private void scroll(ref CdgPacket pack, bool copy)
+ {
+ var colour = 0;
+ var hScroll = 0;
+ var vScroll = 0;
+ var hSCmd = 0;
+ var hOffset = 0;
+ var vSCmd = 0;
+ var vOffset = 0;
+ var vScrollPixels = 0;
+ var hScrollPixels = 0;
+
+ //Decode the scroll command parameters
+ colour = pack.data[0] & 0xf;
+ hScroll = pack.data[1] & 0x3f;
+ vScroll = pack.data[2] & 0x3f;
+
+ hSCmd = (hScroll & 0x30) >> 4;
+ hOffset = hScroll & 0x7;
+ vSCmd = (vScroll & 0x30) >> 4;
+ vOffset = vScroll & 0xf;
+
+
+ m_hOffset = hOffset < 5 ? hOffset : 5;
+ m_vOffset = vOffset < 11 ? vOffset : 11;
+
+ //Scroll Vertical - Calculate number of pixels
+
+ vScrollPixels = 0;
+ if (vSCmd == 2)
+ {
+ vScrollPixels = -12;
+ }
+ else if (vSCmd == 1)
+ {
+ vScrollPixels = 12;
+ }
+
+ //Scroll Horizontal- Calculate number of pixels
+
+ hScrollPixels = 0;
+ if (hSCmd == 2)
+ {
+ hScrollPixels = -6;
+ }
+ else if (hSCmd == 1)
+ {
+ hScrollPixels = 6;
+ }
+
+ if (hScrollPixels == 0 && vScrollPixels == 0)
+ {
+ return;
+ }
+
+ //Perform the actual scroll.
+
+ var temp = new byte[CDG_FULL_HEIGHT + 1, CDG_FULL_WIDTH + 1];
+ var vInc = vScrollPixels + CDG_FULL_HEIGHT;
+ var hInc = hScrollPixels + CDG_FULL_WIDTH;
+ var ri = 0;
+ //row index
+ var ci = 0;
+ //column index
+
+ for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ temp[(ri + vInc) % CDG_FULL_HEIGHT, (ci + hInc) % CDG_FULL_WIDTH] = m_pixelColours[ri, ci];
+ }
+ }
+
+
+ //if copy is false, we were supposed to fill in the new pixels
+ //with a new colour. Go back and do that now.
+
+
+ if (copy == false)
+ {
+ if (vScrollPixels > 0)
+ {
+ for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ for (ri = 0; ri <= vScrollPixels - 1; ri++)
+ {
+ temp[ri, ci] = (byte)colour;
+ }
+ }
+ }
+ else if (vScrollPixels < 0)
+ {
+ for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ for (ri = CDG_FULL_HEIGHT + vScrollPixels; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ temp[ri, ci] = (byte)colour;
+ }
+ }
+ }
+
+
+ if (hScrollPixels > 0)
+ {
+ for (ci = 0; ci <= hScrollPixels - 1; ci++)
+ {
+ for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ temp[ri, ci] = (byte)colour;
+ }
+ }
+ }
+ else if (hScrollPixels < 0)
+ {
+ for (ci = CDG_FULL_WIDTH + hScrollPixels; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ temp[ri, ci] = (byte)colour;
+ }
+ }
+ }
+ }
+
+ //Now copy the temporary buffer back to our array
+
+ for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ m_pixelColours[ri, ci] = temp[ri, ci];
+ }
+ }
+ }
+
+
+ private void render()
+ {
+ if (m_pSurface == null)
+ return;
+ for (var ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++)
+ {
+ for (var ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++)
+ {
+ if (ri < TILE_HEIGHT || ri >= CDG_FULL_HEIGHT - TILE_HEIGHT || ci < TILE_WIDTH ||
+ ci >= CDG_FULL_WIDTH - TILE_WIDTH)
+ {
+ m_pSurface.rgbData[ri, ci] = m_colourTable[m_borderColourIndex];
+ }
+ else
+ {
+ m_pSurface.rgbData[ri, ci] = m_colourTable[m_pixelColours[ri + m_vOffset, ci + m_hOffset]];
+ }
+ }
+ }
+ }
+
+ #endregion
+ }
+}
+
+
+namespace CdgLib
+{
+ public class CdgPacket
+ {
+ public byte[] command = new byte[1];
+ public byte[] data = new byte[16];
+ public byte[] instruction = new byte[1];
+ public byte[] parityP = new byte[4];
+ public byte[] parityQ = new byte[2];
+ }
+}
+
+namespace CdgLib
+{
+ public class ISurface
+ {
+ public int[,] rgbData = new int[CDGFile.CDG_FULL_HEIGHT, CDGFile.CDG_FULL_WIDTH];
+
+ public int MapRGBColour(int red, int green, int blue)
+ {
+ return Color.FromArgb(red, green, blue).ToArgb();
+ }
+ }
+}
diff --git a/CdgLib/CdgFileIoStream.cs b/CdgLib/CdgFileIoStream.cs
new file mode 100644
index 0000000..8d25f5d
--- /dev/null
+++ b/CdgLib/CdgFileIoStream.cs
@@ -0,0 +1,96 @@
+using System.IO;
+
+namespace CdgLib
+{
+
+ ///
+ ///
+ public class CdgFileIoStream
+ {
+ private Stream _cdgFile;
+
+ ///
+ ///
+ public CdgFileIoStream()
+ {
+ _cdgFile = null;
+ }
+
+ ///
+ /// Reads the specified buf.
+ ///
+ /// The buf.
+ /// The buf_size.
+ ///
+ public int Read(ref byte[] buf, int bufSize)
+ {
+ return _cdgFile.Read(buf, 0, bufSize);
+ }
+
+ ///
+ /// Writes the specified buf.
+ ///
+ /// The buf.
+ /// The buf_size.
+ ///
+ public int Write(ref byte[] buf, int bufSize)
+ {
+ _cdgFile.Write(buf, 0, bufSize);
+ return 1;
+ }
+
+ ///
+ /// Seeks the specified offset.
+ ///
+ /// The offset.
+ /// The whence.
+ ///
+ public int Seek(int offset, SeekOrigin whence)
+ {
+ return (int)_cdgFile.Seek(offset, whence);
+ }
+
+ ///
+ /// EOFs this instance.
+ ///
+ ///
+ public bool Eof()
+ {
+ return _cdgFile.Position >= _cdgFile.Length;
+ }
+
+ ///
+ /// Getsizes this instance.
+ ///
+ ///
+ public int Getsize()
+ {
+ return (int)_cdgFile.Length;
+ }
+
+ ///
+ /// Opens the specified filename.
+ ///
+ /// The filename.
+ ///
+ public bool Open(string filename)
+ {
+ Close();
+ _cdgFile = new FileStream(filename, FileMode.Open);
+ return _cdgFile != null;
+ }
+
+ ///
+ /// Closes this instance.
+ ///
+ public void Close()
+ {
+ if (_cdgFile != null)
+ {
+ _cdgFile.Close();
+ _cdgFile = null;
+ }
+ }
+ }
+}
+
diff --git a/CdgLib/CdgLib.csproj b/CdgLib/CdgLib.csproj
new file mode 100644
index 0000000..3103364
--- /dev/null
+++ b/CdgLib/CdgLib.csproj
@@ -0,0 +1,57 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {3203DFD2-DA5B-47B3-B009-18DD9C401FC3}
+ Library
+ Properties
+ CdgLib
+ CdgLib
+ v4.6
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CdgLib/GraphicUtil.cs b/CdgLib/GraphicUtil.cs
new file mode 100644
index 0000000..d64191f
--- /dev/null
+++ b/CdgLib/GraphicUtil.cs
@@ -0,0 +1,109 @@
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace CdgLib
+{
+ ///
+ ///
+ public class GraphicUtil
+ {
+ ///
+ /// Bitmaps to stream.
+ ///
+ /// The filename.
+ ///
+ public static Stream BitmapToStream(string filename)
+ {
+ var oldBmp = (Bitmap)Image.FromFile(filename);
+ var oldData = oldBmp.LockBits(new Rectangle(0, 0, oldBmp.Width, oldBmp.Height), ImageLockMode.WriteOnly,
+ PixelFormat.Format24bppRgb);
+ var length = oldData.Stride * oldBmp.Height;
+ var stream = new byte[length];
+ Marshal.Copy(oldData.Scan0, stream, 0, length);
+ oldBmp.UnlockBits(oldData);
+ oldBmp.Dispose();
+ return new MemoryStream(stream);
+ }
+
+
+ ///
+ /// Streams to bitmap.
+ ///
+ /// The stream.
+ /// The width.
+ /// The height.
+ ///
+ public static Bitmap StreamToBitmap(ref Stream stream, int width, int height)
+ {
+ //create a new bitmap
+ var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
+ var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
+ stream.Seek(0, SeekOrigin.Begin);
+ //copy the stream of pixel
+ for (var n = 0; n <= stream.Length - 1; n++)
+ {
+ var myByte = new byte[1];
+ stream.Read(myByte, 0, 1);
+ Marshal.WriteByte(bmpData.Scan0, n, myByte[0]);
+ }
+ bmp.UnlockBits(bmpData);
+ return bmp;
+ }
+
+ ///
+ /// Gets the CDG size bitmap.
+ ///
+ /// The filename.
+ ///
+ public static Bitmap GetCdgSizeBitmap(string filename)
+ {
+ var bm = new Bitmap(filename);
+ return ResizeBitmap(ref bm, CDGFile.CDG_FULL_WIDTH, CDGFile.CDG_FULL_HEIGHT);
+ }
+
+ ///
+ /// Resizes the bitmap.
+ ///
+ /// The bm.
+ /// The width.
+ /// The height.
+ ///
+ public static Bitmap ResizeBitmap(ref Bitmap bm, int width, int height)
+ {
+ var thumb = new Bitmap(width, height);
+ using (bm)
+ {
+ using (var g = Graphics.FromImage(thumb))
+ {
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ g.DrawImage(bm, new Rectangle(0, 0, width, height), new Rectangle(0, 0, bm.Width, bm.Height),
+ GraphicsUnit.Pixel);
+ }
+ }
+ return thumb;
+ }
+
+ ///
+ /// Merges the images with transparency.
+ ///
+ /// The pic1.
+ /// The pic2.
+ ///
+ public static Bitmap MergeImagesWithTransparency(Bitmap picture1, Bitmap picture2)
+ {
+ Bitmap mergedImage;
+ var bm = new Bitmap(picture1.Width, picture1.Height);
+ using (var gr = Graphics.FromImage(bm))
+ {
+ gr.DrawImage(picture1, 0, 0);
+ picture2.MakeTransparent(picture2.GetPixel(1, 1));
+ gr.DrawImage(picture2, 0, 0);
+ mergedImage = bm;
+ }
+ return mergedImage;
+ }
+ }
+}
diff --git a/CdgLib/Properties/AssemblyInfo.cs b/CdgLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0b89514
--- /dev/null
+++ b/CdgLib/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CdgLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CdgLib")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3203dfd2-da5b-47b3-b009-18dd9c401fc3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/KaraokeConverter/App.config b/KaraokeConverter/App.config
new file mode 100644
index 0000000..8324aa6
--- /dev/null
+++ b/KaraokeConverter/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KaraokeConverter/ExportAVI.cs b/KaraokeConverter/ExportAVI.cs
new file mode 100644
index 0000000..769f04e
--- /dev/null
+++ b/KaraokeConverter/ExportAVI.cs
@@ -0,0 +1,130 @@
+using AviFile;
+using CdgLib;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace KaraokeConverter
+{
+ public class ExportAVI
+ {
+
+
+ public void CDGtoAVI(string aviFileName, string cdgFileName, string mp3FileName, double frameRate, string backgroundFileName = "")
+ {
+ Bitmap backgroundBmp = null;
+ Bitmap mergedBMP = null;
+ VideoStream aviStream = null;
+ CDGFile myCDGFile = new CDGFile(cdgFileName);
+ myCDGFile.renderAtPosition(0);
+ Bitmap bitmap__1 = (Bitmap)myCDGFile.RgbImage;
+ if (!string.IsNullOrEmpty(backgroundFileName))
+ {
+ try
+ {
+ if (IsMovie(backgroundFileName))
+ backgroundBmp = MovieFrameExtractor.GetBitmap(0, backgroundFileName, CDGFile.CDG_FULL_WIDTH, CDGFile.CDG_FULL_HEIGHT);
+ if (IsGraphic(backgroundFileName))
+ backgroundBmp = GraphicUtil.GetCdgSizeBitmap(backgroundFileName);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ AviManager aviManager = new AviManager(aviFileName, false);
+ if (backgroundBmp != null)
+ {
+ mergedBMP = GraphicUtil.MergeImagesWithTransparency(backgroundBmp, bitmap__1);
+ aviStream = aviManager.AddVideoStream(true, frameRate, mergedBMP);
+ mergedBMP.Dispose();
+ if (IsMovie(backgroundFileName))
+ backgroundBmp.Dispose();
+ }
+ else {
+ aviStream = aviManager.AddVideoStream(true, frameRate, bitmap__1);
+ }
+
+ int count = 0;
+ double frameInterval = 1000 / frameRate;
+ long totalDuration = myCDGFile.getTotalDuration();
+ double position = 0;
+ while (position <= totalDuration)
+ {
+ count += 1;
+ position = count * frameInterval;
+ myCDGFile.renderAtPosition(Convert.ToInt64(position));
+ bitmap__1 = (Bitmap)myCDGFile.RgbImage;
+ if (!string.IsNullOrEmpty(backgroundFileName))
+ {
+ if (IsMovie(backgroundFileName))
+ backgroundBmp = MovieFrameExtractor.GetBitmap(position / 1000, backgroundFileName, CDGFile.CDG_FULL_WIDTH, CDGFile.CDG_FULL_HEIGHT);
+ }
+ if (backgroundBmp != null)
+ {
+ mergedBMP = GraphicUtil.MergeImagesWithTransparency(backgroundBmp, bitmap__1);
+ aviStream.AddFrame(mergedBMP);
+ mergedBMP.Dispose();
+ if (IsMovie(backgroundFileName))
+ backgroundBmp.Dispose();
+ }
+ else {
+ aviStream.AddFrame(bitmap__1);
+ }
+ bitmap__1.Dispose();
+ int percentageDone = (int)((position / totalDuration) * 100);
+ if (Status != null)
+ {
+ Status(percentageDone.ToString());
+ }
+ Application.DoEvents();
+ }
+ myCDGFile.Dispose();
+ aviManager.Close();
+ if (backgroundBmp != null)
+ backgroundBmp.Dispose();
+ AddMP3toAVI(aviFileName, mp3FileName);
+ }
+
+ public static void AddMP3toAVI(string aviFileName, string mp3FileName)
+ {
+ /*
+ string newAVIFileName = Regex.Replace(aviFileName, "\\.avi$", "MUX.avi", RegexOptions.IgnoreCase);
+ string cmdLineArgs = "-ovc copy -oac copy -audiofile \"" + mp3FileName + "\" -o \"" + newAVIFileName + "\" \"" + aviFileName + "\"";
+ using (Process myProcess = new Process()) {
+ string myCMD = "\"" + System.AppDomain.CurrentDomain.BaseDirectory() + "mencoder.exe \"" + cmdLineArgs;
+ myProcess.StartInfo.FileName = "\"" + System.AppDomain.CurrentDomain.BaseDirectory() + "mencoder.exe\"";
+ myProcess.StartInfo.Arguments = cmdLineArgs;
+ myProcess.StartInfo.UseShellExecute = false;
+ myProcess.StartInfo.CreateNoWindow = true;
+ myProcess.Start();
+ myProcess.PriorityClass = ProcessPriorityClass.Normal;
+ myProcess.WaitForExit();
+ }
+ if (File.Exists(newAVIFileName)) {
+ File.Delete(aviFileName);
+ File.Move(newAVIFileName, aviFileName);
+ }
+ */
+ }
+
+ public static bool IsMovie(string filename)
+ {
+ return Regex.IsMatch(filename, "^.+(\\.avi|\\.mpg|\\.wmv)$", RegexOptions.IgnoreCase);
+ }
+
+ public static bool IsGraphic(string filename)
+ {
+ return Regex.IsMatch(filename, "^.+(\\.jpg|\\.bmp|\\.png|\\.tif|\\.tiff|\\.gif|\\.wmf)$", RegexOptions.IgnoreCase);
+ }
+
+ public event StatusEventHandler Status;
+ public delegate void StatusEventHandler(string message);
+
+
+ }
+}
diff --git a/KaraokeConverter/Form1.Designer.cs b/KaraokeConverter/Form1.Designer.cs
new file mode 100644
index 0000000..a60be36
--- /dev/null
+++ b/KaraokeConverter/Form1.Designer.cs
@@ -0,0 +1,314 @@
+namespace KaraokeConverter
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.tbFileName = new System.Windows.Forms.TextBox();
+ this.btBrowseCDG = new System.Windows.Forms.Button();
+ this.OpenFileDialog1 = new System.Windows.Forms.OpenFileDialog();
+ this.Panel1 = new System.Windows.Forms.Panel();
+ this.GroupBox3 = new System.Windows.Forms.GroupBox();
+ this.chkBackGraph = new System.Windows.Forms.CheckBox();
+ this.tbBackGroundImg = new System.Windows.Forms.TextBox();
+ this.btBrowseImg = new System.Windows.Forms.Button();
+ this.chkBackGround = new System.Windows.Forms.CheckBox();
+ this.tbBackGroundAVI = new System.Windows.Forms.TextBox();
+ this.btBackGroundBrowse = new System.Windows.Forms.Button();
+ this.lbSaveAs = new System.Windows.Forms.Label();
+ this.tbAVIFile = new System.Windows.Forms.TextBox();
+ this.btOutputAVI = new System.Windows.Forms.Button();
+ this.tbFPS = new System.Windows.Forms.TextBox();
+ this.lbFPS = new System.Windows.Forms.Label();
+ this.btConvert = new System.Windows.Forms.Button();
+ this.GroupBox2 = new System.Windows.Forms.GroupBox();
+ this.GroupBox1 = new System.Windows.Forms.GroupBox();
+ this.pbAVI = new System.Windows.Forms.ProgressBar();
+ this.Panel2 = new System.Windows.Forms.Panel();
+ this.SaveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
+ this.Panel1.SuspendLayout();
+ this.GroupBox3.SuspendLayout();
+ this.GroupBox2.SuspendLayout();
+ this.GroupBox1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tbFileName
+ //
+ this.tbFileName.Location = new System.Drawing.Point(9, 13);
+ this.tbFileName.Name = "tbFileName";
+ this.tbFileName.ReadOnly = true;
+ this.tbFileName.Size = new System.Drawing.Size(475, 20);
+ this.tbFileName.TabIndex = 0;
+ //
+ // btBrowseCDG
+ //
+ this.btBrowseCDG.Location = new System.Drawing.Point(490, 11);
+ this.btBrowseCDG.Name = "btBrowseCDG";
+ this.btBrowseCDG.Size = new System.Drawing.Size(68, 23);
+ this.btBrowseCDG.TabIndex = 1;
+ this.btBrowseCDG.Text = "Browse...";
+ this.btBrowseCDG.UseVisualStyleBackColor = true;
+ this.btBrowseCDG.Click += new System.EventHandler(this.btBrowseCDG_Click);
+ //
+ // OpenFileDialog1
+ //
+ this.OpenFileDialog1.FileName = "OpenFileDialog1";
+ //
+ // Panel1
+ //
+ this.Panel1.Controls.Add(this.GroupBox3);
+ this.Panel1.Controls.Add(this.GroupBox2);
+ this.Panel1.Controls.Add(this.GroupBox1);
+ this.Panel1.Dock = System.Windows.Forms.DockStyle.Top;
+ this.Panel1.Location = new System.Drawing.Point(0, 0);
+ this.Panel1.Name = "Panel1";
+ this.Panel1.Size = new System.Drawing.Size(577, 255);
+ this.Panel1.TabIndex = 3;
+ //
+ // GroupBox3
+ //
+ this.GroupBox3.Controls.Add(this.chkBackGraph);
+ this.GroupBox3.Controls.Add(this.tbBackGroundImg);
+ this.GroupBox3.Controls.Add(this.btBrowseImg);
+ this.GroupBox3.Controls.Add(this.chkBackGround);
+ this.GroupBox3.Controls.Add(this.tbBackGroundAVI);
+ this.GroupBox3.Controls.Add(this.btBackGroundBrowse);
+ this.GroupBox3.Controls.Add(this.lbSaveAs);
+ this.GroupBox3.Controls.Add(this.tbAVIFile);
+ this.GroupBox3.Controls.Add(this.btOutputAVI);
+ this.GroupBox3.Controls.Add(this.tbFPS);
+ this.GroupBox3.Controls.Add(this.lbFPS);
+ this.GroupBox3.Controls.Add(this.btConvert);
+ this.GroupBox3.Location = new System.Drawing.Point(3, 53);
+ this.GroupBox3.Name = "GroupBox3";
+ this.GroupBox3.Size = new System.Drawing.Size(571, 145);
+ this.GroupBox3.TabIndex = 18;
+ this.GroupBox3.TabStop = false;
+ this.GroupBox3.Text = "AVI Settings";
+ //
+ // chkBackGraph
+ //
+ this.chkBackGraph.AutoSize = true;
+ this.chkBackGraph.Location = new System.Drawing.Point(7, 79);
+ this.chkBackGraph.Name = "chkBackGraph";
+ this.chkBackGraph.Size = new System.Drawing.Size(122, 17);
+ this.chkBackGraph.TabIndex = 23;
+ this.chkBackGraph.Text = "Background graphic";
+ this.chkBackGraph.UseVisualStyleBackColor = true;
+ this.chkBackGraph.CheckedChanged += new System.EventHandler(this.chkBackGraph_CheckedChanged);
+ //
+ // tbBackGroundImg
+ //
+ this.tbBackGroundImg.Enabled = false;
+ this.tbBackGroundImg.Location = new System.Drawing.Point(128, 77);
+ this.tbBackGroundImg.Name = "tbBackGroundImg";
+ this.tbBackGroundImg.Size = new System.Drawing.Size(356, 20);
+ this.tbBackGroundImg.TabIndex = 21;
+ //
+ // btBrowseImg
+ //
+ this.btBrowseImg.Enabled = false;
+ this.btBrowseImg.Location = new System.Drawing.Point(490, 75);
+ this.btBrowseImg.Name = "btBrowseImg";
+ this.btBrowseImg.Size = new System.Drawing.Size(75, 23);
+ this.btBrowseImg.TabIndex = 22;
+ this.btBrowseImg.Text = "Browse...";
+ this.btBrowseImg.UseVisualStyleBackColor = true;
+ this.btBrowseImg.Click += new System.EventHandler(this.btBrowseImg_Click);
+ //
+ // chkBackGround
+ //
+ this.chkBackGround.AutoSize = true;
+ this.chkBackGround.Location = new System.Drawing.Point(7, 51);
+ this.chkBackGround.Name = "chkBackGround";
+ this.chkBackGround.Size = new System.Drawing.Size(115, 17);
+ this.chkBackGround.TabIndex = 20;
+ this.chkBackGround.Text = "Background movie";
+ this.chkBackGround.UseVisualStyleBackColor = true;
+ this.chkBackGround.CheckedChanged += new System.EventHandler(this.chkBackGround_CheckedChanged);
+ //
+ // tbBackGroundAVI
+ //
+ this.tbBackGroundAVI.Enabled = false;
+ this.tbBackGroundAVI.Location = new System.Drawing.Point(128, 49);
+ this.tbBackGroundAVI.Name = "tbBackGroundAVI";
+ this.tbBackGroundAVI.Size = new System.Drawing.Size(356, 20);
+ this.tbBackGroundAVI.TabIndex = 17;
+ //
+ // btBackGroundBrowse
+ //
+ this.btBackGroundBrowse.Enabled = false;
+ this.btBackGroundBrowse.Location = new System.Drawing.Point(490, 47);
+ this.btBackGroundBrowse.Name = "btBackGroundBrowse";
+ this.btBackGroundBrowse.Size = new System.Drawing.Size(75, 23);
+ this.btBackGroundBrowse.TabIndex = 18;
+ this.btBackGroundBrowse.Text = "Browse...";
+ this.btBackGroundBrowse.UseVisualStyleBackColor = true;
+ this.btBackGroundBrowse.Click += new System.EventHandler(this.btBackGroundBrowse_Click);
+ //
+ // lbSaveAs
+ //
+ this.lbSaveAs.AutoSize = true;
+ this.lbSaveAs.Location = new System.Drawing.Point(76, 22);
+ this.lbSaveAs.Name = "lbSaveAs";
+ this.lbSaveAs.Size = new System.Drawing.Size(46, 13);
+ this.lbSaveAs.TabIndex = 16;
+ this.lbSaveAs.Text = "Save as";
+ //
+ // tbAVIFile
+ //
+ this.tbAVIFile.Location = new System.Drawing.Point(128, 19);
+ this.tbAVIFile.Name = "tbAVIFile";
+ this.tbAVIFile.Size = new System.Drawing.Size(356, 20);
+ this.tbAVIFile.TabIndex = 9;
+ //
+ // btOutputAVI
+ //
+ this.btOutputAVI.Location = new System.Drawing.Point(490, 17);
+ this.btOutputAVI.Name = "btOutputAVI";
+ this.btOutputAVI.Size = new System.Drawing.Size(75, 23);
+ this.btOutputAVI.TabIndex = 10;
+ this.btOutputAVI.Text = "Browse...";
+ this.btOutputAVI.UseVisualStyleBackColor = true;
+ this.btOutputAVI.Click += new System.EventHandler(this.btOutputAVI_Click_1);
+ //
+ // tbFPS
+ //
+ this.tbFPS.Location = new System.Drawing.Point(128, 108);
+ this.tbFPS.Name = "tbFPS";
+ this.tbFPS.Size = new System.Drawing.Size(67, 20);
+ this.tbFPS.TabIndex = 15;
+ this.tbFPS.Text = "15";
+ //
+ // lbFPS
+ //
+ this.lbFPS.AutoSize = true;
+ this.lbFPS.Location = new System.Drawing.Point(201, 111);
+ this.lbFPS.Name = "lbFPS";
+ this.lbFPS.Size = new System.Drawing.Size(94, 13);
+ this.lbFPS.TabIndex = 12;
+ this.lbFPS.Text = "frames per second";
+ //
+ // btConvert
+ //
+ this.btConvert.Location = new System.Drawing.Point(490, 106);
+ this.btConvert.Name = "btConvert";
+ this.btConvert.Size = new System.Drawing.Size(75, 23);
+ this.btConvert.TabIndex = 13;
+ this.btConvert.Text = "Create AVI";
+ this.btConvert.UseVisualStyleBackColor = true;
+ this.btConvert.Click += new System.EventHandler(this.btConvert_Click);
+ //
+ // GroupBox2
+ //
+ this.GroupBox2.Controls.Add(this.tbFileName);
+ this.GroupBox2.Controls.Add(this.btBrowseCDG);
+ this.GroupBox2.Location = new System.Drawing.Point(3, 3);
+ this.GroupBox2.Name = "GroupBox2";
+ this.GroupBox2.Size = new System.Drawing.Size(571, 40);
+ this.GroupBox2.TabIndex = 17;
+ this.GroupBox2.TabStop = false;
+ this.GroupBox2.Text = "MP3 + CDG File";
+ //
+ // GroupBox1
+ //
+ this.GroupBox1.Controls.Add(this.pbAVI);
+ this.GroupBox1.Location = new System.Drawing.Point(3, 204);
+ this.GroupBox1.Name = "GroupBox1";
+ this.GroupBox1.Size = new System.Drawing.Size(571, 48);
+ this.GroupBox1.TabIndex = 16;
+ this.GroupBox1.TabStop = false;
+ this.GroupBox1.Text = "Progress";
+ //
+ // pbAVI
+ //
+ this.pbAVI.Location = new System.Drawing.Point(7, 19);
+ this.pbAVI.Name = "pbAVI";
+ this.pbAVI.Size = new System.Drawing.Size(555, 23);
+ this.pbAVI.TabIndex = 14;
+ //
+ // Panel2
+ //
+ this.Panel2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.Panel2.Location = new System.Drawing.Point(0, 255);
+ this.Panel2.Name = "Panel2";
+ this.Panel2.Size = new System.Drawing.Size(577, 0);
+ this.Panel2.TabIndex = 4;
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(577, 253);
+ this.Controls.Add(this.Panel2);
+ this.Controls.Add(this.Panel1);
+ this.Name = "Form1";
+ this.Text = "MP3+CDG To Video Converter";
+ this.Panel1.ResumeLayout(false);
+ this.GroupBox3.ResumeLayout(false);
+ this.GroupBox3.PerformLayout();
+ this.GroupBox2.ResumeLayout(false);
+ this.GroupBox2.PerformLayout();
+ this.GroupBox1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+ private System.Windows.Forms.TextBox tbFileName;
+ private System.Windows.Forms.Button btBrowseCDG;
+
+ private System.Windows.Forms.OpenFileDialog OpenFileDialog1;
+ private System.Windows.Forms.Panel Panel1;
+ private System.Windows.Forms.Panel Panel2;
+ private System.Windows.Forms.GroupBox GroupBox2;
+ private System.Windows.Forms.GroupBox GroupBox1;
+ private System.Windows.Forms.ProgressBar pbAVI;
+ private System.Windows.Forms.TextBox tbFPS;
+
+ private System.Windows.Forms.Button btConvert;
+
+ private System.Windows.Forms.Label lbFPS;
+ private System.Windows.Forms.Button btOutputAVI;
+
+ private System.Windows.Forms.TextBox tbAVIFile;
+ private System.Windows.Forms.GroupBox GroupBox3;
+ private System.Windows.Forms.SaveFileDialog SaveFileDialog1;
+ private System.Windows.Forms.TextBox tbBackGroundAVI;
+ private System.Windows.Forms.Button btBackGroundBrowse;
+
+ private System.Windows.Forms.Label lbSaveAs;
+ private System.Windows.Forms.CheckBox chkBackGround;
+
+ private System.Windows.Forms.CheckBox chkBackGraph;
+
+ private System.Windows.Forms.TextBox tbBackGroundImg;
+ private System.Windows.Forms.Button btBrowseImg;
+
+
+ #endregion
+ }
+}
+
diff --git a/KaraokeConverter/Form1.cs b/KaraokeConverter/Form1.cs
new file mode 100644
index 0000000..1a82fb5
--- /dev/null
+++ b/KaraokeConverter/Form1.cs
@@ -0,0 +1,224 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using CdgLib;
+
+namespace KaraokeConverter
+{
+ public partial class Form1 : Form
+ {
+ public Form1()
+ {
+ InitializeComponent();
+ }
+ #region "Private Declarations"
+
+ private CDGFile mCDGFile;
+ private CdgFileIoStream mCDGStream;
+ private string mCDGFileName;
+ private string mMP3FileName;
+ private string mTempDir;
+ private ExportAVI withEventsField_mExportAVI;
+ private ExportAVI mExportAVI
+ {
+ get { return withEventsField_mExportAVI; }
+ set
+ {
+ if (withEventsField_mExportAVI != null)
+ {
+ withEventsField_mExportAVI.Status -= mExportAVI_Status;
+ }
+ withEventsField_mExportAVI = value;
+ if (withEventsField_mExportAVI != null)
+ {
+ withEventsField_mExportAVI.Status += mExportAVI_Status;
+ }
+ }
+
+ }
+ #endregion
+
+ #region "Control Events"
+
+ private void btOutputAVI_Click_1(System.Object sender, System.EventArgs e)
+ {
+ SelectOutputAVI();
+ }
+
+ private void btBackGroundBrowse_Click(System.Object sender, System.EventArgs e)
+ {
+ SelectBackGroundAVI();
+ }
+
+ private void btConvert_Click(System.Object sender, System.EventArgs e)
+ {
+ ConvertAVI();
+ }
+
+ private void tbFPS_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
+ {
+ /*
+ if ((Strings.Asc(e.KeyChar) >= Keys.D0 & Strings.Asc(e.KeyChar) <= Keys.D9) | Strings.Asc(e.KeyChar) == Keys.Back | e.KeyChar == ".") {
+ e.Handled = false;
+ } else {
+ e.Handled = true;
+ }
+ */
+ }
+
+ private void btBrowseCDG_Click(System.Object sender, System.EventArgs e)
+ {
+ OpenFileDialog1.Filter = "CDG or Zip Files (*.zip, *.cdg)|*.zip;*.cdg";
+ OpenFileDialog1.ShowDialog();
+ tbFileName.Text = OpenFileDialog1.FileName;
+ }
+
+ private void chkBackGraph_CheckedChanged(System.Object sender, System.EventArgs e)
+ {
+ if (chkBackGround.Checked && chkBackGraph.Checked)
+ {
+ chkBackGround.Checked = false;
+ }
+ ToggleCheckBox();
+ }
+
+ private void chkBackGround_CheckedChanged(System.Object sender, System.EventArgs e)
+ {
+ if (chkBackGraph.Checked && chkBackGround.Checked)
+ {
+ chkBackGraph.Checked = false;
+ }
+ ToggleCheckBox();
+ }
+
+ private void btBrowseImg_Click(System.Object sender, System.EventArgs e)
+ {
+ SelectBackGroundGraphic();
+ }
+
+ #endregion
+
+ #region "Events"
+
+ private void mExportAVI_Status(string message)
+ {
+ pbAVI.Value = (Convert.ToInt32(message));
+ }
+
+ #endregion
+
+ #region "Private Methods"
+
+ private void SelectOutputAVI()
+ {
+ SaveFileDialog1.Filter = "AVI Files (*.avi)|*.avi";
+ SaveFileDialog1.ShowDialog();
+ tbAVIFile.Text = SaveFileDialog1.FileName;
+ }
+
+ private void SelectBackGroundAVI()
+ {
+ OpenFileDialog1.Filter = "Movie Files (*.avi, *.mpg, *.wmv)|*.avi;*.mpg;*.wmv";
+ OpenFileDialog1.ShowDialog();
+ tbBackGroundAVI.Text = OpenFileDialog1.FileName;
+ }
+
+ private void SelectBackGroundGraphic()
+ {
+ OpenFileDialog1.Filter = "Graphic Files|*.jpg;*.bmp;*.png;*.tif;*.tiff;*.gif;*.wmf";
+ OpenFileDialog1.ShowDialog();
+ tbBackGroundImg.Text = OpenFileDialog1.FileName;
+ }
+
+ private void ConvertAVI()
+ {
+ try
+ {
+ PreProcessFiles();
+ if (string.IsNullOrEmpty(mCDGFileName) | string.IsNullOrEmpty(mMP3FileName))
+ {
+ MessageBox.Show("Cannot find a CDG and MP3 file to convert together.");
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ //Do nothing for now
+ }
+ mExportAVI = new ExportAVI();
+ pbAVI.Value = 0;
+ string backGroundFilename = "";
+ if (chkBackGraph.Checked)
+ backGroundFilename = tbBackGroundImg.Text;
+ if (chkBackGround.Checked)
+ backGroundFilename = tbBackGroundAVI.Text;
+ mExportAVI.CDGtoAVI(tbAVIFile.Text, mCDGFileName, mMP3FileName, Convert.ToDouble(tbFPS.Text), backGroundFilename);
+ pbAVI.Value = 0;
+ try
+ {
+ CleanUp();
+ }
+ catch (Exception ex)
+ {
+ //Do nothing for now
+ }
+ }
+
+ private void CleanUp()
+ {
+ if (!string.IsNullOrEmpty(mTempDir))
+ {
+ try
+ {
+ Directory.Delete(mTempDir, true);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ mTempDir = "";
+ }
+
+ private void PreProcessFiles()
+ {
+ /*
+ string myCDGFileName = "";
+ if (Regex.IsMatch(tbFileName.Text, "\\.zip$")) {
+ string myTempDir = Path.GetTempPath() + Path.GetRandomFileName();
+ Directory.CreateDirectory(myTempDir);
+ mTempDir = myTempDir;
+ myCDGFileName = Unzip.UnzipMP3GFiles(tbFileName.Text, myTempDir);
+ goto PairUpFiles;
+ } else if (Regex.IsMatch(tbFileName.Text, "\\.cdg$")) {
+ myCDGFileName = tbFileName.Text;
+ PairUpFiles:
+ string myMP3FileName = System.Text.RegularExpressions.Regex.Replace(myCDGFileName, "\\.cdg$", ".mp3");
+ if (File.Exists(myMP3FileName)) {
+ mMP3FileName = myMP3FileName;
+ mCDGFileName = myCDGFileName;
+ mTempDir = "";
+ }
+ }
+ */
+ }
+
+
+ private void ToggleCheckBox()
+ {
+ tbBackGroundAVI.Enabled = chkBackGround.Checked;
+ btBackGroundBrowse.Enabled = chkBackGround.Checked;
+ tbBackGroundImg.Enabled = chkBackGraph.Checked;
+ btBrowseImg.Enabled = chkBackGraph.Checked;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/KaraokeConverter/Form1.resx b/KaraokeConverter/Form1.resx
new file mode 100644
index 0000000..fdfe6a4
--- /dev/null
+++ b/KaraokeConverter/Form1.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 159, 17
+
+
\ No newline at end of file
diff --git a/KaraokeConverter/KaraokeConverter.csproj b/KaraokeConverter/KaraokeConverter.csproj
new file mode 100644
index 0000000..cd0a149
--- /dev/null
+++ b/KaraokeConverter/KaraokeConverter.csproj
@@ -0,0 +1,123 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {2821C26D-52D8-43D9-BEF4-7CE4DFA60776}
+ WinExe
+ Properties
+ KaraokeConverter
+ KaraokeConverter
+ v4.6
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ lib\AviFile.dll
+
+
+ False
+ lib\DirectShowLib-2005.dll
+
+
+ ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll
+ True
+
+
+ False
+ False
+ lib\Interop.DexterLib.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+
+
+
+
+ Form1.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {3203dfd2-da5b-47b3-b009-18dd9c401fc3}
+ CdgLib
+
+
+
+
+
\ No newline at end of file
diff --git a/KaraokeConverter/MovieFrameExtractor.cs b/KaraokeConverter/MovieFrameExtractor.cs
new file mode 100644
index 0000000..528926d
--- /dev/null
+++ b/KaraokeConverter/MovieFrameExtractor.cs
@@ -0,0 +1,33 @@
+using System.Drawing;
+using System.IO;
+namespace KaraokeConverter
+{
+ public class MovieFrameExtractor
+ {
+
+ public static Bitmap GetBitmap(double position, string movieFileName, int width, int height)
+ {
+
+ DexterLib.MediaDetClass det = new DexterLib.MediaDetClass();
+ det.Filename = movieFileName;
+ det.CurrentStream = 0;
+ double len = det.StreamLength;
+ if (position > len)
+ {
+ return null;
+ }
+
+ string myTempFile = System.IO.Path.GetTempFileName();
+ det.WriteBitmapBits(position, width, height, myTempFile);
+ Bitmap myBMP = null;
+ using (FileStream lStream = new FileStream(myTempFile, FileMode.Open, FileAccess.Read))
+ {
+ myBMP = (Bitmap)Image.FromStream(lStream);
+ }
+ System.IO.File.Delete(myTempFile);
+ return myBMP;
+
+ }
+
+ }
+}
diff --git a/KaraokeConverter/Program.cs b/KaraokeConverter/Program.cs
new file mode 100644
index 0000000..a227dba
--- /dev/null
+++ b/KaraokeConverter/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace KaraokeConverter
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Form1());
+ }
+ }
+}
diff --git a/KaraokeConverter/Properties/AssemblyInfo.cs b/KaraokeConverter/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..af6ad95
--- /dev/null
+++ b/KaraokeConverter/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("KaraokeConverter")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("KaraokeConverter")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("2821c26d-52d8-43d9-bef4-7ce4dfa60776")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/KaraokeConverter/Properties/Resources.Designer.cs b/KaraokeConverter/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..d065a06
--- /dev/null
+++ b/KaraokeConverter/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace KaraokeConverter.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KaraokeConverter.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/KaraokeConverter/Properties/Resources.resx b/KaraokeConverter/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/KaraokeConverter/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/KaraokeConverter/Properties/Settings.Designer.cs b/KaraokeConverter/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..86bce9f
--- /dev/null
+++ b/KaraokeConverter/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace KaraokeConverter.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/KaraokeConverter/Properties/Settings.settings b/KaraokeConverter/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/KaraokeConverter/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/KaraokeConverter/Unzip.cs b/KaraokeConverter/Unzip.cs
new file mode 100644
index 0000000..2507dc2
--- /dev/null
+++ b/KaraokeConverter/Unzip.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace KaraokeConverter
+{
+
+ public class Unzip
+ {
+
+ public static string UnzipMP3GFiles(string zipFilename, string outputPath)
+ {
+ string functionReturnValue = null;
+ functionReturnValue = "";
+ try
+ {
+ ICSharpCode.SharpZipLib.Zip.FastZip myZip = new ICSharpCode.SharpZipLib.Zip.FastZip();
+ myZip.ExtractZip(zipFilename, outputPath, "");
+ DirectoryInfo myDirInfo = new DirectoryInfo(outputPath);
+ FileInfo[] myFileInfo = myDirInfo.GetFiles("*.cdg", SearchOption.AllDirectories);
+ if (myFileInfo.Length > 0)
+ {
+ functionReturnValue = myFileInfo[0].FullName;
+ }
+ }
+ catch (Exception ex)
+ {
+ }
+ return functionReturnValue;
+ }
+
+ }
+}
diff --git a/KaraokeConverter/lib/AviFile.dll b/KaraokeConverter/lib/AviFile.dll
new file mode 100644
index 0000000..0019757
Binary files /dev/null and b/KaraokeConverter/lib/AviFile.dll differ
diff --git a/KaraokeConverter/lib/DirectShowLib-2005.dll b/KaraokeConverter/lib/DirectShowLib-2005.dll
new file mode 100644
index 0000000..ba11a16
Binary files /dev/null and b/KaraokeConverter/lib/DirectShowLib-2005.dll differ
diff --git a/KaraokeConverter/lib/Interop.DexterLib.dll b/KaraokeConverter/lib/Interop.DexterLib.dll
new file mode 100644
index 0000000..b5b2c9b
Binary files /dev/null and b/KaraokeConverter/lib/Interop.DexterLib.dll differ
diff --git a/KaraokeConverter/lib/mencoder.exe b/KaraokeConverter/lib/mencoder.exe
new file mode 100644
index 0000000..df8e2d8
Binary files /dev/null and b/KaraokeConverter/lib/mencoder.exe differ
diff --git a/KaraokeConverter/packages.config b/KaraokeConverter/packages.config
new file mode 100644
index 0000000..273ff53
--- /dev/null
+++ b/KaraokeConverter/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/KaraokePlayer.sln b/KaraokePlayer.sln
index c5cf7de..52544fa 100644
--- a/KaraokePlayer.sln
+++ b/KaraokePlayer.sln
@@ -5,6 +5,10 @@ VisualStudioVersion = 14.0.25008.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KaraokePlayer", "KaraokePlayer\KaraokePlayer.csproj", "{2CF318E2-04B5-40FC-9577-6DAC62B86FB2}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KaraokeConverter", "KaraokeConverter\KaraokeConverter.csproj", "{2821C26D-52D8-43D9-BEF4-7CE4DFA60776}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CdgLib", "CdgLib\CdgLib.csproj", "{3203DFD2-DA5B-47B3-B009-18DD9C401FC3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +19,14 @@ Global
{2CF318E2-04B5-40FC-9577-6DAC62B86FB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CF318E2-04B5-40FC-9577-6DAC62B86FB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CF318E2-04B5-40FC-9577-6DAC62B86FB2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2821C26D-52D8-43D9-BEF4-7CE4DFA60776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2821C26D-52D8-43D9-BEF4-7CE4DFA60776}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2821C26D-52D8-43D9-BEF4-7CE4DFA60776}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2821C26D-52D8-43D9-BEF4-7CE4DFA60776}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3203DFD2-DA5B-47B3-B009-18DD9C401FC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3203DFD2-DA5B-47B3-B009-18DD9C401FC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3203DFD2-DA5B-47B3-B009-18DD9C401FC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3203DFD2-DA5B-47B3-B009-18DD9C401FC3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/KaraokePlayer/CDGWindow.Designer.cs b/KaraokePlayer/CDGWindow.Designer.cs
new file mode 100644
index 0000000..2f3dff5
--- /dev/null
+++ b/KaraokePlayer/CDGWindow.Designer.cs
@@ -0,0 +1,69 @@
+namespace KaraokePlayer
+{
+ partial class CDGWindow
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CDGWindow));
+ this.PictureBox1 = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)this.PictureBox1).BeginInit();
+ this.SuspendLayout();
+ //
+ //PictureBox1
+ //
+ this.PictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
+ this.PictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.PictureBox1.Location = new System.Drawing.Point(0, 0);
+ this.PictureBox1.Name = "PictureBox1";
+ this.PictureBox1.Size = new System.Drawing.Size(300, 216);
+ this.PictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+ this.PictureBox1.TabIndex = 0;
+ this.PictureBox1.TabStop = false;
+ //
+ //CDGWindow
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6f, 13f);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.Black;
+ this.ClientSize = new System.Drawing.Size(300, 216);
+ this.Controls.Add(this.PictureBox1);
+ this.KeyPreview = true;
+ this.Name = "CDGWindow";
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Karaoke";
+ this.TopMost = true;
+ ((System.ComponentModel.ISupportInitialize)this.PictureBox1).EndInit();
+ this.ResumeLayout(false);
+
+ }
+ public System.Windows.Forms.PictureBox PictureBox1;
+
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/KaraokePlayer/CDGWindow.cs b/KaraokePlayer/CDGWindow.cs
new file mode 100644
index 0000000..4e19210
--- /dev/null
+++ b/KaraokePlayer/CDGWindow.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace KaraokePlayer
+{
+ public partial class CDGWindow : Form
+ {
+
+ private void CDGWindow_DoubleClick(object sender, System.EventArgs e)
+ {
+ AutoSizeWindow();
+ }
+
+ private void PictureBox1_DoubleClick(object sender, System.EventArgs e)
+ {
+ AutoSizeWindow();
+ }
+
+ private void AutoSizeWindow()
+ {
+ if (this.WindowState == FormWindowState.Normal)
+ {
+ this.WindowState = FormWindowState.Maximized;
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+ this.TopMost = true;
+ this.Refresh();
+ }
+ else {
+ this.WindowState = FormWindowState.Normal;
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
+ this.TopMost = false;
+ this.Refresh();
+ }
+ }
+
+ private void CDGWindow_SizeChanged(object sender, System.EventArgs e)
+ {
+ if (this.WindowState == FormWindowState.Maximized)
+ {
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+ this.TopMost = true;
+ }
+ else {
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
+ this.TopMost = false;
+ }
+ }
+ public CDGWindow()
+ {
+ SizeChanged += CDGWindow_SizeChanged;
+ DoubleClick += CDGWindow_DoubleClick;
+ InitializeComponent();
+ }
+
+ }
+}
diff --git a/KaraokePlayer/Form1.Designer.cs b/KaraokePlayer/Form1.Designer.cs
index dd0e1d3..5605616 100644
--- a/KaraokePlayer/Form1.Designer.cs
+++ b/KaraokePlayer/Form1.Designer.cs
@@ -29,9 +29,203 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
+ this.tbFileName = new System.Windows.Forms.TextBox();
+ this.btBrowse = new System.Windows.Forms.Button();
+ this.OpenFileDialog1 = new System.Windows.Forms.OpenFileDialog();
+ this.Timer1 = new System.Windows.Forms.Timer(this.components);
+ this.Panel1 = new System.Windows.Forms.Panel();
+ this.Label2 = new System.Windows.Forms.Label();
+ this.nudKey = new System.Windows.Forms.NumericUpDown();
+ this.Label1 = new System.Windows.Forms.Label();
+ this.ToolStrip1 = new System.Windows.Forms.ToolStrip();
+ this.tsbPlay = new System.Windows.Forms.ToolStripButton();
+ this.tsbStop = new System.Windows.Forms.ToolStripButton();
+ this.tsbPause = new System.Windows.Forms.ToolStripButton();
+ this.trbVolume = new System.Windows.Forms.TrackBar();
+ this.Panel2 = new System.Windows.Forms.Panel();
+ this.Panel1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudKey)).BeginInit();
+ this.ToolStrip1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.trbVolume)).BeginInit();
+ this.SuspendLayout();
+ //
+ // tbFileName
+ //
+ this.tbFileName.Location = new System.Drawing.Point(3, 5);
+ this.tbFileName.Name = "tbFileName";
+ this.tbFileName.ReadOnly = true;
+ this.tbFileName.Size = new System.Drawing.Size(309, 20);
+ this.tbFileName.TabIndex = 0;
+ //
+ // btBrowse
+ //
+ this.btBrowse.Location = new System.Drawing.Point(318, 6);
+ this.btBrowse.Name = "btBrowse";
+ this.btBrowse.Size = new System.Drawing.Size(75, 23);
+ this.btBrowse.TabIndex = 1;
+ this.btBrowse.Text = "Browse...";
+ this.btBrowse.UseVisualStyleBackColor = true;
+ this.btBrowse.Click += new System.EventHandler(this.Button1_Click);
+ //
+ // OpenFileDialog1
+ //
+ this.OpenFileDialog1.FileName = "OpenFileDialog1";
+ //
+ // Timer1
+ //
+ this.Timer1.Interval = 50;
+ //
+ // Panel1
+ //
+ this.Panel1.Controls.Add(this.Label2);
+ this.Panel1.Controls.Add(this.nudKey);
+ this.Panel1.Controls.Add(this.Label1);
+ this.Panel1.Controls.Add(this.ToolStrip1);
+ this.Panel1.Controls.Add(this.tbFileName);
+ this.Panel1.Controls.Add(this.btBrowse);
+ this.Panel1.Controls.Add(this.trbVolume);
+ this.Panel1.Dock = System.Windows.Forms.DockStyle.Top;
+ this.Panel1.Location = new System.Drawing.Point(0, 0);
+ this.Panel1.Name = "Panel1";
+ this.Panel1.Size = new System.Drawing.Size(397, 61);
+ this.Panel1.TabIndex = 3;
+ //
+ // Label2
+ //
+ this.Label2.AutoSize = true;
+ this.Label2.Location = new System.Drawing.Point(230, 37);
+ this.Label2.Name = "Label2";
+ this.Label2.Size = new System.Drawing.Size(25, 13);
+ this.Label2.TabIndex = 9;
+ this.Label2.Text = "Key";
+ //
+ // nudKey
+ //
+ this.nudKey.Location = new System.Drawing.Point(261, 35);
+ this.nudKey.Maximum = new decimal(new int[] {
+ 12,
+ 0,
+ 0,
+ 0});
+ this.nudKey.Minimum = new decimal(new int[] {
+ 12,
+ 0,
+ 0,
+ -2147483648});
+ this.nudKey.Name = "nudKey";
+ this.nudKey.Size = new System.Drawing.Size(50, 20);
+ this.nudKey.TabIndex = 8;
+ this.nudKey.ValueChanged += new System.EventHandler(this.nudKey_ValueChanged);
+ //
+ // Label1
+ //
+ this.Label1.AutoSize = true;
+ this.Label1.Location = new System.Drawing.Point(90, 35);
+ this.Label1.Name = "Label1";
+ this.Label1.Size = new System.Drawing.Size(42, 13);
+ this.Label1.TabIndex = 7;
+ this.Label1.Text = "Volume";
+ //
+ // ToolStrip1
+ //
+ this.ToolStrip1.Dock = System.Windows.Forms.DockStyle.None;
+ this.ToolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsbPlay,
+ this.tsbStop,
+ this.tsbPause});
+ this.ToolStrip1.Location = new System.Drawing.Point(3, 29);
+ this.ToolStrip1.Name = "ToolStrip1";
+ this.ToolStrip1.Size = new System.Drawing.Size(81, 25);
+ this.ToolStrip1.TabIndex = 2;
+ this.ToolStrip1.Text = "ToolStrip1";
+ //
+ // tsbPlay
+ //
+ this.tsbPlay.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbPlay.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbPlay.Name = "tsbPlay";
+ this.tsbPlay.Size = new System.Drawing.Size(23, 22);
+ this.tsbPlay.Text = "Play";
+ this.tsbPlay.Click += new System.EventHandler(this.tsbPlay_Click);
+ //
+ // tsbStop
+ //
+ this.tsbStop.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbStop.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbStop.Name = "tsbStop";
+ this.tsbStop.Size = new System.Drawing.Size(23, 22);
+ this.tsbStop.Text = "Stop";
+ this.tsbStop.Click += new System.EventHandler(this.tsbStop_Click);
+ //
+ // tsbPause
+ //
+ this.tsbPause.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbPause.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbPause.Name = "tsbPause";
+ this.tsbPause.Size = new System.Drawing.Size(23, 22);
+ this.tsbPause.Text = "Pause";
+ this.tsbPause.Click += new System.EventHandler(this.tsbPause_Click);
+ //
+ // trbVolume
+ //
+ this.trbVolume.Location = new System.Drawing.Point(131, 34);
+ this.trbVolume.Maximum = 100;
+ this.trbVolume.Name = "trbVolume";
+ this.trbVolume.Size = new System.Drawing.Size(101, 45);
+ this.trbVolume.TabIndex = 6;
+ this.trbVolume.TickFrequency = 5;
+ this.trbVolume.TickStyle = System.Windows.Forms.TickStyle.None;
+ this.trbVolume.Value = 100;
+ this.trbVolume.Scroll += new System.EventHandler(this.TrackBar1_Scroll);
+ //
+ // Panel2
+ //
+ this.Panel2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.Panel2.Location = new System.Drawing.Point(0, 61);
+ this.Panel2.Name = "Panel2";
+ this.Panel2.Size = new System.Drawing.Size(397, 0);
+ this.Panel2.TabIndex = 4;
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.Text = "Form1";
+ this.ClientSize = new System.Drawing.Size(397, 61);
+ this.Controls.Add(this.Panel2);
+ this.Controls.Add(this.Panel1);
+ this.Name = "Form1";
+ this.Text = "MP3+CDG Player";
+ this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed);
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.Panel1.ResumeLayout(false);
+ this.Panel1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudKey)).EndInit();
+ this.ToolStrip1.ResumeLayout(false);
+ this.ToolStrip1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.trbVolume)).EndInit();
+ this.ResumeLayout(false);
+
}
+ private System.Windows.Forms.TextBox tbFileName;
+ private System.Windows.Forms.Button btBrowse;
+ private System.Windows.Forms.OpenFileDialog OpenFileDialog1;
+ private System.Windows.Forms.Timer Timer1;
+ private System.Windows.Forms.Panel Panel1;
+ private System.Windows.Forms.Panel Panel2;
+ private System.Windows.Forms.ToolStrip ToolStrip1;
+ private System.Windows.Forms.ToolStripButton tsbPlay;
+
+ private System.Windows.Forms.ToolStripButton tsbStop;
+
+ private System.Windows.Forms.ToolStripButton tsbPause;
+ private System.Windows.Forms.Label Label1;
+
+ private System.Windows.Forms.TrackBar trbVolume;
+
+ private System.Windows.Forms.Label Label2;
+
+ private System.Windows.Forms.NumericUpDown nudKey;
+
#endregion
}
diff --git a/KaraokePlayer/Form1.cs b/KaraokePlayer/Form1.cs
index 3264230..1e9a57f 100644
--- a/KaraokePlayer/Form1.cs
+++ b/KaraokePlayer/Form1.cs
@@ -7,14 +7,312 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
+using CdgLib;
+using Un4seen.Bass;
+using System.Text.RegularExpressions;
+using System.IO;
namespace KaraokePlayer
{
public partial class Form1 : Form
- {
+{
public Form1()
{
InitializeComponent();
}
- }
+
+ #region "Private Declarations"
+
+ private CDGFile mCDGFile;
+ private CdgFileIoStream mCDGStream;
+ private int mSemitones = 0;
+ private bool mPaused;
+ private long mFrameCount = 0;
+ private bool mStop;
+ private string mCDGFileName;
+ private string mMP3FileName;
+ private string mTempDir;
+ private int mMP3Stream;
+ private CDGWindow withEventsField_mCDGWindow = new CDGWindow();
+ private CDGWindow mCDGWindow {
+ get { return withEventsField_mCDGWindow; }
+ set {
+ if (withEventsField_mCDGWindow != null) {
+ withEventsField_mCDGWindow.FormClosing -= mCDGWindow_FormClosing;
+ }
+ withEventsField_mCDGWindow = value;
+ if (withEventsField_mCDGWindow != null) {
+ withEventsField_mCDGWindow.FormClosing += mCDGWindow_FormClosing;
+ }
+ }
+ }
+
+ private bool mBassInitalized = false;
+ #endregion
+
+ #region "Control Events"
+
+ private void Form1_Load(object sender, System.EventArgs e)
+ {
+ //Add registration key here if you have a license
+ //BassNet.Registration("email@domain.com", "0000000000000000")
+ try {
+ Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle);
+ mBassInitalized = true;
+ } catch (Exception ex) {
+ MessageBox.Show("Unable to initialize the audio playback system.");
+ }
+ }
+
+ private void Button1_Click(System.Object sender, System.EventArgs e)
+ {
+ BrowseCDGZip();
+ }
+
+ private void Form1_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
+ {
+ StopPlayback();
+ }
+
+ private void tsbPlay_Click(System.Object sender, System.EventArgs e)
+ {
+ Play();
+ }
+
+ private void tsbStop_Click(System.Object sender, System.EventArgs e)
+ {
+ try {
+ StopPlayback();
+ } catch (Exception ex) {
+ //Do nothing for now
+ }
+ }
+
+ private void tsbPause_Click(System.Object sender, System.EventArgs e)
+ {
+ Pause();
+ }
+
+ private void TrackBar1_Scroll(System.Object sender, System.EventArgs e)
+ {
+ AdjustVolume();
+ }
+
+ private void nudKey_ValueChanged(System.Object sender, System.EventArgs e)
+ {
+ AdjustPitch();
+ }
+
+ private void mCDGWindow_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
+ {
+ StopPlayback();
+ mCDGWindow.Hide();
+ e.Cancel = true;
+ }
+
+ #endregion
+
+ #region "CDG + MP3 Playback Operations"
+
+ private void Pause()
+ {
+ mPaused = !mPaused;
+ if (mMP3Stream != 0) {
+ if (Bass.BASS_ChannelIsActive(mMP3Stream) != BASSActive.BASS_ACTIVE_PLAYING) {
+ Bass.BASS_ChannelPlay(mMP3Stream, false);
+ tsbPause.Text = "Pause";
+ } else {
+ Bass.BASS_ChannelPause(mMP3Stream);
+ tsbPause.Text = "Resume";
+ }
+ }
+ }
+
+ private void PlayMP3Bass(string mp3FileName)
+ {
+ if (mBassInitalized || Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle)) {
+ mMP3Stream = 0;
+ mMP3Stream = Bass.BASS_StreamCreateFile(mp3FileName, 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
+ mMP3Stream = Un4seen.Bass.AddOn.Fx.BassFx.BASS_FX_TempoCreate(mMP3Stream, BASSFlag.BASS_FX_FREESOURCE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_SAMPLE_LOOP);
+ if (mMP3Stream != 0) {
+ AdjustPitch();
+ AdjustVolume();
+ ShowCDGWindow();
+ Bass.BASS_ChannelPlay(mMP3Stream, false);
+ } else {
+ throw new Exception(string.Format("Stream error: {0}", Bass.BASS_ErrorGetCode()));
+ }
+ }
+ }
+
+ private void StopPlaybackBass()
+ {
+ Bass.BASS_Stop();
+ Bass.BASS_StreamFree(mMP3Stream);
+ Bass.BASS_Free();
+ mMP3Stream = 0;
+ mBassInitalized = false;
+ }
+
+ private void StopPlayback()
+ {
+ mStop = true;
+ HideCDGWindow();
+ StopPlaybackBass();
+ mCDGFile.Dispose();
+ CleanUp();
+ }
+
+ private void PausePlayback()
+ {
+ Bass.BASS_Pause();
+ }
+
+ private void ResumePlayback()
+ {
+ Bass.BASS_Pause();
+ }
+
+ private void Play()
+ {
+ try {
+ if (mMP3Stream != 0 && Bass.BASS_ChannelIsActive(mMP3Stream) == BASSActive.BASS_ACTIVE_PLAYING) {
+ StopPlayback();
+ }
+ PreProcessFiles();
+ if (string.IsNullOrEmpty(mCDGFileName) | string.IsNullOrEmpty(mMP3FileName)) {
+ MessageBox.Show("Cannot find a CDG and MP3 file to play together.");
+ StopPlayback();
+ return;
+ }
+ mPaused = false;
+ mStop = false;
+ mFrameCount = 0;
+ mCDGFile = new CDGFile(mCDGFileName);
+ long cdgLength = mCDGFile.getTotalDuration();
+ PlayMP3Bass(mMP3FileName);
+ DateTime startTime = DateTime.Now;
+ var endTime = startTime.AddMilliseconds(mCDGFile.getTotalDuration());
+ long millisecondsRemaining = cdgLength;
+ while (millisecondsRemaining > 0) {
+ if (mStop) {
+ break; // TODO: might not be correct. Was : Exit While
+ }
+ millisecondsRemaining = (long)endTime.Subtract(DateTime.Now).TotalMilliseconds;
+ long pos = cdgLength - millisecondsRemaining;
+ while (mPaused) {
+ endTime = DateTime.Now.AddMilliseconds(millisecondsRemaining);
+ Application.DoEvents();
+ }
+ mCDGFile.renderAtPosition(pos);
+ mFrameCount += 1;
+ mCDGWindow.PictureBox1.Image = mCDGFile.RgbImage;
+ mCDGWindow.PictureBox1.BackColor = ((Bitmap)mCDGFile.RgbImage).GetPixel(1, 1);
+ mCDGWindow.PictureBox1.Refresh();
+
+ Application.DoEvents();
+ }
+ StopPlayback();
+ } catch (Exception ex) {
+ }
+ }
+
+ private void AdjustPitch()
+ {
+ if (mMP3Stream != 0) {
+ Bass.BASS_ChannelSetAttribute(mMP3Stream, BASSAttribute.BASS_ATTRIB_TEMPO_PITCH, (float)nudKey.Value);
+ }
+ }
+
+ private void AdjustVolume()
+ {
+ if (mMP3Stream != 0) {
+ Bass.BASS_ChannelSetAttribute(mMP3Stream, BASSAttribute.BASS_ATTRIB_VOL, trbVolume.Value == 0 ? 0 : (trbVolume.Value / 100));
+ }
+ }
+
+ #endregion
+
+ #region "File Access"
+
+ private void BrowseCDGZip()
+ {
+ OpenFileDialog1.Filter = "CDG or Zip Files (*.zip, *.cdg)|*.zip;*.cdg";
+ OpenFileDialog1.ShowDialog();
+ tbFileName.Text = OpenFileDialog1.FileName;
+ }
+
+ private void PreProcessFiles()
+ {
+
+ string myCDGFileName = "";
+ if (Regex.IsMatch(tbFileName.Text, "\\.zip$")) {
+ string myTempDir = Path.GetTempPath() + Path.GetRandomFileName();
+ Directory.CreateDirectory(myTempDir);
+ mTempDir = myTempDir;
+ myCDGFileName = Unzip.UnzipMP3GFiles(tbFileName.Text, myTempDir);
+
+ } else if (Regex.IsMatch(tbFileName.Text, "\\.cdg$")) {
+ myCDGFileName = tbFileName.Text;
+ PairUpFiles:
+ string myMP3FileName = System.Text.RegularExpressions.Regex.Replace(myCDGFileName, "\\.cdg$", ".mp3");
+ if (File.Exists(myMP3FileName)) {
+ mMP3FileName = myMP3FileName;
+ mCDGFileName = myCDGFileName;
+ mTempDir = "";
+ }
+ }
+
+ }
+
+ private void CleanUp()
+ {
+ if (!string.IsNullOrEmpty(mTempDir)) {
+ try {
+ Directory.Delete(mTempDir, true);
+ } catch (Exception ex) {
+ }
+ }
+ mTempDir = "";
+ }
+
+ #endregion
+
+ #region "CDG Graphics Window"
+
+ private void ShowCDGWindow()
+ {
+ mCDGWindow.Show();
+ }
+
+ private void HideCDGWindow()
+ {
+ mCDGWindow.PictureBox1.Image = null;
+ mCDGWindow.Hide();
+ }
+
+ #endregion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
}
diff --git a/KaraokePlayer/Form1.resx b/KaraokePlayer/Form1.resx
new file mode 100644
index 0000000..c8cba2e
--- /dev/null
+++ b/KaraokePlayer/Form1.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 159, 17
+
+
+ 248, 17
+
+
\ No newline at end of file
diff --git a/KaraokePlayer/KaraokePlayer.csproj b/KaraokePlayer/KaraokePlayer.csproj
index 7f0af26..35af766 100644
--- a/KaraokePlayer/KaraokePlayer.csproj
+++ b/KaraokePlayer/KaraokePlayer.csproj
@@ -33,6 +33,13 @@
4
+
+ lib\Bass.Net.dll
+
+
+ ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll
+ True
+
@@ -46,6 +53,12 @@
+
+ Form
+
+
+ CDGWindow.cs
+
Form
@@ -54,6 +67,10 @@
+
+
+ Form1.cs
+
ResXFileCodeGenerator
Resources.Designer.cs
@@ -63,6 +80,7 @@
True
Resources.resx
+
SettingsSingleFileGenerator
Settings.Designer.cs
@@ -76,7 +94,22 @@
+
+
+
+
+
+
+
+ {3203dfd2-da5b-47b3-b009-18dd9c401fc3}
+ CdgLib
+
+
+
+ copy "$(ProjectDir)lib\bass.dll" "$(TargetDir)"
+copy "$(ProjectDir)lib\bass_fx.dll" "$(TargetDir)"
+