private void MoflexThreadMain(Object Args)
        {
            FileStream s = File.OpenRead((String)Args);
            var        d = new MoLiveDemux(s);//@"d:\Old\Temp\3DS Files\Moflex Audio\law_end(3d).moflex")));

            d.OnCompleteFrameReceived += new MoLiveDemux.CompleteFrameReceivedEventHandler(d_OnCompleteFrameReceived);
            bool left = false;

            while (!StopThread)
            {
                d.ReadPacket();
            }
            s.Close();
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            Console.WriteLine("MobiConverter by Gericom");
            Console.WriteLine();
            if (args.Length == 0)
            {
                PrintUsage();
                return;
            }
            switch (args[0])
            {
            case "-d":
            {
                if (args.Length != 2 && args.Length != 3)
                {
                    goto default;
                }
                if (!File.Exists(args[1]))
                {
                    Console.WriteLine("Error! File not found: " + args[1]);
                    return;
                }
                String outfile = (args.Length == 3) ? args[2] : Path.ChangeExtension(args[1], "avi");
                byte[] sig     = new byte[4];
                Stream s       = File.OpenRead(args[1]);
                s.Read(sig, 0, 4);
                s.Close();
                if (sig[0] == 0x4C && sig[1] == 0x32 && sig[2] == 0xAA && sig[3] == 0xAB)        //moflex
                {
                    Console.WriteLine("Moflex container detected!");
                    Console.Write("Converting: ");
                    Console.CursorVisible = false;
                    MobiclipDecoder    ddd   = null;
                    AviManager         m     = new AviManager(outfile, false);
                    MemoryStream       audio = null;
                    FastAudioDecoder[] mFastAudioDecoders = null;
                    int         audiorate          = -1;
                    int         audiochannels      = 0;
                    VideoStream vs                 = null;
                    FileStream  stream             = File.OpenRead(args[1]);
                    var         d                  = new MoLiveDemux(stream);
                    int         PlayingVideoStream = -1;
                    d.OnCompleteFrameReceived += delegate(MoLiveChunk Chunk, byte[] Data)
                    {
                        if ((Chunk is MoLiveStreamVideo || Chunk is MoLiveStreamVideoWithLayout) && ((PlayingVideoStream == -1) || ((MoLiveStream)Chunk).StreamIndex == PlayingVideoStream))
                        {
                            if (ddd == null)
                            {
                                ddd = new MobiclipDecoder(((MoLiveStreamVideo)Chunk).Width, ((MoLiveStreamVideo)Chunk).Height, MobiclipDecoder.MobiclipVersion.Moflex3DS);
                                PlayingVideoStream = ((MoLiveStream)Chunk).StreamIndex;
                            }
                            ddd.Data   = Data;
                            ddd.Offset = 0;
                            Bitmap b = ddd.DecodeFrame();
                            if (vs == null)
                            {
                                vs = m.AddVideoStream(false, Math.Round(((double)((MoLiveStreamVideo)Chunk).FpsRate) / ((double)((MoLiveStreamVideo)Chunk).FpsScale), 3), b);
                            }
                            else
                            {
                                vs.AddFrame(b);
                            }
                        }
                        else if (Chunk is MoLiveStreamAudio)
                        {
                            if (audio == null)
                            {
                                audio         = new MemoryStream();
                                audiochannels = (int)((MoLiveStreamAudio)Chunk).Channel;
                                audiorate     = (int)((MoLiveStreamAudio)Chunk).Frequency;
                            }
                            switch ((int)((MoLiveStreamAudio)Chunk).CodecId)
                            {
                            case 0:            //fastaudio
                            {
                                if (mFastAudioDecoders == null)
                                {
                                    mFastAudioDecoders = new FastAudioDecoder[(int)((MoLiveStreamAudio)Chunk).Channel];
                                    for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                                    {
                                        mFastAudioDecoders[i] = new FastAudioDecoder();
                                    }
                                }
                                List <short>[] channels = new List <short> [(int)((MoLiveStreamAudio)Chunk).Channel];
                                for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                                {
                                    channels[i] = new List <short>();
                                }

                                int offset = 0;
                                int size   = 40;
                                while (offset + size < Data.Length)
                                {
                                    for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                                    {
                                        mFastAudioDecoders[i].Data   = Data;
                                        mFastAudioDecoders[i].Offset = offset;
                                        channels[i].AddRange(mFastAudioDecoders[i].Decode());
                                        offset = mFastAudioDecoders[i].Offset;
                                    }
                                }
                                short[][] channelsresult = new short[(int)((MoLiveStreamAudio)Chunk).Channel][];
                                for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                                {
                                    channelsresult[i] = channels[i].ToArray();
                                }
                                byte[] result = InterleaveChannels(channelsresult);
                                audio.Write(result, 0, result.Length);
                            }
                            break;

                            case 1:            //IMA-ADPCM
                            {
                                IMAADPCMDecoder[] decoders = new IMAADPCMDecoder[(int)((MoLiveStreamAudio)Chunk).Channel];
                                List <short>[]    channels = new List <short> [(int)((MoLiveStreamAudio)Chunk).Channel];
                                for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                                {
                                    decoders[i] = new IMAADPCMDecoder();
                                    decoders[i].GetWaveData(Data, 4 * i, 4);
                                    channels[i] = new List <short>();
                                }

                                int offset = 4 * (int)((MoLiveStreamAudio)Chunk).Channel;
                                int size   = 128 * (int)((MoLiveStreamAudio)Chunk).Channel;
                                while (offset + size < Data.Length)
                                {
                                    for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                                    {
                                        channels[i].AddRange(decoders[i].GetWaveData(Data, offset, 128));
                                        offset += 128;
                                    }
                                }
                                short[][] channelsresult = new short[(int)((MoLiveStreamAudio)Chunk).Channel][];
                                for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                                {
                                    channelsresult[i] = channels[i].ToArray();
                                }
                                byte[] result = InterleaveChannels(channelsresult);
                                audio.Write(result, 0, result.Length);
                            }
                            break;

                            case 2:            //PCM16
                            {
                                audio.Write(Data, 0, Data.Length - (Data.Length % ((int)((MoLiveStreamAudio)Chunk).Channel * 2)));
                            }
                            break;
                            }
                        }
                    };
                    bool left    = false;
                    int  counter = 0;
                    while (true)
                    {
                        uint error = d.ReadPacket();
                        if (error == 73)
                        {
                            break;
                        }
                        //report progress
                        if (counter == 0)
                        {
                            Console.Write("{0,3:D}%", stream.Position * 100 / stream.Length);
                            Console.CursorLeft -= 4;
                        }
                        counter++;
                        if (counter == 50)
                        {
                            counter = 0;
                        }
                    }
                    if (audio != null)
                    {
                        byte[] adata = audio.ToArray();
                        audio.Close();
                        var sinfo = new Avi.AVISTREAMINFO();
                        sinfo.fccType      = Avi.streamtypeAUDIO;
                        sinfo.dwScale      = audiochannels * 2;
                        sinfo.dwRate       = audiorate * audiochannels * 2;
                        sinfo.dwSampleSize = audiochannels * 2;
                        sinfo.dwQuality    = -1;
                        var sinfo2 = new Avi.PCMWAVEFORMAT();
                        sinfo2.wFormatTag      = 1;
                        sinfo2.nChannels       = (short)audiochannels;
                        sinfo2.nSamplesPerSec  = audiorate;
                        sinfo2.nAvgBytesPerSec = audiorate * audiochannels * 2;
                        sinfo2.nBlockAlign     = (short)(audiochannels * 2);
                        sinfo2.wBitsPerSample  = 16;
                        unsafe
                        {
                            fixed(byte *pAData = &adata[0])
                            {
                                m.AddAudioStream((IntPtr)pAData, sinfo, sinfo2, adata.Length);
                            }
                        }
                    }
                    m.Close();
                    stream.Close();
                    Console.WriteLine("Done!");
                    Console.CursorVisible = true;
                }
                else if (sig[0] == 0x4D && sig[1] == 0x4F && sig[2] == 0x44 && sig[3] == 0x53)
                {
                    //mods
                    Console.WriteLine("Mods container detected!");
                    Console.Write("Converting: ");
                    Console.CursorVisible = false;
                    AviManager   m      = new AviManager(outfile, false);
                    FileStream   stream = File.OpenRead(args[1]);
                    ModsDemuxer  dm     = new ModsDemuxer(stream);
                    MemoryStream audio  = null;
                    if ((dm.Header.AudioCodec == 1 || dm.Header.AudioCodec == 3) && dm.Header.NbChannel > 0 && dm.Header.Frequency > 0)
                    {
                        audio = new MemoryStream();
                    }
                    MobiclipDecoder    d          = new MobiclipDecoder(dm.Header.Width, dm.Header.Height, MobiclipDecoder.MobiclipVersion.ModsDS);
                    VideoStream        vs         = null;
                    int                CurChannel = 0;
                    List <short>[]     channels   = new List <short> [dm.Header.NbChannel];
                    IMAADPCMDecoder[]  decoders   = new IMAADPCMDecoder[dm.Header.NbChannel];
                    SxDecoder[]        sxd        = new SxDecoder[dm.Header.NbChannel];
                    FastAudioDecoder[] fad        = new FastAudioDecoder[dm.Header.NbChannel];
                    bool[]             isinit     = new bool[dm.Header.NbChannel];
                    for (int i = 0; i < dm.Header.NbChannel; i++)
                    {
                        channels[i] = new List <short>();
                        decoders[i] = new IMAADPCMDecoder();
                        sxd[i]      = new SxDecoder();
                        fad[i]      = new FastAudioDecoder();
                        isinit[i]   = false;
                    }
                    int counter = 0;
                    while (true)
                    {
                        uint   NrAudioPackets;
                        bool   IsKeyFrame;
                        byte[] framedata = dm.ReadFrame(out NrAudioPackets, out IsKeyFrame);
                        if (framedata == null)
                        {
                            break;
                        }
                        d.Data   = framedata;
                        d.Offset = 0;
                        Bitmap b = d.DecodeFrame();
                        if (vs == null)
                        {
                            vs = m.AddVideoStream(false, Math.Round(dm.Header.Fps / (double)0x01000000, 3), b);
                        }
                        else
                        {
                            vs.AddFrame(b);
                        }
                        if (NrAudioPackets > 0 && audio != null)
                        {
                            int Offset = d.Offset - 2;
                            if (dm.Header.TagId == 0x334E && (IOUtil.ReadU16LE(framedata, 0) & 0x8000) != 0)
                            {
                                Offset += 4;
                            }
                            if (dm.Header.AudioCodec == 3)
                            {
                                if (IsKeyFrame)
                                {
                                    for (int i = 0; i < dm.Header.NbChannel; i++)
                                    {
                                        channels[i] = new List <short>();
                                        decoders[i] = new IMAADPCMDecoder();
                                        sxd[i]      = new SxDecoder();
                                        fad[i]      = new FastAudioDecoder();
                                        isinit[i]   = false;
                                    }
                                }
                                for (int i = 0; i < NrAudioPackets; i++)
                                {
                                    channels[CurChannel].AddRange(decoders[CurChannel].GetWaveData(framedata, Offset, 128 + (!isinit[CurChannel] ? 4 : 0)));
                                    Offset            += 128 + (!isinit[CurChannel] ? 4 : 0);
                                    isinit[CurChannel] = true;
                                    CurChannel++;
                                    if (CurChannel >= dm.Header.NbChannel)
                                    {
                                        CurChannel = 0;
                                    }
                                }
                            }
                            else if (dm.Header.AudioCodec == 1)
                            {
                                for (int i = 0; i < NrAudioPackets; i++)
                                {
                                    if (!isinit[CurChannel])
                                    {
                                        sxd[CurChannel].Codebook = dm.AudioCodebooks[CurChannel];
                                    }
                                    isinit[CurChannel]     = true;
                                    sxd[CurChannel].Data   = framedata;
                                    sxd[CurChannel].Offset = Offset;
                                    channels[CurChannel].AddRange(sxd[CurChannel].Decode());
                                    Offset = sxd[CurChannel].Offset;
                                    CurChannel++;
                                    if (CurChannel >= dm.Header.NbChannel)
                                    {
                                        CurChannel = 0;
                                    }
                                }
                            }
                            else if (dm.Header.AudioCodec == 2)
                            {
                                for (int i = 0; i < NrAudioPackets; i++)
                                {
                                    fad[CurChannel].Data   = framedata;
                                    fad[CurChannel].Offset = Offset;
                                    channels[CurChannel].AddRange(fad[CurChannel].Decode());
                                    Offset = fad[CurChannel].Offset;
                                    CurChannel++;
                                    if (CurChannel >= dm.Header.NbChannel)
                                    {
                                        CurChannel = 0;
                                    }
                                }
                            }
                            int smallest = int.MaxValue;
                            for (int i = 0; i < dm.Header.NbChannel; i++)
                            {
                                if (channels[i].Count < smallest)
                                {
                                    smallest = channels[i].Count;
                                }
                            }
                            if (smallest > 0)
                            {
                                //Gather samples
                                short[][] samps = new short[dm.Header.NbChannel][];
                                for (int i = 0; i < dm.Header.NbChannel; i++)
                                {
                                    samps[i] = new short[smallest];
                                    channels[i].CopyTo(0, samps[i], 0, smallest);
                                    channels[i].RemoveRange(0, smallest);
                                }
                                byte[] result = InterleaveChannels(samps);
                                audio.Write(result, 0, result.Length);
                            }
                        }
                        //report progress
                        if (counter == 0)
                        {
                            Console.Write("{0,3:D}%", stream.Position * 100 / stream.Length);
                            Console.CursorLeft -= 4;
                        }
                        counter++;
                        if (counter == 50)
                        {
                            counter = 0;
                        }
                    }
                    if (audio != null)
                    {
                        byte[] adata = audio.ToArray();
                        audio.Close();
                        var sinfo = new Avi.AVISTREAMINFO();
                        sinfo.fccType      = Avi.streamtypeAUDIO;
                        sinfo.dwScale      = dm.Header.NbChannel * 2;
                        sinfo.dwRate       = (int)dm.Header.Frequency * dm.Header.NbChannel * 2;
                        sinfo.dwSampleSize = dm.Header.NbChannel * 2;
                        sinfo.dwQuality    = -1;
                        var sinfo2 = new Avi.PCMWAVEFORMAT();
                        sinfo2.wFormatTag      = 1;
                        sinfo2.nChannels       = (short)dm.Header.NbChannel;
                        sinfo2.nSamplesPerSec  = (int)dm.Header.Frequency;
                        sinfo2.nAvgBytesPerSec = (int)dm.Header.Frequency * dm.Header.NbChannel * 2;
                        sinfo2.nBlockAlign     = (short)(dm.Header.NbChannel * 2);
                        sinfo2.wBitsPerSample  = 16;
                        unsafe
                        {
                            fixed(byte *pAData = &adata[0])
                            {
                                m.AddAudioStream((IntPtr)pAData, sinfo, sinfo2, adata.Length);
                            }
                        }
                    }
                    m.Close();
                    stream.Close();
                    Console.WriteLine("Done!");
                    Console.CursorVisible = true;
                    return;
                }
                else if (sig[0] == 0x4D && sig[1] == 0x4F && sig[2] == 0x43 && sig[3] == 0x35)
                {
                    //moc5
                    Console.WriteLine("MOC5 container detected!");
                    Console.WriteLine("Error! Not supported yet!");
                    return;
                }
                else if (Path.GetExtension(args[1]).ToLower() == ".vx2")
                {
                    //mods
                    Console.WriteLine("VX2 container detected!");
                    Console.Write("Converting: ");
                    Console.CursorVisible = false;
                    AviManager      m         = new AviManager(outfile, false);
                    FileStream      fs        = File.OpenRead(args[1]);
                    MemoryStream    audio     = new MemoryStream();
                    MobiclipDecoder d         = new MobiclipDecoder(256, 192, MobiclipDecoder.MobiclipVersion.Moflex3DS);
                    VideoStream     vs        = null;
                    int             framerate = 20;
                    int             counter   = 0;
                    int             frame     = 0;
                    while (true)
                    {
                        if (fs.Position >= fs.Length)
                        {
                            break;
                        }
                        if ((frame % framerate) == 0)        //Audio
                        {
                            byte[] adata = new byte[32768 * 2];
                            fs.Read(adata, 0, 32768 * 2);
                            audio.Write(adata, 0, adata.Length);
                        }
                        int    length = (fs.ReadByte() << 0) | (fs.ReadByte() << 8) | (fs.ReadByte() << 16) | (fs.ReadByte() << 24);
                        byte[] data   = new byte[length];
                        fs.Read(data, 0, length);
                        d.Data   = data;
                        d.Offset = 0;
                        Bitmap b = d.DecodeFrame();
                        if (vs == null)
                        {
                            vs = m.AddVideoStream(false, framerate, b);
                        }
                        else
                        {
                            vs.AddFrame(b);
                        }
                        frame++;
                        //report progress
                        if (counter == 0)
                        {
                            Console.Write("{0,3:D}%", fs.Position * 100 / fs.Length);
                            Console.CursorLeft -= 4;
                        }
                        counter++;
                        if (counter == 50)
                        {
                            counter = 0;
                        }
                    }
                    if (audio != null)
                    {
                        byte[] adata = audio.ToArray();
                        audio.Close();
                        var sinfo = new Avi.AVISTREAMINFO();
                        sinfo.fccType      = Avi.streamtypeAUDIO;
                        sinfo.dwScale      = 1 * 2;
                        sinfo.dwRate       = (int)32768 * 1 * 2;
                        sinfo.dwSampleSize = 1 * 2;
                        sinfo.dwQuality    = -1;
                        var sinfo2 = new Avi.PCMWAVEFORMAT();
                        sinfo2.wFormatTag      = 1;
                        sinfo2.nChannels       = (short)1;
                        sinfo2.nSamplesPerSec  = (int)32768;
                        sinfo2.nAvgBytesPerSec = (int)32768 * 1 * 2;
                        sinfo2.nBlockAlign     = (short)(1 * 2);
                        sinfo2.wBitsPerSample  = 16;
                        unsafe
                        {
                            fixed(byte *pAData = &adata[0])
                            {
                                m.AddAudioStream((IntPtr)pAData, sinfo, sinfo2, adata.Length);
                            }
                        }
                    }
                    m.Close();
                    fs.Close();
                    Console.WriteLine("Done!");
                    Console.CursorVisible = true;
                    return;
                }
                else
                {
                    Console.WriteLine("Error! Unrecognized format!");
                    return;
                }
                break;
            }

            case "-e":
            {
                break;
            }

            default:
            case "-h":
                PrintUsage();
                return;
            }
        }
Beispiel #3
0
    public static void Process(string srcfile, string outDir, out double fps)
    {
        MobiclipDecoder decoder = null;
        MemoryStream    audio   = null;

        FastAudioDecoder[] mFastAudioDecoders = null;
        int audiorate     = -1;
        int audiochannels = 0;
        //VideoStream vs = null;
        FileStream stream             = File.OpenRead(srcfile);
        var        d                  = new MoLiveDemux(stream);
        int        PlayingVideoStream = -1;

        int frameCount = 0; double finalFps = 0;

        d.OnCompleteFrameReceived += delegate(MoLiveChunk Chunk, byte[] Data)
        {
            if ((Chunk is MoLiveStreamVideo || Chunk is MoLiveStreamVideoWithLayout) && ((PlayingVideoStream == -1) || ((MoLiveStream)Chunk).StreamIndex == PlayingVideoStream))
            {
                if (decoder == null)
                {
                    decoder            = new MobiclipDecoder(((MoLiveStreamVideo)Chunk).Width, ((MoLiveStreamVideo)Chunk).Height, MobiclipDecoder.MobiclipVersion.Moflex3DS);
                    PlayingVideoStream = ((MoLiveStream)Chunk).StreamIndex;
                }
                decoder.Data   = Data;
                decoder.Offset = 0;
                Bitmap b = decoder.DecodeFrame();
                b.Save(outDir + "frame" + Util.NumToNo(frameCount, 8) + ".png", ImageFormat.Png);
                frameCount++;
                finalFps = (double)((MoLiveStreamVideo)Chunk).FpsRate / ((double)((MoLiveStreamVideo)Chunk).FpsScale);
            }
            else if (Chunk is MoLiveStreamAudio)
            {
                if (audio == null)
                {
                    audio         = new MemoryStream();
                    audiochannels = (int)((MoLiveStreamAudio)Chunk).Channel;
                    audiorate     = (int)((MoLiveStreamAudio)Chunk).Frequency;
                }
                switch ((int)((MoLiveStreamAudio)Chunk).CodecId)
                {
                case 0:    //fastaudio
                {
                    if (mFastAudioDecoders == null)
                    {
                        mFastAudioDecoders = new FastAudioDecoder[(int)((MoLiveStreamAudio)Chunk).Channel];
                        for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                        {
                            mFastAudioDecoders[i] = new FastAudioDecoder();
                        }
                    }
                    List <short>[] channels = new List <short> [(int)((MoLiveStreamAudio)Chunk).Channel];
                    for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                    {
                        channels[i] = new List <short>();
                    }

                    int offset = 0;
                    int size   = 40;
                    while (offset + size < Data.Length)
                    {
                        for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                        {
                            mFastAudioDecoders[i].Data   = Data;
                            mFastAudioDecoders[i].Offset = offset;
                            channels[i].AddRange(mFastAudioDecoders[i].Decode());
                            offset = mFastAudioDecoders[i].Offset;
                        }
                    }
                    short[][] channelsresult = new short[(int)((MoLiveStreamAudio)Chunk).Channel][];
                    for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                    {
                        channelsresult[i] = channels[i].ToArray();
                    }
                    byte[] result = InterleaveChannels(channelsresult);
                    audio.Write(result, 0, result.Length);
                }
                break;

                case 1:    //IMA-ADPCM
                {
                    IMAADPCMDecoder[] decoders = new IMAADPCMDecoder[(int)((MoLiveStreamAudio)Chunk).Channel];
                    List <short>[]    channels = new List <short> [(int)((MoLiveStreamAudio)Chunk).Channel];
                    for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                    {
                        decoders[i] = new IMAADPCMDecoder();
                        decoders[i].GetWaveData(Data, 4 * i, 4);
                        channels[i] = new List <short>();
                    }

                    int offset = 4 * (int)((MoLiveStreamAudio)Chunk).Channel;
                    int size   = 128 * (int)((MoLiveStreamAudio)Chunk).Channel;
                    while (offset + size < Data.Length)
                    {
                        for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                        {
                            channels[i].AddRange(decoders[i].GetWaveData(Data, offset, 128));
                            offset += 128;
                        }
                    }
                    short[][] channelsresult = new short[(int)((MoLiveStreamAudio)Chunk).Channel][];
                    for (int i = 0; i < (int)((MoLiveStreamAudio)Chunk).Channel; i++)
                    {
                        channelsresult[i] = channels[i].ToArray();
                    }
                    byte[] result = InterleaveChannels(channelsresult);
                    audio.Write(result, 0, result.Length);
                }
                break;

                case 2:    //PCM16
                {
                    audio.Write(Data, 0, Data.Length - (Data.Length % ((int)((MoLiveStreamAudio)Chunk).Channel * 2)));
                }
                break;
                }
            }
        };

        int counter = 0;

        while (true)
        {
            uint error = d.ReadPacket();
            if (error == 73)
            {
                break;
            }

            counter++;
            if (counter == 50)
            {
                counter = 0;
            }
        }
        if (audio != null)
        {
            //Write WAV
            byte[] adata = audio.ToArray();
            audio.Close();
            byte[] head = new byte[0x2C + adata.Length];

            new byte[] { (byte)'R', (byte)'I', (byte)'F', (byte)'F' }.CopyTo(head, 0x0);
            BitConverter.GetBytes((Int32)(0x2C - 8 + adata.Length)).CopyTo(head, 0x4);
            new byte[] { (byte)'W', (byte)'A', (byte)'V', (byte)'E' }.CopyTo(head, 0x8);
            new byte[] { (byte)'f', (byte)'m', (byte)'t', 0x20 }.CopyTo(head, 0xC);
            BitConverter.GetBytes((Int32)0x10).CopyTo(head, 0x10);
            BitConverter.GetBytes((Int16)0x1).CopyTo(head, 0x14);
            head[0x16] = (byte)audiochannels;
            BitConverter.GetBytes((Int32)audiorate).CopyTo(head, 0x18);
            BitConverter.GetBytes((Int32)(audiorate * audiochannels * 2)).CopyTo(head, 0x1C);
            BitConverter.GetBytes((Int16)(audiochannels * 2)).CopyTo(head, 0x20);
            head[0x22] = 16;
            new byte[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a' }.CopyTo(head, 0x24);
            BitConverter.GetBytes((Int32)(adata.Length)).CopyTo(head, 0x28);
            adata.CopyTo(head, 0x2C);
            File.WriteAllBytes(outDir + "audio.wav", head);
        }
        stream.Close();
        fps = finalFps;
        Console.WriteLine("FPS:" + finalFps);
    }