Advertisement
Guest User

Atacama

a guest
Apr 19th, 2008
1,296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 18.17 KB | None | 0 0
  1. /******************************************************************************
  2.  * BNRSound.cs
  3.  * Created by Atacama
  4.  *
  5.  * uses portions of in_cube code (coverted to c#)
  6.  * -created by hcs - http://www.hcs64.com/in_cube.html
  7.  *
  8.  *****************************************************************************/
  9.  
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13. using System.IO;
  14.  
  15. namespace bnrLoader
  16. {
  17.     class Channel
  18.     {
  19.         public short[] CoEfficients = new short[16];
  20.         public byte[] data;
  21.         public MemoryStream mspdata;
  22.         public MemoryStream msploop;
  23.         public BinaryWriter bwpdata;
  24.         public MemoryStream mscdata;
  25.         public BinaryReader brcdata;
  26.         //public byte header;
  27.         public short adpcmhistory1;
  28.         public short adpcmhistory2;
  29.         //private int loopcount = 0;
  30.         public bool loop;
  31.         public bool hasIntro = false;
  32.  
  33.         public void decodeDSP(int looppos)
  34.         {
  35.  
  36.             mspdata = new MemoryStream();
  37.             msploop = new MemoryStream();
  38.             bwpdata = new BinaryWriter(mspdata);
  39.             mscdata = new MemoryStream(data);
  40.             brcdata = new BinaryReader(mscdata);
  41.             looppos = ((looppos) /14) * 8;
  42.  
  43.             hasIntro = (looppos > 0);
  44.             while(mscdata.Position < mscdata.Length) {
  45.                 int sample;
  46.                 short[] nibbles = new short[14];
  47.                 int index1;
  48.                 int i,j;
  49.                 byte header;
  50.                 short delta;
  51.                 byte thisbyte;
  52.                 short hist=adpcmhistory1;
  53.                 short hist2=adpcmhistory2;
  54.                 // If we have loop data then we write to our looping file.
  55.                 if (mscdata.Position == looppos)
  56.                     bwpdata = new BinaryWriter(msploop);
  57.  
  58.  
  59.                 header = brcdata.ReadByte();
  60.                 i = header&0xFF;
  61.                 delta = (short) (1 << (i & 0xff & 0xf));
  62.                 index1 = (i & 0xff) >> 4;
  63.                
  64.                 for(i = 0; i < 14; i += 2) {
  65.                     thisbyte = brcdata.ReadByte();
  66.                     j = (thisbyte & 0xff) >> 4;
  67.                     nibbles[i] = (short) j;
  68.                     j = thisbyte & 0xff & 0xf;
  69.                     nibbles[i+1] = (short) j;
  70.                 }
  71.  
  72.                 for(i = 0; i < 14; i++) {
  73.                     if(nibbles[i] >= 8)
  74.                         nibbles[i] = (short)(nibbles[i] - 16);      
  75.                 }
  76.                  
  77.                 for(i = 0; i<14 ; i++) {
  78.  
  79.                     sample = (delta * nibbles[i])<<11;
  80.                     sample += CoEfficients[index1 * 2] * hist;
  81.                     sample += CoEfficients[index1 * 2 + 1] * hist2;
  82.                     sample = sample + 1024;
  83.                     sample = sample >> 11;
  84.                     if(sample > 32767)
  85.                         sample = 32767;
  86.  
  87.                     if(sample < -32768)
  88.                         sample = -32768;
  89.                     bwpdata.Write((short)sample);
  90.                     hist2 = hist;
  91.                     hist = (short)sample;
  92.                 }
  93.                 adpcmhistory1 = hist;
  94.                 adpcmhistory2 = hist2;
  95.  
  96.             }
  97.            
  98.         }
  99.  
  100.  
  101.     }
  102.     class BNRSound
  103.     {
  104.        
  105.         byte[] FileBuffer;
  106.         byte[] MD5Hash;
  107.  
  108.         public Channel[] channels;
  109.         byte codectype;
  110.         byte loop;
  111.         int loopstart;
  112.         byte channelCount = 0;
  113.         public ushort SampleRate;
  114.         uint SampleCount;
  115.         MemoryStream WholeStream;
  116.         MemoryStream InfoStream;
  117.         MemoryStream DataStream;
  118.         BinaryReader brInfoStream;
  119.         BinaryReader brDataStream;
  120.         string AudioFormat;
  121.         BinaryReader brWholeStream;
  122.         private long AudioDatastart;
  123.         //byte samplesperframe = 14;
  124.         //byte framesize = 8;
  125.  
  126.         /* For BNS We should have:
  127.          *  (GG means any hex data)
  128.          * I  M  D  5  |BNS  Size| Nothingness.......
  129.          * 49 4D 44 35 GG GG GG GG 00 00 00 00 00 00 00 00
  130.          * | ----------M D 5  H A S H -------------------|
  131.          * GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG
  132.          * B  N  S                 |BNS  Size| Unknown
  133.          * 42 4E 53 20 FE FF 01 00 GG GG GG GG GG GG GG GG  
  134.          * Info Offset|Info Length|Data Offset|Data Length|
  135.          * 00 00 00 20 00 00 00 A0 00 00 00 C0 00 04 2B A8
  136.          * I  N  F  O |Info Length|*1|*2|*3|*4| Hz  | Unk |   *1: Codec number? Seems to be 0 (NGC-DSP)
  137.          * 49 4E 46 4F 00 00 00 A0 00 00 02 00 7D 00 00 00    *2: Loop Flag?
  138.          * |LoopStart?|            |Always 18 and 4 nulls?|   *3: Channel Count?
  139.          * 00 00 00 00 00 03 A6 25 00 00 00 18 00 00 00 00    *4: Always 00?
  140.          * |       *5 |         *6|         *7|         *8|   *5: 1C if channels = 1, 20 if channels = 2
  141.          * 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
  142.          *            |        *10|         *11           |   *7: 28 if channels = 1, 00 if channels = 2
  143.      *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
  144.          *                                                    *9: This line is only here for stereo files.
  145.      *12 * FD A6 00 05 05 84 FE 38 01 16 04 B1 0C 41 FA D7    *10: Channel 2 start pos?
  146.          *                                                    *11: Always 68 surrounded by 00s
  147.      *12 * 01 DD FE 9D 06 BF FF D1 03 D3 03 CA 09 36 FE 9D    *12: Chan 0 ADPCM CoEfficients
  148.          *                                                    *13: Chan 1 ADPCM CoEfficients
  149.          * 00 00 00 42 00 00 00 00 00 42 00 00 00 00 00 00
  150.          *
  151.      *13 * FD 74 00 C7 05 CB FD F9 01 28 03 E7 08 43 FF 00
  152.          *
  153.      *13 * 01 8D FE 48 0B 7B FB 20 03 65 04 2E 07 84 00 5A
  154.          *
  155.          * 00 00 00 21 00 00 00 00 00 21 00 00 00 00 00 00
  156.          * D  A  T  A  |Data Size|
  157.          * 44 41 54 41 00 04 2B A8 42 86 B3 E2 E1 F1 F1 F1
  158.              
  159.          */
  160.  
  161.         public BNRSound(Stream fio)
  162.         {
  163.             WholeStream = (MemoryStream) fio;
  164.             brWholeStream = new BinaryReader(WholeStream);
  165.             byte[] IMD5 = brWholeStream.ReadBytes(4);
  166.            
  167.             if (System.Text.Encoding.ASCII.GetString(IMD5) != "IMD5")
  168.             {
  169.                 return;
  170.             }
  171.             WholeStream.Seek(12, SeekOrigin.Current);
  172.             MD5Hash = brWholeStream.ReadBytes(16);
  173.             AudioDatastart = WholeStream.Position;
  174.             audiodatacheck:
  175.  
  176.             /* Now we have actually reached the audio file data */
  177.             byte[] AudioType = brWholeStream.ReadBytes(3);
  178.             byte Extra = brWholeStream.ReadByte(); // when BNS it is a non printable char so we just read first 3.
  179.             AudioFormat = System.Text.Encoding.ASCII.GetString(AudioType);
  180.  
  181.  
  182.             switch (AudioFormat){
  183.                 case "BNS":
  184.                     /* BNS Format */
  185.                     processBNS();
  186.                     break;
  187.                 case "LZ7":
  188.                     /* LZ77 something so lets decompress it and try again */
  189.                     MemoryStream lzdata = new MemoryStream();
  190.                     LZ77Stream lz7s = new LZ77Stream(lzdata, System.IO.Compression.CompressionMode.Decompress);
  191.                    
  192.                     WholeStream.Seek(0x24, SeekOrigin.Begin);
  193.                     byte[] Indata = new byte[WholeStream.Length - WholeStream.Position];
  194.                     WholeStream.Read(Indata, 0, (int)(WholeStream.Length - WholeStream.Position));
  195.                     lz7s.Write(Indata, 0, (int)Indata.Length);
  196.                     WholeStream = lzdata;
  197.                     WholeStream.Seek(0, SeekOrigin.Begin);
  198.                     brWholeStream = new BinaryReader(WholeStream);
  199.                     AudioDatastart = 0;
  200.                     goto audiodatacheck;
  201.                 case "RIF":
  202.                     /* Wav file */
  203.                     processWAV();
  204.                     return;
  205.                     //break;
  206.                 case "FOR":
  207.                     /* Aif File */
  208.                     processAIF();
  209.                     return;
  210.                     //break;
  211.             }
  212.  
  213.  
  214.         }
  215.  
  216.         private void processBNS() {
  217.             uint ChannelSplit = 0;
  218.             WholeStream.Seek(4, SeekOrigin.Current);
  219.             uint bnssize = toBEInt(brWholeStream.ReadUInt32());
  220.             WholeStream.Seek(-12, SeekOrigin.Current);
  221.             FileBuffer = brWholeStream.ReadBytes((int) bnssize);
  222.             //WholeStream.Seek(0, SeekOrigin.Begin);
  223.  
  224.             WholeStream.Seek(-(FileBuffer.Length-12), SeekOrigin.Current);
  225.             uint unknown1 = toBEInt(brWholeStream.ReadUInt32());
  226.             uint infooffset = toBEInt(brWholeStream.ReadUInt32());
  227.             uint infolength = toBEInt(brWholeStream.ReadUInt32());
  228.             uint dataoffset = toBEInt(brWholeStream.ReadUInt32());
  229.             uint datalength = toBEInt(brWholeStream.ReadUInt32());
  230.             InfoStream = new MemoryStream(FileBuffer, (int)infooffset, (int)infolength);
  231.             brInfoStream = new BinaryReader(InfoStream);
  232.             DataStream = new MemoryStream(FileBuffer, (int)dataoffset, (int)datalength);
  233.             brDataStream = new BinaryReader(DataStream);
  234.  
  235.             InfoStream.Seek(8, SeekOrigin.Begin);
  236.             codectype = brInfoStream.ReadByte();
  237.             loop = brInfoStream.ReadByte();
  238.             channelCount = brInfoStream.ReadByte();
  239.             byte unknownbyte1 = brInfoStream.ReadByte();
  240.             SampleRate = toBEInt(brInfoStream.ReadUInt16());
  241.             ushort unknown2 = brInfoStream.ReadUInt16();
  242.             loopstart = toBEInt(brInfoStream.ReadInt32());
  243.             SampleCount = toBEInt(brInfoStream.ReadUInt32());
  244.  
  245.             channels = new Channel[channelCount];
  246.             InfoStream.Seek(24, SeekOrigin.Current);
  247.             uint length;
  248.             switch (channelCount)
  249.             {
  250.                 case 1:
  251.  
  252.                     channels[0] = new Channel();
  253.                     for (int a = 0; a < 16; a++)
  254.                     {
  255.                         channels[0].CoEfficients[a] = toBEInt(brInfoStream.ReadInt16());
  256.                     }
  257.                     channels[0].loop = (this.loop == 1);
  258.                     DataStream.Seek(4,SeekOrigin.Begin);
  259.                     length = toBEInt(brDataStream.ReadUInt32());
  260.                     channels[0].data = brDataStream.ReadBytes((int)length - 4);
  261.                     channels[0].decodeDSP(this.loopstart);
  262.                     FileStream fsmono = new FileStream(Path.GetTempPath() + "mono" + this.SampleRate.ToString() + ".raw", FileMode.Create, FileAccess.Write);
  263.  
  264.                     channels[0].mspdata.WriteTo(fsmono);
  265.                     fsmono.Close();
  266.  
  267.                     break;
  268.  
  269.                 case 2:
  270.                     uint unknown3 = toBEInt(brInfoStream.ReadUInt32());
  271.                     ChannelSplit = toBEInt(brInfoStream.ReadUInt32());
  272.                     uint unknown4 = toBEInt(brInfoStream.ReadUInt32());
  273.                     uint unknown5 = toBEInt(brInfoStream.ReadUInt32());
  274.                     channels[0] = new Channel();
  275.                     for (int a = 0; a < 16; a++)
  276.                     {
  277.                         channels[0].CoEfficients[a] = toBEInt(brInfoStream.ReadInt16());
  278.                     }
  279.                     channels[0].loop = (this.loop == 1);
  280.                     DataStream.Seek(4, SeekOrigin.Begin);
  281.                     length = toBEInt(brDataStream.ReadUInt32());
  282.                     channels[0].data = brDataStream.ReadBytes((int)ChannelSplit);
  283.                     channels[0].decodeDSP(this.loopstart);
  284.  
  285.                     FileStream fsleft = new FileStream(Path.GetTempPath() + "left" + this.SampleRate.ToString() + ".raw", FileMode.Create, FileAccess.Write);
  286.  
  287.                     channels[0].mspdata.WriteTo(fsleft);
  288.                     fsleft.Close();
  289.  
  290.  
  291.                     InfoStream.Seek(16, SeekOrigin.Current);
  292.                     channels[1] = new Channel();
  293.                     for (int a = 0; a < 16; a++)
  294.                     {
  295.                         channels[1].CoEfficients[a] = toBEInt(brInfoStream.ReadInt16());
  296.                     }
  297.                     channels[1].loop = (this.loop == 1);
  298.                     channels[1].data = brDataStream.ReadBytes((int)length - (int)ChannelSplit);
  299.                     channels[1].decodeDSP(this.loopstart);
  300.  
  301.                     FileStream fsright = new FileStream(Path.GetTempPath() + "right" + this.SampleRate.ToString() + ".raw", FileMode.Create, FileAccess.Write);
  302.  
  303.                     channels[1].mspdata.WriteTo(fsright);
  304.                     fsright.Close();
  305.  
  306.                     break;
  307.  
  308.             }
  309.  
  310.            
  311.  
  312.  
  313.         }
  314.  
  315.         private void processWAV()
  316.         {
  317.             // This is a bit inefficient since we split the wav stuff out to separate channels
  318.             // and then recombine it for DSound, doesn't matter too much though as we are
  319.             // only using memorystreams :)
  320.  
  321.  
  322.             int riffsize = brWholeStream.ReadInt32();
  323.             WholeStream.Seek(12, SeekOrigin.Current);
  324.             int pcm = brWholeStream.ReadInt16();
  325.  
  326.             if (pcm != 1)
  327.             {
  328.                 // Not PCM data
  329.                 return;
  330.             }
  331.             this.channelCount = (byte) brWholeStream.ReadInt16();
  332.             this.channels = new Channel[this.channelCount];
  333.             this.SampleRate = (ushort) brWholeStream.ReadInt32();
  334.             this.loop = 0;
  335.             WholeStream.Seek(12, SeekOrigin.Current);
  336.             channels[0] = new Channel();
  337.             channels[0].msploop = new MemoryStream();
  338.             BinaryWriter brleft = new BinaryWriter(channels[0].msploop);
  339.  
  340.             BinaryWriter brright = null;
  341.  
  342.             if (this.channelCount == 2)
  343.             {
  344.                 channels[1] = new Channel();
  345.                 channels[1].msploop = new MemoryStream();
  346.                 brright = new BinaryWriter(channels[0].msploop);
  347.                
  348.  
  349.             }
  350.  
  351.             while (WholeStream.Position < riffsize)
  352.             {
  353.                 brleft.Write(brWholeStream.ReadInt32());
  354.                 if (this.channels.Length == 2)
  355.                 {
  356.                     brright.Write(brWholeStream.ReadInt32());
  357.                 }
  358.  
  359.             }
  360.  
  361.             /*bwav.Write("RIFF".ToCharArray());
  362. bwav.Write(totallength + 0x2c);
  363. bwav.Write("WAVEfmt ".ToCharArray());
  364. bwav.Write((int)0x10);
  365. bwav.Write((short)1);
  366. bwav.Write((short)channelcount);
  367. bwav.Write((int)WiiSound.SampleRate);
  368. bwav.Write((int)bps);
  369. bwav.Write((short)(channelcount * 2));
  370. bwav.Write((short)0x10);
  371. bwav.Write("data".ToCharArray());
  372. bwav.Write(totallength);
  373.  * */
  374.  
  375.         }
  376.  
  377.         private void processAIF()
  378.         {
  379.  
  380.             uint aiffsize = brWholeStream.ReadUInt32();
  381.             byte[] aifftype = brWholeStream.ReadBytes(4);
  382.  
  383.             BinaryWriter brleft = null;
  384.  
  385.             BinaryWriter brright = null;
  386.             do
  387.             {
  388.                 //            WholeStream.Seek(0x90, SeekOrigin.Current);
  389.                 byte[] type = brWholeStream.ReadBytes(4);
  390.                 uint size = toBEInt(brWholeStream.ReadUInt32());
  391.                 long start = WholeStream.Position;
  392.  
  393.                 string sInType = System.Text.Encoding.ASCII.GetString(type);
  394.  
  395.  
  396.                 switch (sInType)
  397.                 {
  398.                     case "COMM":
  399.                         //header - we will assume this comes before ssnd
  400.                         this.channelCount = (byte) toBEInt(brWholeStream.ReadInt16());
  401.                         this.channels = new Channel[this.channelCount];
  402.  
  403.  
  404.                         ulong numsampleframes = brWholeStream.ReadUInt32();
  405.                         ushort bits = toBEInt(brWholeStream.ReadUInt16());
  406.                         ushort wtf = toBEInt(brWholeStream.ReadUInt16());
  407.                         this.SampleRate = toBEInt(brWholeStream.ReadUInt16());
  408.                         this.loop = 0;
  409.                         this.channels[0] = new Channel();
  410.                         this.channels[0].msploop = new MemoryStream();
  411.                         brleft = new BinaryWriter(channels[0].msploop);
  412.  
  413.                         if (this.channelCount == 2)
  414.                         {
  415.                             channels[1] = new Channel();
  416.                             channels[1].msploop = new MemoryStream();
  417.                             brright = new BinaryWriter(channels[0].msploop);
  418.                         }
  419.                         break;
  420.                     case "SSND":
  421.                         // Sound Data
  422.  
  423.  
  424.                         while (WholeStream.Position < (start + (long) size))
  425.                         {
  426.                             brleft.Write(toBEInt(brWholeStream.ReadInt32()));
  427.                             if (this.channels.Length == 2)
  428.                             {
  429.                                 brright.Write(toBEInt(brWholeStream.ReadInt32()));
  430.                             }
  431.  
  432.                         }
  433.                         break;
  434.  
  435.                 }
  436.  
  437.                 WholeStream.Seek(start + (long) size, SeekOrigin.Begin);
  438.  
  439.  
  440.  
  441.  
  442.  
  443.                
  444.                
  445.                 //WholeStream.Seek(12, SeekOrigin.Current);
  446.  
  447.  
  448.  
  449.             } while (WholeStream.Position < WholeStream.Length);
  450.  
  451.         }
  452.  
  453.  
  454.         public int toBEInt(int theint)
  455.         {
  456.             return ((theint & 0x000000ff) << 24) |
  457.            ((theint & 0x0000ff00) << 8) |
  458.            ((theint & 0x00ff0000) >> 8) | (int)
  459.            ((theint & 0xff000000) >> 24);
  460.         }
  461.         public uint toBEInt(uint theint)
  462.         {
  463.             return (uint)(theint >> 24) |
  464.              ((theint << 8) & 0x00FF0000) |
  465.              ((theint >> 8) & 0x0000FF00) |
  466.               (theint << 24);
  467.         }
  468.         public short toBEInt(short theshort)
  469.         {
  470.             int theint = (int)theshort;
  471.             int ret = ((theint >> 8) & 0xff) | (theint & 0xff) << 8;
  472.  
  473.             return (short)ret;
  474.         }
  475.         public ushort toBEInt(ushort theshort)
  476.         {
  477.             return (ushort)(theshort >> 8 | theshort << 8);
  478.  
  479.  
  480.         }
  481.  
  482.  
  483.     }
  484. }
  485.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement