Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************
- * BNRSound.cs
- * Created by Atacama
- *
- * uses portions of in_cube code (coverted to c#)
- * -created by hcs - http://www.hcs64.com/in_cube.html
- *
- *****************************************************************************/
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.IO;
- namespace bnrLoader
- {
- class Channel
- {
- public short[] CoEfficients = new short[16];
- public byte[] data;
- public MemoryStream mspdata;
- public MemoryStream msploop;
- public BinaryWriter bwpdata;
- public MemoryStream mscdata;
- public BinaryReader brcdata;
- //public byte header;
- public short adpcmhistory1;
- public short adpcmhistory2;
- //private int loopcount = 0;
- public bool loop;
- public bool hasIntro = false;
- public void decodeDSP(int looppos)
- {
- mspdata = new MemoryStream();
- msploop = new MemoryStream();
- bwpdata = new BinaryWriter(mspdata);
- mscdata = new MemoryStream(data);
- brcdata = new BinaryReader(mscdata);
- looppos = ((looppos) /14) * 8;
- hasIntro = (looppos > 0);
- while(mscdata.Position < mscdata.Length) {
- int sample;
- short[] nibbles = new short[14];
- int index1;
- int i,j;
- byte header;
- short delta;
- byte thisbyte;
- short hist=adpcmhistory1;
- short hist2=adpcmhistory2;
- // If we have loop data then we write to our looping file.
- if (mscdata.Position == looppos)
- bwpdata = new BinaryWriter(msploop);
- header = brcdata.ReadByte();
- i = header&0xFF;
- delta = (short) (1 << (i & 0xff & 0xf));
- index1 = (i & 0xff) >> 4;
- for(i = 0; i < 14; i += 2) {
- thisbyte = brcdata.ReadByte();
- j = (thisbyte & 0xff) >> 4;
- nibbles[i] = (short) j;
- j = thisbyte & 0xff & 0xf;
- nibbles[i+1] = (short) j;
- }
- for(i = 0; i < 14; i++) {
- if(nibbles[i] >= 8)
- nibbles[i] = (short)(nibbles[i] - 16);
- }
- for(i = 0; i<14 ; i++) {
- sample = (delta * nibbles[i])<<11;
- sample += CoEfficients[index1 * 2] * hist;
- sample += CoEfficients[index1 * 2 + 1] * hist2;
- sample = sample + 1024;
- sample = sample >> 11;
- if(sample > 32767)
- sample = 32767;
- if(sample < -32768)
- sample = -32768;
- bwpdata.Write((short)sample);
- hist2 = hist;
- hist = (short)sample;
- }
- adpcmhistory1 = hist;
- adpcmhistory2 = hist2;
- }
- }
- }
- class BNRSound
- {
- byte[] FileBuffer;
- byte[] MD5Hash;
- public Channel[] channels;
- byte codectype;
- byte loop;
- int loopstart;
- byte channelCount = 0;
- public ushort SampleRate;
- uint SampleCount;
- MemoryStream WholeStream;
- MemoryStream InfoStream;
- MemoryStream DataStream;
- BinaryReader brInfoStream;
- BinaryReader brDataStream;
- string AudioFormat;
- BinaryReader brWholeStream;
- private long AudioDatastart;
- //byte samplesperframe = 14;
- //byte framesize = 8;
- /* For BNS We should have:
- * (GG means any hex data)
- * I M D 5 |BNS Size| Nothingness.......
- * 49 4D 44 35 GG GG GG GG 00 00 00 00 00 00 00 00
- * | ----------M D 5 H A S H -------------------|
- * GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG
- * B N S |BNS Size| Unknown
- * 42 4E 53 20 FE FF 01 00 GG GG GG GG GG GG GG GG
- * Info Offset|Info Length|Data Offset|Data Length|
- * 00 00 00 20 00 00 00 A0 00 00 00 C0 00 04 2B A8
- * I N F O |Info Length|*1|*2|*3|*4| Hz | Unk | *1: Codec number? Seems to be 0 (NGC-DSP)
- * 49 4E 46 4F 00 00 00 A0 00 00 02 00 7D 00 00 00 *2: Loop Flag?
- * |LoopStart?| |Always 18 and 4 nulls?| *3: Channel Count?
- * 00 00 00 00 00 03 A6 25 00 00 00 18 00 00 00 00 *4: Always 00?
- * | *5 | *6| *7| *8| *5: 1C if channels = 1, 20 if channels = 2
- * 00 00 00 20 00 00 00 2C 00 00 00 00 00 00 00 38 *6: 00 if channels = 1, 2C if channels = 2
- * | *10| *11 | *7: 28 if channels = 1, 00 if channels = 2
- *9 * 00 00 00 00 00 02 15 D0 00 00 00 68 00 00 00 00 *8: 00 if channels = 1, 38 if channels = 2
- * *9: This line is only here for stereo files.
- *12 * FD A6 00 05 05 84 FE 38 01 16 04 B1 0C 41 FA D7 *10: Channel 2 start pos?
- * *11: Always 68 surrounded by 00s
- *12 * 01 DD FE 9D 06 BF FF D1 03 D3 03 CA 09 36 FE 9D *12: Chan 0 ADPCM CoEfficients
- * *13: Chan 1 ADPCM CoEfficients
- * 00 00 00 42 00 00 00 00 00 42 00 00 00 00 00 00
- *
- *13 * FD 74 00 C7 05 CB FD F9 01 28 03 E7 08 43 FF 00
- *
- *13 * 01 8D FE 48 0B 7B FB 20 03 65 04 2E 07 84 00 5A
- *
- * 00 00 00 21 00 00 00 00 00 21 00 00 00 00 00 00
- * D A T A |Data Size|
- * 44 41 54 41 00 04 2B A8 42 86 B3 E2 E1 F1 F1 F1
- */
- public BNRSound(Stream fio)
- {
- WholeStream = (MemoryStream) fio;
- brWholeStream = new BinaryReader(WholeStream);
- byte[] IMD5 = brWholeStream.ReadBytes(4);
- if (System.Text.Encoding.ASCII.GetString(IMD5) != "IMD5")
- {
- return;
- }
- WholeStream.Seek(12, SeekOrigin.Current);
- MD5Hash = brWholeStream.ReadBytes(16);
- AudioDatastart = WholeStream.Position;
- audiodatacheck:
- /* Now we have actually reached the audio file data */
- byte[] AudioType = brWholeStream.ReadBytes(3);
- byte Extra = brWholeStream.ReadByte(); // when BNS it is a non printable char so we just read first 3.
- AudioFormat = System.Text.Encoding.ASCII.GetString(AudioType);
- switch (AudioFormat){
- case "BNS":
- /* BNS Format */
- processBNS();
- break;
- case "LZ7":
- /* LZ77 something so lets decompress it and try again */
- MemoryStream lzdata = new MemoryStream();
- LZ77Stream lz7s = new LZ77Stream(lzdata, System.IO.Compression.CompressionMode.Decompress);
- WholeStream.Seek(0x24, SeekOrigin.Begin);
- byte[] Indata = new byte[WholeStream.Length - WholeStream.Position];
- WholeStream.Read(Indata, 0, (int)(WholeStream.Length - WholeStream.Position));
- lz7s.Write(Indata, 0, (int)Indata.Length);
- WholeStream = lzdata;
- WholeStream.Seek(0, SeekOrigin.Begin);
- brWholeStream = new BinaryReader(WholeStream);
- AudioDatastart = 0;
- goto audiodatacheck;
- case "RIF":
- /* Wav file */
- processWAV();
- return;
- //break;
- case "FOR":
- /* Aif File */
- processAIF();
- return;
- //break;
- }
- }
- private void processBNS() {
- uint ChannelSplit = 0;
- WholeStream.Seek(4, SeekOrigin.Current);
- uint bnssize = toBEInt(brWholeStream.ReadUInt32());
- WholeStream.Seek(-12, SeekOrigin.Current);
- FileBuffer = brWholeStream.ReadBytes((int) bnssize);
- //WholeStream.Seek(0, SeekOrigin.Begin);
- WholeStream.Seek(-(FileBuffer.Length-12), SeekOrigin.Current);
- uint unknown1 = toBEInt(brWholeStream.ReadUInt32());
- uint infooffset = toBEInt(brWholeStream.ReadUInt32());
- uint infolength = toBEInt(brWholeStream.ReadUInt32());
- uint dataoffset = toBEInt(brWholeStream.ReadUInt32());
- uint datalength = toBEInt(brWholeStream.ReadUInt32());
- InfoStream = new MemoryStream(FileBuffer, (int)infooffset, (int)infolength);
- brInfoStream = new BinaryReader(InfoStream);
- DataStream = new MemoryStream(FileBuffer, (int)dataoffset, (int)datalength);
- brDataStream = new BinaryReader(DataStream);
- InfoStream.Seek(8, SeekOrigin.Begin);
- codectype = brInfoStream.ReadByte();
- loop = brInfoStream.ReadByte();
- channelCount = brInfoStream.ReadByte();
- byte unknownbyte1 = brInfoStream.ReadByte();
- SampleRate = toBEInt(brInfoStream.ReadUInt16());
- ushort unknown2 = brInfoStream.ReadUInt16();
- loopstart = toBEInt(brInfoStream.ReadInt32());
- SampleCount = toBEInt(brInfoStream.ReadUInt32());
- channels = new Channel[channelCount];
- InfoStream.Seek(24, SeekOrigin.Current);
- uint length;
- switch (channelCount)
- {
- case 1:
- channels[0] = new Channel();
- for (int a = 0; a < 16; a++)
- {
- channels[0].CoEfficients[a] = toBEInt(brInfoStream.ReadInt16());
- }
- channels[0].loop = (this.loop == 1);
- DataStream.Seek(4,SeekOrigin.Begin);
- length = toBEInt(brDataStream.ReadUInt32());
- channels[0].data = brDataStream.ReadBytes((int)length - 4);
- channels[0].decodeDSP(this.loopstart);
- FileStream fsmono = new FileStream(Path.GetTempPath() + "mono" + this.SampleRate.ToString() + ".raw", FileMode.Create, FileAccess.Write);
- channels[0].mspdata.WriteTo(fsmono);
- fsmono.Close();
- break;
- case 2:
- uint unknown3 = toBEInt(brInfoStream.ReadUInt32());
- ChannelSplit = toBEInt(brInfoStream.ReadUInt32());
- uint unknown4 = toBEInt(brInfoStream.ReadUInt32());
- uint unknown5 = toBEInt(brInfoStream.ReadUInt32());
- channels[0] = new Channel();
- for (int a = 0; a < 16; a++)
- {
- channels[0].CoEfficients[a] = toBEInt(brInfoStream.ReadInt16());
- }
- channels[0].loop = (this.loop == 1);
- DataStream.Seek(4, SeekOrigin.Begin);
- length = toBEInt(brDataStream.ReadUInt32());
- channels[0].data = brDataStream.ReadBytes((int)ChannelSplit);
- channels[0].decodeDSP(this.loopstart);
- FileStream fsleft = new FileStream(Path.GetTempPath() + "left" + this.SampleRate.ToString() + ".raw", FileMode.Create, FileAccess.Write);
- channels[0].mspdata.WriteTo(fsleft);
- fsleft.Close();
- InfoStream.Seek(16, SeekOrigin.Current);
- channels[1] = new Channel();
- for (int a = 0; a < 16; a++)
- {
- channels[1].CoEfficients[a] = toBEInt(brInfoStream.ReadInt16());
- }
- channels[1].loop = (this.loop == 1);
- channels[1].data = brDataStream.ReadBytes((int)length - (int)ChannelSplit);
- channels[1].decodeDSP(this.loopstart);
- FileStream fsright = new FileStream(Path.GetTempPath() + "right" + this.SampleRate.ToString() + ".raw", FileMode.Create, FileAccess.Write);
- channels[1].mspdata.WriteTo(fsright);
- fsright.Close();
- break;
- }
- }
- private void processWAV()
- {
- // This is a bit inefficient since we split the wav stuff out to separate channels
- // and then recombine it for DSound, doesn't matter too much though as we are
- // only using memorystreams :)
- int riffsize = brWholeStream.ReadInt32();
- WholeStream.Seek(12, SeekOrigin.Current);
- int pcm = brWholeStream.ReadInt16();
- if (pcm != 1)
- {
- // Not PCM data
- return;
- }
- this.channelCount = (byte) brWholeStream.ReadInt16();
- this.channels = new Channel[this.channelCount];
- this.SampleRate = (ushort) brWholeStream.ReadInt32();
- this.loop = 0;
- WholeStream.Seek(12, SeekOrigin.Current);
- channels[0] = new Channel();
- channels[0].msploop = new MemoryStream();
- BinaryWriter brleft = new BinaryWriter(channels[0].msploop);
- BinaryWriter brright = null;
- if (this.channelCount == 2)
- {
- channels[1] = new Channel();
- channels[1].msploop = new MemoryStream();
- brright = new BinaryWriter(channels[0].msploop);
- }
- while (WholeStream.Position < riffsize)
- {
- brleft.Write(brWholeStream.ReadInt32());
- if (this.channels.Length == 2)
- {
- brright.Write(brWholeStream.ReadInt32());
- }
- }
- /*bwav.Write("RIFF".ToCharArray());
- bwav.Write(totallength + 0x2c);
- bwav.Write("WAVEfmt ".ToCharArray());
- bwav.Write((int)0x10);
- bwav.Write((short)1);
- bwav.Write((short)channelcount);
- bwav.Write((int)WiiSound.SampleRate);
- bwav.Write((int)bps);
- bwav.Write((short)(channelcount * 2));
- bwav.Write((short)0x10);
- bwav.Write("data".ToCharArray());
- bwav.Write(totallength);
- * */
- }
- private void processAIF()
- {
- uint aiffsize = brWholeStream.ReadUInt32();
- byte[] aifftype = brWholeStream.ReadBytes(4);
- BinaryWriter brleft = null;
- BinaryWriter brright = null;
- do
- {
- // WholeStream.Seek(0x90, SeekOrigin.Current);
- byte[] type = brWholeStream.ReadBytes(4);
- uint size = toBEInt(brWholeStream.ReadUInt32());
- long start = WholeStream.Position;
- string sInType = System.Text.Encoding.ASCII.GetString(type);
- switch (sInType)
- {
- case "COMM":
- //header - we will assume this comes before ssnd
- this.channelCount = (byte) toBEInt(brWholeStream.ReadInt16());
- this.channels = new Channel[this.channelCount];
- ulong numsampleframes = brWholeStream.ReadUInt32();
- ushort bits = toBEInt(brWholeStream.ReadUInt16());
- ushort wtf = toBEInt(brWholeStream.ReadUInt16());
- this.SampleRate = toBEInt(brWholeStream.ReadUInt16());
- this.loop = 0;
- this.channels[0] = new Channel();
- this.channels[0].msploop = new MemoryStream();
- brleft = new BinaryWriter(channels[0].msploop);
- if (this.channelCount == 2)
- {
- channels[1] = new Channel();
- channels[1].msploop = new MemoryStream();
- brright = new BinaryWriter(channels[0].msploop);
- }
- break;
- case "SSND":
- // Sound Data
- while (WholeStream.Position < (start + (long) size))
- {
- brleft.Write(toBEInt(brWholeStream.ReadInt32()));
- if (this.channels.Length == 2)
- {
- brright.Write(toBEInt(brWholeStream.ReadInt32()));
- }
- }
- break;
- }
- WholeStream.Seek(start + (long) size, SeekOrigin.Begin);
- //WholeStream.Seek(12, SeekOrigin.Current);
- } while (WholeStream.Position < WholeStream.Length);
- }
- public int toBEInt(int theint)
- {
- return ((theint & 0x000000ff) << 24) |
- ((theint & 0x0000ff00) << 8) |
- ((theint & 0x00ff0000) >> 8) | (int)
- ((theint & 0xff000000) >> 24);
- }
- public uint toBEInt(uint theint)
- {
- return (uint)(theint >> 24) |
- ((theint << 8) & 0x00FF0000) |
- ((theint >> 8) & 0x0000FF00) |
- (theint << 24);
- }
- public short toBEInt(short theshort)
- {
- int theint = (int)theshort;
- int ret = ((theint >> 8) & 0xff) | (theint & 0xff) << 8;
- return (short)ret;
- }
- public ushort toBEInt(ushort theshort)
- {
- return (ushort)(theshort >> 8 | theshort << 8);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement