2 using System.Collections.Generic;
4 using System.Runtime.InteropServices;
6 using System.Diagnostics;
7 using System.Threading;
9 using Un4seen.Bass.Misc;
14 public unsafe class Cmp3 : SoundDecoder
16 private int stream_in = -1;
17 private bool bBASS_Already_Init = false;
19 public override int Open( string filename )
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を終了させないようにするため。
25 stream_in = Bass.BASS_StreamCreateFile(filename, 0, 0, BASSFlag.BASS_DEFAULT | BASSFlag.BASS_STREAM_DECODE);
28 BASSError be = Bass.BASS_ErrorGetCode();
29 Trace.TraceInformation("Cmp3: StreamCreateFile error: " + be.ToString());
32 nTotalPCMSize = Bass.BASS_ChannelGetLength(stream_in);
34 #region [ Getting WAVEFORMEX info ]
35 var chinfo = Bass.BASS_ChannelGetInfo(stream_in);
36 wfx = new CWin32.WAVEFORMATEX(
37 (ushort)1, // wFormatTag
38 (ushort)chinfo.chans, // nChannels
39 (uint)chinfo.freq, // nSamplesPerSec
40 (uint)(chinfo.freq * 2 * chinfo.chans), // nAvgBytesPerSec
41 (ushort)(2 * chinfo.chans), // nBlockAlign
47 //string fn = Path.GetFileName(filename);
48 //Trace.TraceInformation("filename=" + fn + ", size=(decode): " + wavdata.Length + ", channelgetlength=" + _TotalPCMSize2 + ", " + _TotalPCMSize) ;
53 public override int Decode(ref byte[] Dest, long offset)
57 byte[] data = new byte[LEN]; // 2 x 16-bit and length in is bytes
62 len = Bass.BASS_ChannelGetData(stream_in, data, LEN);
65 BASSError be = Bass.BASS_ErrorGetCode();
66 Trace.TraceInformation("Cmp3: BASS_ChannelGetData Error: " + be.ToString());
68 if (p + len > nTotalPCMSize)
70 len = nTotalPCMSize - p;
72 Array.Copy(data, 0, Dest, p, len);
74 } while (p < nTotalPCMSize);
77 //SaveWav(filename, Dest);
83 public override void Close()
85 if (!bBASS_Already_Init)
87 Bass.BASS_StreamFree(stream_in);
93 /// save wav file (for debugging)
95 /// <param name="filename">input mp3/xa filename</param>
96 private void SaveWav(string filename, byte[] Dest)
98 string outfile = Path.GetFileName(filename);
99 var fs = new FileStream(outfile + ".wav", FileMode.Create);
100 var st = new BinaryWriter(fs);
102 st.Write(new byte[] { 0x52, 0x49, 0x46, 0x46 }); // 'RIFF'
103 st.Write((int)(nTotalPCMSize + 44 - 8)); // RIFF chunk size
104 st.Write(new byte[] { 0x57, 0x41, 0x56, 0x45 }); // 'WAVE'
105 st.Write(new byte[] { 0x66, 0x6D, 0x74, 0x20 }); // 'fmt '
106 st.Write(new byte[] { 0x10, 0x00, 0x00, 0x00 }); // chunk size 16bytes
107 st.Write(new byte[] { 0x01, 0x00 }, 0, 2); // formatTag 0001 PCM
108 st.Write((short)wfx.nChannels); // channels
109 st.Write((int)wfx.nSamplesPerSec); // samples per sec
110 st.Write((int)wfx.nAvgBytesPerSec); // avg bytesper sec
111 st.Write((short)wfx.nBlockAlign); // blockalign = 16bit * mono/stereo
112 st.Write((short)wfx.wBitsPerSample); // bitspersample = 16bits
114 st.Write(new byte[] { 0x64, 0x61, 0x74, 0x61 }); // 'data'
115 st.Write((int) nTotalPCMSize); // datasize
118 Trace.TraceInformation($"wrote ({outfile}.wav) fsLength=" + fs.Length + ", TotalPCMSize=" + nTotalPCMSize + ", diff=" + (fs.Length - nTotalPCMSize));