Exemple #1
0
        public byte[] GetRawSongs()
        {
            if (this.id == 0)
            {
                var dataLength = 0;
                //get data length, for faster concat
                for (int i = 0; i < songList.Count; i++)
                {
                    dataLength += songList[i].rawData.Length;
                }


                byte[] midiData = new byte[dataLength];
                int    index    = 0;

                //do fast concat
                for (int i = 0; i < songList.Count; i++)
                {
                    var songRawData = CGeneric.GiveMeArray(songList[i].rawData, 0, songList[i].rawData.Length);
                    for (int j = 0; j < songList[i].rawData.Length; j++)
                    {
                        midiData[index + j] = songRawData[j];
                    }
                    index += songList[i].rawData.Length;
                }
                return(midiData);
            }
            else
            {
                return(midi);
            }
        }
Exemple #2
0
        private void DecomposeSounds()
        {
            nbInstruments = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, 0x20, 4));

            int indexSoundPtr = 0;
            int soundLength   = 0;

            for (int i = 0; i < nbInstruments; i++)
            {
                Sound sound = new Sound();

                sound.start = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, indexSoundPtr + 0x30, 4));
                soundLength = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, indexSoundPtr + 0x34, 4));

                //grab sound data
                sound.rawData = CGeneric.GiveMeArray(waveTable, sound.start, soundLength);

                sound.loop.offset      = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, indexSoundPtr + 0x3C, 4));
                sound.predictor.offset = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, indexSoundPtr + 0x40, 4));

                //loop
                if (sound.loop.offset != 0)
                {
                    sound.loop.start = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, sound.loop.offset, 4));
                    sound.loop.end   = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, sound.loop.offset + 4, 4));
                    sound.loop.count = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, sound.loop.offset + 8, 4));
                    sound.loop.state = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, sound.loop.offset + 0xC, 0x20));
                }

                //predictors
                sound.predictor.order       = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, sound.predictor.offset, 4));
                sound.predictor.nPredictors = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(ptrTable, sound.predictor.offset + 4, 4));
                sound.predictor.predictors  = CGeneric.GiveMeArray(ptrTable, sound.predictor.offset + 8, sound.predictor.order * sound.predictor.nPredictors * 8 * 2);

                sound.predictor.predictorShort = new short[sound.predictor.predictors.Length / 2];
                for (int j = 0; j < sound.predictor.predictorShort.Length; j++)
                {
                    sound.predictor.predictorShort[j] = BitConverter.ToInt16(new[] { sound.predictor.predictors[j * 2 + 1], sound.predictor.predictors[j * 2] }, 0);
                }

                if (sound.loop.offset != 0)
                {
                    indexSoundPtr = sound.loop.offset;
                }
                else
                {
                    indexSoundPtr += 0xA0;
                }
                soundList.Add(sound);
            }
        }
Exemple #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="wavData">the waveData</param>
        /// <param name="predictorOrder"></param>
        /// <param name="predictors"></param>
        /// <param name="npredictors"></param>
        /// <returns></returns>
        public static short[] Decode(byte[] wavData, int predictorOrder, short[] predictors, int npredictors)
        {
            int index;
            int pred;

            short[] output = new short[wavData.Length * 2];
            short[] tmpOut = new short[8];

            //flip the predictors
            short[] preds = new short[32 * npredictors];
            for (int j = 0; j < (8 * predictorOrder * npredictors); j++)
            {
                preds[j] = predictors[j];
            }

            int indexIn  = 0;
            int indexOut = 0;

            int i = (wavData.Length / 9) * 9;

            while (i > 0)
            {
                index = (wavData[indexIn] >> 4) & 0xF;
                pred  = (wavData[indexIn] & 0xF);

                i--;

                short[] pred1 = new short[16];
                for (int j = 0; j < 16; j++)
                {
                    pred1[j] = preds[pred * 16 + j];
                }

                indexIn++;
                tmpOut = Decode8(CGeneric.GiveMeArray(wavData, indexIn, 8), index, pred1, tmpOut, pred);
                Array.Copy(tmpOut, 0, output, indexOut, 8);
                indexIn  += 4;
                i        -= 4;
                indexOut += 8;

                tmpOut = Decode8(CGeneric.GiveMeArray(wavData, indexIn, i == 4 ? i:8), index, pred1, tmpOut, pred);
                Array.Copy(tmpOut, 0, output, indexOut, 8);
                indexIn  += 4;
                i        -= 4;
                indexOut += 8;
            }

            //trim 00 end padding
            return(output.Take(indexOut).ToArray());
        }
Exemple #4
0
        private byte[] DecodeSound()
        {
            var shortArray = AudioDecode.Decode(rawData, predictor.order, predictor.predictorShort, predictor.nPredictors);

            byte[] byteArray = new byte[shortArray.Length * 2];
            byte[] tmp       = new byte[2];
            for (int i = 0; i < shortArray.Length; i++)
            {
                tmp = CGeneric.ConvertIntToByteArray16bits(shortArray[i]);
                byteArray[i * 2]     = tmp[1];
                byteArray[i * 2 + 1] = tmp[0];
            }
            return(byteArray);
        }
Exemple #5
0
        private int DecomposeSong()
        {
            int songTotalLength = 0;

            for (int i = 0; i < songDataAddress.Length; i += 8)
            {
                //starting address song0
                int songAddress = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(songDataAddress, i, 4));
                int songLength  = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(songDataAddress, i + 4, 4)) - songAddress;

                //grab the start address of song
                byte[] songRawData = CGeneric.GiveMeArray(rawData, songAddress - positionPtrStart, songLength);

                Song song = new Song(songRawData);
                songList.Add(song);
                songTotalLength += songLength;
            }
            return(songTotalLength);
        }
Exemple #6
0
        private byte[] GetWavHeader(int soundBank, int instrument, int lengthWave)
        {
            byte[] wavHeader = CGeneric.patternHeaderWavFile;

            int loopHeader = 0;

            if (loop.count > 0)
            {
                loopHeader = 0x18;
            }

            byte[] fileSize = CGeneric.ConvertIntToByteArray(0x4C + lengthWave + loopHeader);
            wavHeader[0x04] = fileSize[3];
            wavHeader[0x05] = fileSize[2];
            wavHeader[0x06] = fileSize[1];
            wavHeader[0x07] = fileSize[0];

            if (IsHalfSamplingRate(soundBank, instrument))
            {
                wavHeader[0x18] = 0x11;
                wavHeader[0x19] = 0x2B;
                wavHeader[0x1C] = 0x22;
                wavHeader[0x1D] = 0x56;
            }
            else
            {
                wavHeader[0x18] = 0x22;
                wavHeader[0x19] = 0x56;
                wavHeader[0x1C] = 0x44;
                wavHeader[0x1D] = 0xAC;
            }

            byte[] lengthFile = CGeneric.ConvertIntToByteArray(lengthWave);
            wavHeader[0x28] = lengthFile[3];
            wavHeader[0x29] = lengthFile[2];
            wavHeader[0x2A] = lengthFile[1];
            wavHeader[0x2B] = lengthFile[0];

            return(wavHeader);
        }
Exemple #7
0
        private byte[] GetWavBottom()
        {
            byte[] wavBottom = CGeneric.patternBottomWavFile;
            if (loop.count > 0)
            {
                wavBottom[0x4]  = 0x3C;
                wavBottom[0x24] = 0x01;

                var loopStartByte = CGeneric.ConvertIntToByteArray(loop.start);
                var loopEndByte   = CGeneric.ConvertIntToByteArray(loop.end);
                wavBottom[0x34] = loopStartByte[3];
                wavBottom[0x35] = loopStartByte[2];
                wavBottom[0x36] = loopStartByte[1];
                wavBottom[0x37] = loopStartByte[0];
                wavBottom[0x38] = loopEndByte[3];
                wavBottom[0x39] = loopEndByte[2];
                wavBottom[0x3A] = loopEndByte[1];
                wavBottom[0x3B] = loopEndByte[0];

                if (loop.count != -1)
                {
                    var loopCountByte = CGeneric.ConvertIntToByteArray(loop.count);
                    wavBottom[0x40] = loopCountByte[3];
                    wavBottom[0x41] = loopCountByte[2];
                    wavBottom[0x42] = loopCountByte[1];
                    wavBottom[0x43] = loopCountByte[0];
                }
            }
            else
            {
                wavBottom[0x4] = 0x24;
            }
            //keybase to add
            wavBottom[0x14] = 0x3C;



            return(wavBottom);
        }
Exemple #8
0
        //search for N64 PtrTable V2 for cutting soundbank
        private void ChunkSoundBank()
        {
            byte[] tmpRawDataN64PtrTable = new byte[16];

            //initialized to 16 to avoid first soundbank set to 0..
            int sizeOfSoundBank = 16;

            //searching N64PtrTableV2 pattern (each one will be stored in a soundbank)
            int position     = initialIndexAudioStart;
            int positionNext = 0;

            for (int i = 0; i <= 0x15; i++)
            {
                positionNext = CGeneric.SearchBytesInArray(rawData, CGeneric.patternN64PtrTableV2, 0, position + 16, 16);

                //if it's the last, don't search the next, just search the end of the rom
                if (positionNext == -1)
                {
                    positionNext = CGeneric.SearchBytesInArray(rawData, CGeneric.endOfRom, 0, position + 16, 16);
                }

                sizeOfSoundBank = positionNext - position;
                if (i == 0)//for the first soundBank, give
                {
                    byte[] startingEndingAddress = CGeneric.GiveMeArray(rawData, RomLangAddress.GetMidiSongSoundBank0(), 0x238);
                    soundBankList.Add(new SoundBank(CGeneric.GiveMeArray(rawData, position, sizeOfSoundBank), soundBankList.Count, position, startingEndingAddress));
                }
                else
                {
                    soundBankList.Add(new SoundBank(CGeneric.GiveMeArray(rawData, position, sizeOfSoundBank), soundBankList.Count));
                }

                position       += sizeOfSoundBank;
                sizeOfSoundBank = 16;
            }
        }
Exemple #9
0
        public void WriteAllData(FileStream fs)
        {
            //set 16bit alignment for first soundbank
            int alignment = 16 - ((int)fs.Position % 16);

            for (int i = 0; i < alignment; i++)
            {
                fs.WriteByte(0);
            }

            //update address of midi (SoundBank 0) by making the difference between old position and new position
            this.finalIndexAudioStart = (int)fs.Position;


            //Array.Copy(rawData, RomLangAddress.GetMidiSongSoundBank0(), addressHeaderSb0, 0, addressHeaderSb0.Length);

            //set the good position of song, and write to rom
            int valueToStore1 = 0;
            int lengthData    = 0;
            int adder         = 0;

            fs.Position = RomLangAddress.GetMidiSongSoundBank0();
            for (int i = 0; i < soundBankList[0].songList.Count; i++)
            {
                //finalindexaudiostart + ptrlength+wavedatalength
                valueToStore1 = finalIndexAudioStart + soundBankList[0].ptrTable.Length + soundBankList[0].waveTable.Length + adder;
                lengthData    = soundBankList[0].songList[i].rawData.Length;
                fs.Write(CGeneric.ConvertIntToByteArray(valueToStore1), 0, 4);
                fs.Write(CGeneric.ConvertIntToByteArray(valueToStore1 + lengthData), 0, 4);
                adder += lengthData;
            }

            /*for (int i = 0; i < addressHeaderSb0.Length; i += 4)
             * {
             *  int tmpValue = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(addressHeaderSb0, i, 4));
             *  if (finalIndexAudioStart > initialIndexAudioStart)
             *      tmpValue += finalIndexAudioStart - initialIndexAudioStart;
             *  else
             *      tmpValue -= initialIndexAudioStart - finalIndexAudioStart;
             *  byte[] tmpBytesNew = CGeneric.ConvertIntToByteArray(tmpValue);
             *  for(int j = 0; j < tmpBytesNew.Length; j++)
             *      addressHeaderSb0[i + j] = tmpBytesNew[j];
             *
             * }*/

            //write rawData soundBank
            fs.Position = finalIndexAudioStart;

            //write ptrData, waveTable, midi and sfx
            for (int i = 0; i <= 0x15; i++)
            {
                //write ptrData and update position
                soundBankList[i].address.PtrTable = CGeneric.ConvertIntToByteArray((int)fs.Position);
                fs.Write(soundBankList[i].ptrTable, 0, soundBankList[i].ptrTable.Length);

                //write waveTable and update position
                soundBankList[i].address.WaveTable = CGeneric.ConvertIntToByteArray((int)fs.Position);
                fs.Write(soundBankList[i].waveTable, 0, soundBankList[i].waveTable.Length);

                //write midi song and update sfx position ! (will only change the position of soundbank 1 and 2, the others doesn't have midi)
                soundBankList[i].address.Sfx = CGeneric.ConvertIntToByteArray((int)fs.Position);
                fs.Write(soundBankList[i].GetRawSongs() /*midi*/, 0, soundBankList[i].GetRawSongs().Length /*midi.Length*/);

                //write sfx and update position
                fs.Write(soundBankList[i].sfx, 0, soundBankList[i].sfx.Length);

                //write end position
                soundBankList[i].address.end = CGeneric.ConvertIntToByteArray((int)fs.Position);
            }

            long savedFsPosition = fs.Position;

            //update address in the header (first part)
            for (int i = 0; i <= 0x15; i++)
            {
                fs.Position = RomLangAddress.GetSoundBankPtrTable()[i];
                fs.Write(soundBankList[i].address.PtrTable, 0, 4);

                fs.Write(soundBankList[i].address.WaveTable, 0, 4);
                if (i == 0 || i == 2)
                {
                    if (i == 2)
                    {
                        fs.Position -= 0x38;
                        fs.Write(soundBankList[i].address.Sfx, 0, 4); // in fact, it's the start of midi
                        fs.Write(soundBankList[i].address.end, 0, 4); // and it's end here (and not the sfx)
                        fs.Position += 0x30;
                    }
                    byte[] nullBytes = new byte[4];
                    fs.Write(nullBytes, 0, 4);
                    fs.Write(nullBytes, 0, 4);
                }
                else
                {
                    fs.Write(soundBankList[i].address.Sfx, 0, 4);

                    //small hack.. weird part in the rom...
                    if (i != 1)
                    {
                        fs.Write(soundBankList[i].address.end, 0, 4);
                    }
                    else
                    {
                        int    oldValue = CGeneric.ConvertByteArrayToInt(soundBankList[i].address.end);
                        byte[] newValue = CGeneric.ConvertIntToByteArray(oldValue - 0x470);
                        fs.Write(newValue, 0, 4);
                    }
                }
                fs.Write(soundBankList[i].address.WaveTable, 0, 4);
            }

            //update address in the header(second part)
            for (int i = 4; i <= 0x14; i++)
            {
                fs.Position = RomLangAddress.GetSoundBankPtrTable()[i] + 0x168;
                fs.Write(soundBankList[i].address.PtrTable, 0, 4);
                fs.Write(soundBankList[i].address.WaveTable, 0, 4);
                fs.Write(soundBankList[i].address.Sfx, 0, 4);
                fs.Write(soundBankList[i].address.end, 0, 4);
                fs.Write(soundBankList[i].address.WaveTable, 0, 4);
            }

            fs.Position = savedFsPosition;
        }
Exemple #10
0
        //chunk RawData into PtrTable, WaveTable and Sfx
        private void ChunkRawData(int id)
        {
            //initialized to 16 to avoid first soundbank set to 0..
            int sizeOfPtrTable = 0;

            //searching waveTable (end of PtrTable) and write ptrTable rawData
            sizeOfPtrTable = CGeneric.SearchBytesInArray(rawData, CGeneric.patternN64WaveTable, 0, 16, 16);
            ptrTable       = CGeneric.GiveMeArray(rawData, 0, sizeOfPtrTable);

            //waveTable = CGeneric.GiveMeArray(rawData,ptrTable.Length,rawData.Length - ptrTable.Length);

            int sizeSfx  = 0;
            int sizeMidi = 0;

            //searching midi and sfx
            switch (id)
            {
            case 0:
                sizeMidi = DecomposeSong();
                break;

            //there is a midi song and sfx, so with a unknow wavetable length, we need to determine sfx and midi length..
            case 1:
                var startMidi = CGeneric.SearchBytesInArray(rawData, CGeneric.patternMidiSoundBank1, 0, 0, 16);
                sizeMidi = RomLangAddress.GetSizeMidiSoundBank1();
                sizeSfx  = rawData.Length - (startMidi + sizeMidi);
                break;

            //there is song but no sfx
            case 2:
                sizeMidi = RomLangAddress.GetSizeMidiSoundBank2();
                break;

            //standard computed sfx size and no midi file (dirty check, but seems working pretty well).
            default:
                int tmpSfxEqualValue;
                int tmpSfxEqualValue2;
                int tmpSfxEqualValue3;
                int tmpSfxNull;

                for (int i = ptrTable.Length; i < rawData.Length - 16; i += 16)
                {
                    //quick test, for avoiding cpu consuption
                    tmpSfxNull = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(rawData, i + 12, 4));
                    if (tmpSfxNull == 0)
                    {
                        tmpSfxEqualValue  = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(rawData, i, 4));
                        tmpSfxEqualValue2 = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(rawData, i + 4, 4));
                        tmpSfxEqualValue3 = CGeneric.ConvertByteArrayToInt(CGeneric.GiveMeArray(rawData, i + 8, 4));
                        var tmpSfxEqualValue4 = tmpSfxEqualValue3++;
                        if (tmpSfxEqualValue != 0 && tmpSfxEqualValue == tmpSfxEqualValue2 && (tmpSfxEqualValue2 == tmpSfxEqualValue4 || tmpSfxEqualValue2 == tmpSfxEqualValue3))
                        {
                            sizeSfx = rawData.Length - i;
                            break;
                        }
                    }
                }
                break;
            }

            //store date with size found previously
            waveTable = CGeneric.GiveMeArray(rawData, ptrTable.Length, rawData.Length - (ptrTable.Length + sizeMidi + sizeSfx));
            midi      = CGeneric.GiveMeArray(rawData, ptrTable.Length + waveTable.Length, sizeMidi);
            sfx       = CGeneric.GiveMeArray(rawData, ptrTable.Length + waveTable.Length + sizeMidi, sizeSfx);
        }