+++ /dev/null
-using System;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-using System.Runtime.InteropServices;\r
-using System.IO;\r
-using System.Diagnostics;\r
-using System.Threading;\r
-\r
-\r
-namespace FDK\r
-{\r
- public unsafe class Cxa : SoundDecoder //, IDisposable\r
- {\r
- static byte[] FOURCC = Encoding.ASCII.GetBytes( "1DWK" ); // KWD1 の little endian\r
-\r
- #region [ XA用構造体の宣言 ]\r
- [StructLayout(LayoutKind.Sequential)]\r
- public struct XASTREAMHEADER {\r
- public byte* pSrc;\r
- public uint nSrcLen;\r
- public uint nSrcUsed;\r
- public byte* pDst;\r
- public uint nDstLen;\r
- public uint nDstUsed;\r
- }\r
-\r
- [StructLayout( LayoutKind.Sequential )]\r
- public struct XAHEADER\r
- {\r
- public uint id;\r
- public uint nDataLen;\r
- public uint nSamples;\r
- public ushort nSamplesPerSec;\r
- public byte nBits;\r
- public byte nChannels;\r
- public uint nLoopPtr;\r
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]\r
- public short[] befL;\r
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]\r
- public short[] befR;\r
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]\r
- public byte[] pad;\r
- }\r
- #endregion\r
-\r
- #region [ xadec.dllとのリンク ]\r
- [DllImport( "xadec.dll", EntryPoint = "xaDecodeOpen", CallingConvention = CallingConvention.Cdecl )]\r
- public extern static IntPtr xaDecodeOpen( ref XAHEADER pxah, out FDK.CWin32.WAVEFORMATEX pwfx );\r
- [DllImport( "xadec.dll", EntryPoint = "xaDecodeClose", CallingConvention = CallingConvention.Cdecl )]\r
- public extern static bool xaDecodeClose( IntPtr hxas );\r
- [DllImport( "xadec.dll", EntryPoint = "xaDecodeSize", CallingConvention = CallingConvention.Cdecl )]\r
- public extern static bool xaDecodeSize( IntPtr hxas, uint slen, out uint pdlen );\r
- [DllImport( "xadec.dll", EntryPoint = "xaDecodeConvert", CallingConvention = CallingConvention.Cdecl )]\r
- public extern static bool xaDecodeConvert( IntPtr hxas, ref XASTREAMHEADER psh );\r
- #endregion\r
-\r
- public XAHEADER xaheader;\r
- public XASTREAMHEADER xastreamheader;\r
- public CWin32.WAVEFORMATEX waveformatex;\r
-\r
- private string filename;\r
- private byte[] srcBuf = null;\r
- private int nHandle = -1;\r
-\r
- public override int Open( string filename )\r
- {\r
- this.filename = filename;\r
-\r
- #region [ XAヘッダと、XAデータの読み出し ]\r
- xaheader = new XAHEADER();\r
- using ( FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) ) // FileShare を付けとかないと、Close() 後もロックがかかる??\r
- {\r
- using ( BinaryReader br = new BinaryReader( fs ) )\r
- {\r
- xaheader.id = br.ReadUInt32();\r
- xaheader.nDataLen = br.ReadUInt32();\r
- xaheader.nSamples = br.ReadUInt32();\r
- xaheader.nSamplesPerSec = br.ReadUInt16();\r
- xaheader.nBits = br.ReadByte();\r
- xaheader.nChannels = br.ReadByte();\r
- xaheader.nLoopPtr = br.ReadUInt32();\r
-\r
- xaheader.befL = new short[ 2 ];\r
- xaheader.befR = new short[ 2 ];\r
- xaheader.pad = new byte[ 4 ];\r
-\r
- xaheader.befL[ 0 ] = br.ReadInt16();\r
- xaheader.befL[ 1 ] = br.ReadInt16();\r
- xaheader.befR[ 0 ] = br.ReadInt16();\r
- xaheader.befR[ 1 ] = br.ReadInt16();\r
- xaheader.pad = br.ReadBytes( 4 );\r
-\r
- srcBuf = new byte[ xaheader.nDataLen ];\r
- srcBuf = br.ReadBytes( (int) xaheader.nDataLen );\r
- }\r
- }\r
- //string xaid = Encoding.ASCII.GetString( xah.id );\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**XAHEADER**" );\r
- //Debug.WriteLine( "id= " + xaheader.id.ToString( "X8" ) );\r
- //Debug.WriteLine( "nDataLen= " + xaheader.nDataLen.ToString( "X8" ) );\r
- //Debug.WriteLine( "nSamples= " + xaheader.nSamples.ToString( "X8" ) );\r
- //Debug.WriteLine( "nSamplesPerSec= " + xaheader.nSamplesPerSec.ToString( "X4" ) );\r
- //Debug.WriteLine( "nBits= " + xaheader.nBits.ToString( "X2" ) );\r
- //Debug.WriteLine( "nChannels= " + xaheader.nChannels.ToString( "X2" ) );\r
- //Debug.WriteLine( "nLoopPtr= " + xaheader.nLoopPtr.ToString( "X8" ) );\r
- //Debug.WriteLine( "befL[0]= " + xaheader.befL[ 0 ].ToString( "X4" ) );\r
- //Debug.WriteLine( "befL[1]= " + xaheader.befL[ 1 ].ToString( "X4" ) );\r
- //Debug.WriteLine( "befR[0]= " + xaheader.befR[ 0 ].ToString( "X4" ) );\r
- //Debug.WriteLine( "befR[1]= " + xaheader.befR[ 1 ].ToString( "X4" ) );\r
- #endregion\r
- #endregion\r
-\r
- IntPtr hxas;\r
-\r
- #region [ WAVEFORMEX情報の取得 ]\r
- waveformatex = new CWin32.WAVEFORMATEX();\r
- hxas = xaDecodeOpen( ref xaheader, out waveformatex );\r
- if ( hxas == null )\r
- {\r
- Trace.TraceError( "Error: xa: Open(): xaDecodeOpen(): " + Path.GetFileName( filename ) );\r
- return -1;\r
- }\r
-\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**WAVEFORMATEX**" );\r
- //Debug.WriteLine( "wFormatTag= " + waveformatex.wFormatTag.ToString( "X4" ) );\r
- //Debug.WriteLine( "nChannels = " + waveformatex.nChannels.ToString( "X4" ) );\r
- //Debug.WriteLine( "nSamplesPerSec= " + waveformatex.nSamplesPerSec.ToString( "X8" ) );\r
- //Debug.WriteLine( "nAvgBytesPerSec= " + waveformatex.nAvgBytesPerSec.ToString( "X8" ) );\r
- //Debug.WriteLine( "nBlockAlign= " + waveformatex.nBlockAlign.ToString( "X4" ) );\r
- //Debug.WriteLine( "wBitsPerSample= " + waveformatex.wBitsPerSample.ToString( "X4" ) );\r
- //Debug.WriteLine( "cbSize= " + waveformatex.cbSize.ToString( "X4" ) );\r
- #endregion\r
- #endregion\r
-\r
- this.nHandle = (int) hxas;\r
- return (int) hxas;\r
- }\r
- public override int GetFormat( int nHandle, ref CWin32.WAVEFORMATEX wfx )\r
- {\r
- #region [ WAVEFORMATEX構造体の手動コピー ]\r
- wfx.nAvgBytesPerSec = waveformatex.nAvgBytesPerSec;\r
- wfx.wBitsPerSample = waveformatex.wBitsPerSample;\r
- wfx.nBlockAlign = waveformatex.nBlockAlign;\r
- wfx.nChannels = waveformatex.nChannels;\r
- wfx.wFormatTag = waveformatex.wFormatTag;\r
- wfx.nSamplesPerSec = waveformatex.nSamplesPerSec;\r
-\r
- return 0;\r
- #endregion\r
- }\r
- public override uint GetTotalPCMSize( int nHandle )\r
- {\r
- #region [ データ長の取得 ]\r
- uint dlen;\r
- xaDecodeSize( (IntPtr) nHandle, xaheader.nDataLen, out dlen );\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**INTERNAL VALUE**" );\r
- //Debug.WriteLine( "dlen= " + dlen );\r
- #endregion\r
- #endregion\r
-\r
- return dlen;\r
- }\r
- public override int Seek( int nHandle, uint dwPosition )\r
- {\r
- return 0;\r
- }\r
- public override int Decode( int nHandle, IntPtr pDest, uint szDestSize, int bLoop )\r
- {\r
- #region [ xaデータのデコード ]\r
- xastreamheader = new XASTREAMHEADER();\r
- unsafe\r
- {\r
- fixed ( byte* pXaBuf = srcBuf )\r
- {\r
- byte* pWavBuf = (byte*) pDest;\r
-\r
- xastreamheader.pSrc = pXaBuf;\r
- xastreamheader.nSrcLen = xaheader.nDataLen;\r
- xastreamheader.nSrcUsed = 0;\r
- xastreamheader.pDst = pWavBuf;\r
- xastreamheader.nDstLen = szDestSize;\r
- xastreamheader.nDstUsed = 0;\r
- if ( !xaDecodeConvert( (IntPtr) nHandle, ref xastreamheader ) )\r
- {\r
- Trace.TraceError( "Error: xaDecodeConvert(): " + Path.GetFileName( filename ) );\r
- return -1;\r
- }\r
- }\r
- }\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**XASTREAMHEADER**" );\r
- //Debug.WriteLine( "nSrcLen= " + xastreamheader.nSrcLen );\r
- //Debug.WriteLine( "nSrcUsed= " + xastreamheader.nSrcUsed );\r
- //Debug.WriteLine( "nDstLen= " + xastreamheader.nDstLen );\r
- //Debug.WriteLine( "nDstUsed= " + xastreamheader.nDstUsed );\r
- #endregion\r
- #endregion\r
-\r
- return 0;\r
- }\r
- public override void Close( int nHandle )\r
- {\r
- #region [ xaファイルのクローズ ]\r
- if ( !xaDecodeClose( (IntPtr) nHandle ) )\r
- {\r
- Trace.TraceError( "Error: xaDecodeClose(): " + Path.GetFileName( filename ) );\r
- }\r
- srcBuf = null;\r
- #endregion\r
- }\r
-\r
-\r
-\r
- //#region [ IDisposable 実装 ]\r
- ////-----------------\r
- //private bool bDispose完了済み = false;\r
- //public void Dispose()\r
- //{\r
- // if ( !this.bDispose完了済み )\r
- // {\r
- // if ( srcBuf != null )\r
- // {\r
- // srcBuf = null;\r
- // }\r
- // if ( dstBuf != null )\r
- // {\r
- // dstBuf = null;\r
- // }\r
-\r
- // if ( this.nHandle >= 0 )\r
- // {\r
- // this.Close( this.nHandle );\r
- // this.nHandle = -1;\r
- // }\r
- // this.bDispose完了済み = true;\r
- // }\r
- //}\r
- ////-----------------\r
- //#endregion\r
-\r
-#if false\r
- /// <summary>\r
- /// xaファイルを読み込んで、wavにdecodeする\r
- /// </summary>\r
- /// <param name="filename">xaファイル名</param>\r
- /// <param name="wavBuf">wavファイルが格納されるバッファ</param>\r
- /// <returns></returns>\r
- public bool Decode( string filename, out byte[] wavBuf )\r
- {\r
- // Debug.WriteLine( "xa: Decode: " + Path.GetFileName( filename ) );\r
-\r
- #region [ XAヘッダと、XAデータの読み出し ]\r
- xaheader = new XAHEADER();\r
- byte[] xaBuf;\r
- using ( FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) ) // FileShare を付けとかないと、Close() 後もロックがかかる??\r
- {\r
- using ( BinaryReader br = new BinaryReader( fs ) )\r
- {\r
- xaheader.id = br.ReadUInt32();\r
- xaheader.nDataLen = br.ReadUInt32();\r
- xaheader.nSamples = br.ReadUInt32();\r
- xaheader.nSamplesPerSec = br.ReadUInt16();\r
- xaheader.nBits = br.ReadByte();\r
- xaheader.nChannels = br.ReadByte();\r
- xaheader.nLoopPtr = br.ReadUInt32();\r
-\r
- xaheader.befL = new short[ 2 ];\r
- xaheader.befR = new short[ 2 ];\r
- xaheader.pad = new byte[ 4 ];\r
-\r
- xaheader.befL[ 0 ] = br.ReadInt16();\r
- xaheader.befL[ 1 ] = br.ReadInt16();\r
- xaheader.befR[ 0 ] = br.ReadInt16();\r
- xaheader.befR[ 1 ] = br.ReadInt16();\r
- xaheader.pad = br.ReadBytes( 4 );\r
-\r
- xaBuf = new byte[ xaheader.nDataLen ];\r
- xaBuf = br.ReadBytes( (int) xaheader.nDataLen );\r
- }\r
- }\r
- //string xaid = Encoding.ASCII.GetString( xah.id );\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**XAHEADER**" );\r
- //Debug.WriteLine( "id= " + xaheader.id.ToString( "X8" ) );\r
- //Debug.WriteLine( "nDataLen= " + xaheader.nDataLen.ToString( "X8" ) );\r
- //Debug.WriteLine( "nSamples= " + xaheader.nSamples.ToString( "X8" ) );\r
- //Debug.WriteLine( "nSamplesPerSec= " + xaheader.nSamplesPerSec.ToString( "X4" ) );\r
- //Debug.WriteLine( "nBits= " + xaheader.nBits.ToString( "X2" ) );\r
- //Debug.WriteLine( "nChannels= " + xaheader.nChannels.ToString( "X2" ) );\r
- //Debug.WriteLine( "nLoopPtr= " + xaheader.nLoopPtr.ToString( "X8" ) );\r
- //Debug.WriteLine( "befL[0]= " + xaheader.befL[ 0 ].ToString( "X4" ) );\r
- //Debug.WriteLine( "befL[1]= " + xaheader.befL[ 1 ].ToString( "X4" ) );\r
- //Debug.WriteLine( "befR[0]= " + xaheader.befR[ 0 ].ToString( "X4" ) );\r
- //Debug.WriteLine( "befR[1]= " + xaheader.befR[ 1 ].ToString( "X4" ) );\r
- #endregion\r
- #endregion\r
-\r
- object lockobj = new object();\r
- lock ( lockobj ) // スレッドセーフじゃないかも知れないので、念のため\r
- {\r
- #region [ WAVEFORMEX情報の取得 ]\r
- waveformatex = new CWin32.WAVEFORMATEX();\r
- IntPtr hxas = xaDecodeOpen( ref xaheader, out waveformatex );\r
- if ( hxas == null )\r
- {\r
- Trace.TraceError( "Error: xaDecodeOpen(): " + Path.GetFileName( filename ) );\r
- wavBuf = null;\r
- return false;\r
- }\r
-\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**WAVEFORMATEX**" );\r
- //Debug.WriteLine( "wFormatTag= " + waveformatex.wFormatTag.ToString( "X4" ) );\r
- //Debug.WriteLine( "nChannels = " + waveformatex.nChannels.ToString( "X4" ) );\r
- //Debug.WriteLine( "nSamplesPerSec= " + waveformatex.nSamplesPerSec.ToString( "X8" ) );\r
- //Debug.WriteLine( "nAvgBytesPerSec= " + waveformatex.nAvgBytesPerSec.ToString( "X8" ) );\r
- //Debug.WriteLine( "nBlockAlign= " + waveformatex.nBlockAlign.ToString( "X4" ) );\r
- //Debug.WriteLine( "wBitsPerSample= " + waveformatex.wBitsPerSample.ToString( "X4" ) );\r
- //Debug.WriteLine( "cbSize= " + waveformatex.cbSize.ToString( "X4" ) );\r
- #endregion\r
- #endregion\r
-\r
- #region [ データ長の取得 ]\r
- uint dlen;\r
- xaDecodeSize( hxas, xaheader.nDataLen, out dlen );\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**INTERNAL VALUE**" );\r
- //Debug.WriteLine( "dlen= " + dlen );\r
- #endregion\r
- #endregion\r
-\r
- #region [ xaデータのデコード ]\r
- wavBuf = new byte[ dlen ];\r
- xastreamheader = new XASTREAMHEADER();\r
-\r
- unsafe\r
- {\r
- fixed ( byte* pXaBuf = xaBuf, pWavBuf = wavBuf )\r
- {\r
- xastreamheader.pSrc = pXaBuf;\r
- xastreamheader.nSrcLen = xaheader.nDataLen;\r
- xastreamheader.nSrcUsed = 0;\r
- xastreamheader.pDst = pWavBuf;\r
- xastreamheader.nDstLen = dlen;\r
- xastreamheader.nDstUsed = 0;\r
- bool b = xaDecodeConvert( hxas, ref xastreamheader );\r
- if ( !b )\r
- {\r
- Trace.TraceError( "Error: xaDecodeConvert(): " + Path.GetFileName( filename ) );\r
- wavBuf = null;\r
- return false;\r
- }\r
- }\r
- }\r
- #region [ デバッグ表示 ]\r
- //Debug.WriteLine( "**XASTREAMHEADER**" );\r
- //Debug.WriteLine( "nSrcLen= " + xastreamheader.nSrcLen );\r
- //Debug.WriteLine( "nSrcUsed= " + xastreamheader.nSrcUsed );\r
- //Debug.WriteLine( "nDstLen= " + xastreamheader.nDstLen );\r
- //Debug.WriteLine( "nDstUsed= " + xastreamheader.nDstUsed );\r
- #endregion\r
- #endregion\r
-\r
- #region [ xaファイルのクローズ ]\r
- bool bb = xaDecodeClose( hxas );\r
- if ( !bb )\r
- {\r
- Trace.TraceError( "Error: xaDecodeClose(): " + Path.GetFileName( filename ) );\r
- }\r
- #endregion\r
- }\r
-\r
- return true;\r
- }\r
-#endif\r
- }\r
-}\r