OSDN Git Service

1b729d55f847a72f97869edde0aca28df195903c
[dtxmania/dtxmania.git] / FDK / コード / 03.サウンド / Cmp3.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Runtime.InteropServices;
5 using System.IO;
6 using System.Diagnostics;
7 using System.Threading;
8 using Un4seen.Bass;
9 using Un4seen.Bass.Misc;
10
11
12 namespace FDK
13 {
14         public unsafe class Cmp3 : SoundDecoder
15         {
16                 private int stream_in = -1;
17                 private bool bBASS_Already_Init = false;
18
19                 public override int Open( string filename )
20                 {
21                         bBASS_Already_Init = !Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
22                         // WASAPI/ASIO使用時は(BASS_ERROR_ALREADYとなって)falseが返るので、覚えておく。
23                         // 後でCmp3.Close()時にBASSを終了させないようにするため。
24
25                         stream_in = Bass.BASS_StreamCreateFile(filename, 0, 0, BASSFlag.BASS_DEFAULT | BASSFlag.BASS_STREAM_DECODE);
26                         if (stream_in == 0)
27                         {
28                                 BASSError be = Bass.BASS_ErrorGetCode();
29                                 Trace.TraceInformation("Cmp3: StreamCreateFile error: " + be.ToString());
30                         }
31                         nTotalPCMSize = Bass.BASS_ChannelGetLength(stream_in);
32
33                         #region [ Getting WAVEFORMEX info ]
34                         var chinfo = Bass.BASS_ChannelGetInfo(stream_in);
35                         wfx = new CWin32.WAVEFORMATEX(
36                                 (ushort)1,                                                              // wFormatTag
37                                 (ushort)chinfo.chans,                                   // nChannels
38                                 (uint)chinfo.freq,                                              // nSamplesPerSec
39                                 (uint)(chinfo.freq * 2 * chinfo.chans), // nAvgBytesPerSec
40                                 (ushort)(2 * chinfo.chans),                             // nBlockAlign
41                                 16,                                                                             // wBitsPerSample
42                                 0                                                                               // cbSize                               
43                         );
44                         #endregion
45
46                         //string fn = Path.GetFileName(filename); 
47                         //Trace.TraceInformation("filename=" + fn + ", size=(decode): " + wavdata.Length + ", channelgetlength=" + _TotalPCMSize2 + ", " + _TotalPCMSize) ;
48
49                         return 0;
50                 }
51
52                 public override int Decode(ref byte[] Dest, long offset)
53                 {
54                         #region [ decode ]
55                         int LEN = 65536;
56                         byte[] data = new byte[LEN]; // 2 x 16-bit and length in is bytes
57                         long len = 0;
58                         long p = 0;
59                         do
60                         {
61                                 len = Bass.BASS_ChannelGetData(stream_in, data, LEN);
62                                 if (len < 0)
63                                 {
64                                         BASSError be = Bass.BASS_ErrorGetCode();
65                                         Trace.TraceInformation("Cmp3: BASS_ChannelGetData Error: " + be.ToString());
66                                 }
67                                 if (p + len > nTotalPCMSize)
68                                 {
69                                         len = nTotalPCMSize - p;
70                                 }
71                                 Array.Copy(data, 0, Dest, p, len);
72                                 p += len;
73                         } while (p < nTotalPCMSize);
74                         #endregion
75
76 //SaveWav(filename, Dest);
77
78                         data = null;
79                         return 0;
80                 }
81
82                 public override void Close()
83                 {
84                         if (!bBASS_Already_Init)
85                         {
86                                 Bass.BASS_StreamFree(stream_in);
87                                 Bass.BASS_Free();
88                         }
89                 }
90
91                 /// <summary>
92                 /// save wav file (for debugging)
93                 /// </summary>
94                 /// <param name="filename">input mp3/xa filename</param>
95                 private void SaveWav(string filename, byte[] Dest)
96                 {
97                         string outfile = Path.GetFileName(filename);
98                         var fs = new FileStream(outfile + ".wav", FileMode.Create);
99                         var st = new BinaryWriter(fs);
100
101                         st.Write(new byte[] { 0x52, 0x49, 0x46, 0x46 });      // 'RIFF'
102                         st.Write((int)(nTotalPCMSize + 44 - 8));            // RIFF chunk size
103                         st.Write(new byte[] { 0x57, 0x41, 0x56, 0x45 });      // 'WAVE'
104                         st.Write(new byte[] { 0x66, 0x6D, 0x74, 0x20 });      // 'fmt '
105                         st.Write(new byte[] { 0x10, 0x00, 0x00, 0x00 });      // chunk size 16bytes
106                         st.Write(new byte[] { 0x01, 0x00 }, 0, 2);                  // formatTag 0001 PCM
107                         st.Write((short)wfx.nChannels);                              // channels
108                         st.Write((int)wfx.nSamplesPerSec);                             // samples per sec
109                         st.Write((int)wfx.nAvgBytesPerSec);          // avg bytesper sec
110                         st.Write((short)wfx.nBlockAlign);                        // blockalign = 16bit * mono/stereo
111                         st.Write((short)wfx.wBitsPerSample);                  // bitspersample = 16bits
112
113                         st.Write(new byte[] { 0x64, 0x61, 0x74, 0x61 });      // 'data'
114                         st.Write((int) nTotalPCMSize);      // datasize 
115                         
116                         st.Write(Dest);
117 Trace.TraceInformation($"wrote ({outfile}.wav) fsLength=" + fs.Length + ", TotalPCMSize=" + nTotalPCMSize + ", diff=" + (fs.Length - nTotalPCMSize));
118                         st.Dispose();
119                         fs.Dispose();
120                 }
121         }
122 }