Пример #1
0
        private static int WriteVideoStreamHeader(RiffWriter rw, VideoStreamInfo vsi)
        {
            rw.BeginChunk(AviDemux.ID_strh);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write(AviDemux.FCC_vids);
            bw.Write(vsi.codecFourCC);
            bw.Write((int)0);              // dwFlags
            bw.Write((short)0);            // wPriority
            bw.Write((short)0);            // wLanguage
            bw.Write((int)0);              // dwInitialFrames
            int scale, rate;

            FindScaleAndRate(out scale, out rate, vsi.framerate);
            bw.Write(scale);             // dwScale
            bw.Write(rate);              // dwRate
            bw.Write((int)0);            // dwStart
            bw.Write(vsi.frameCount);    // dwLength. that's how many frames will be in this RIFF element, written over later
            bw.Write((int)0);            // dwSuggestedBufferSize, not suggesting any value
            bw.Write((int)-1);           // dwQuality = -1 meaning "default quality"
            bw.Write((int)0);            // dwSampleSize = 0 for video
            bw.Write((short)0);
            bw.Write((short)0);
            bw.Write((short)vsi.width);
            bw.Write((short)vsi.height);
            rw.EndChunk();
            return(offset);
        }
Пример #2
0
        private static int WriteDmlhHeader(RiffWriter rw, int totalFrames)
        {
            rw.BeginChunk(AviDemux.ID_dmlh);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);

            rw.binaryWriter.Write(totalFrames);              // will be written over later
            rw.EndChunk();
            return(offset);
        }
Пример #3
0
        public override void Init(Stream dstStream, VideoStreamInfo videoStreamInfo, AudioStreamInfo audioStreamInfo)
        {
            if (dstStream == null || videoStreamInfo == null)
            {
                throw new ArgumentException("At least destination stream and video stream info is needed");
            }
            base.Init(dstStream, videoStreamInfo, audioStreamInfo);

            usingMultipleRiffs = false;
            totalFramesOld     = 0;
            totalFrames        = 0;
            totalSamples       = 0;

            writer = new RiffWriter(dstStream);
            writer.BeginRiff(AviDemux.ID_AVI_);
            writer.BeginList(AviDemux.ID_hdrl);

            // main header
            offsets.avih = WriteMainHeader(writer, videoStreamInfo, hasAudioStream);

            // video stream header
            writer.BeginList(AviDemux.ID_strl);
            offsets.videoStrh = WriteVideoStreamHeader(writer, videoStreamInfo);
            WriteVideoFormatHeader(writer, videoStreamInfo);
            offsets.videoIndx         = WriteDummySuperIndex(writer, AviDemux.ID_00dc, maxSuperindexEntries);
            videoSuperIndexEntryCount = 0;
            writer.EndList();              // end of strl

            videoIndex          = new AviStreamIndex();
            videoIndex.streamId = AviDemux.ID_00dc;

            if (hasAudioStream)
            {
                // audio stream header
                writer.BeginList(AviDemux.ID_strl);
                offsets.audioStrh = WriteAudioStreamHeader(writer, audioStreamInfo);
                WriteAudioFormatHeader(writer, audioStreamInfo);
                offsets.audioIndx         = WriteDummySuperIndex(writer, AviDemux.ID_01wb, maxSuperindexEntries);
                audioSuperIndexEntryCount = 0;
                writer.EndList();                  // end of strl

                audioIndex          = new AviStreamIndex();
                audioIndex.streamId = AviDemux.ID_01wb;
            }

            // odml header
            writer.BeginList(AviDemux.ID_odml);
            offsets.dmlh = WriteDmlhHeader(writer, videoStreamInfo.frameCount);
            writer.EndList();

            writer.EndList();              // end of hdrl

            writer.BeginList(AviDemux.ID_movi);
            offsets.indexBase = writer.binaryWriter.Seek(0, SeekOrigin.Current);
        }
Пример #4
0
        public override void Init(Stream dstStream, VideoStreamInfo videoStreamInfo, AudioStreamInfo audioStreamInfo)
        {
            if (dstStream == null || videoStreamInfo == null) {
                throw new ArgumentException ("At least destination stream and video stream info is needed");
            }
            base.Init (dstStream, videoStreamInfo, audioStreamInfo);

            usingMultipleRiffs = false;
            totalFramesOld = 0;
            totalFrames = 0;
            totalSamples = 0;

            writer = new RiffWriter (dstStream);
            writer.BeginRiff (AviDemux.ID_AVI_);
            writer.BeginList (AviDemux.ID_hdrl);

            // main header
            offsets.avih = WriteMainHeader (writer, videoStreamInfo, hasAudioStream);

            // video stream header
            writer.BeginList (AviDemux.ID_strl);
            offsets.videoStrh = WriteVideoStreamHeader (writer, videoStreamInfo);
            WriteVideoFormatHeader (writer, videoStreamInfo);
            offsets.videoIndx = WriteDummySuperIndex (writer, AviDemux.ID_00dc, maxSuperindexEntries);
            videoSuperIndexEntryCount = 0;
            writer.EndList (); // end of strl

            videoIndex = new AviStreamIndex ();
            videoIndex.streamId = AviDemux.ID_00dc;

            if (hasAudioStream) {
                // audio stream header
                writer.BeginList (AviDemux.ID_strl);
                offsets.audioStrh = WriteAudioStreamHeader (writer, audioStreamInfo);
                WriteAudioFormatHeader (writer, audioStreamInfo);
                offsets.audioIndx = WriteDummySuperIndex (writer, AviDemux.ID_01wb, maxSuperindexEntries);
                audioSuperIndexEntryCount = 0;
                writer.EndList (); // end of strl

                audioIndex = new AviStreamIndex ();
                audioIndex.streamId = AviDemux.ID_01wb;
            }

            // odml header
            writer.BeginList (AviDemux.ID_odml);
            offsets.dmlh = WriteDmlhHeader (writer, videoStreamInfo.frameCount);
            writer.EndList ();

            writer.EndList (); // end of hdrl

            writer.BeginList (AviDemux.ID_movi);
            offsets.indexBase = writer.binaryWriter.Seek (0, SeekOrigin.Current);
        }
Пример #5
0
        private static void WriteChunkIndex(RiffWriter rw, AviStreamIndex index, int superIndexChunkOffset, ref int superIndexEntryCount, long indexBaseOffset, int maxSuperindexEntries)
        {
            var bw = rw.binaryWriter;

            // the offset where this index will be written
            long streamIndexOffset = bw.Seek(0, SeekOrigin.Current);

            // update stream superindex
            superIndexEntryCount++;
            if (superIndexEntryCount > maxSuperindexEntries)
            {
                throw new MpException("Not enough space was reserved for superindex. Please increase maxSuperindexEntries");
            }

            bw.Seek(superIndexChunkOffset + 1 * 4, SeekOrigin.Begin);
            bw.Write(superIndexEntryCount);              // overwrite nEntriesInUse
            bw.Seek(superIndexChunkOffset + 6 * 4 + (superIndexEntryCount - 1) * 16, SeekOrigin.Begin);
            bw.Write(streamIndexOffset);
            bw.Write(32 + 8 * index.entries.Count);     // dwSize
            bw.Write(index.entries.Count);              // dwDuration in stream ticks. @todo this is OK only for video, for audio stream this should be ???

            // write stream chunk index
            // @xxx MSDN suggests not seeking BaseStream when using BinaryWriter, but there are no Seek(long)
            //      in BinaryWriter. According to this forum post, BinaryWriter.Seek is just a wrapper
            //      to BinaryWriter.BaseStream.Seek, so all should be ok.
            //      http://www.pcreview.co.uk/forums/binarywriter-seek-vs-binarywriter-basestream-seek-t1223754.html
            bw.BaseStream.Seek(streamIndexOffset, SeekOrigin.Begin);

            rw.BeginChunk((RiffParser.ToFourCC("ix__") & 0x0000FFFF) | ((index.streamId << 16) & 0xFFFF0000));
            bw.Write((short)2);                         // wLongsPerEntry is always 2 here
            bw.Write((byte)0);                          // bIndexSubType is always 0 here
            bw.Write((byte)AviStreamIndex.Type.CHUNKS); // bIndexType = AVI_INDEX_OF_CHUNKS
            bw.Write(index.entries.Count);              // nEntriesInUse.
            bw.Write(index.streamId);                   // dwChunkId ("##dc" and similar)
            bw.Write(indexBaseOffset);                  // qwBaseOffset
            bw.Write((int)0);                           // dwReserved3

            foreach (var entry in index.entries)
            {
                long offset = entry.chunkOffset - indexBaseOffset;
                if (offset > int.MaxValue)
                {
                    throw new MpException("Internal error. Can't write index, because chunk offset won't fit into 31 bits: " + offset);
                }
                bw.Write((uint)offset);                  // bit31==0 indicating that this is a keyframe
                bw.Write(entry.chunkLength);
            }
            rw.EndChunk();

            index.globalOffset += index.entries.Count;
            index.entries.Clear();
        }
Пример #6
0
        /// <summary>
        /// Write the RIFF.
        /// </summary>
        /// <param name="w">The writer.</param>
        public override void Write(FileWriter w)
        {
            //Init.
            using (RiffWriter rw = new RiffWriter(w.BaseStream)) {
                //Init file.
                rw.InitFile("WAVE");

                //Format block.
                rw.StartChunk("fmt ");
                rw.Write((ushort)1);
                rw.Write((ushort)Audio.Channels.Count);
                rw.Write(SampleRate);
                uint bitsPerSample = Audio.EncodingType.Equals(typeof(PCM16)) ? 16u : 8u;
                rw.Write((uint)(SampleRate * Audio.Channels.Count * (bitsPerSample / 8)));
                rw.Write((ushort)(bitsPerSample / 8 * Audio.Channels.Count));
                rw.Write((ushort)bitsPerSample);
                rw.EndChunk();

                //Sample block.
                if (Loops)
                {
                    rw.StartChunk("smpl");
                    rw.Write(new uint[2]);
                    rw.Write((uint)(1d / SampleRate * 1000000000));
                    rw.Write((uint)60);
                    rw.Write(new uint[3]);
                    rw.Write((uint)1);
                    rw.Write(new uint[3]);
                    rw.Write(LoopStart /* * bitsPerSample / 8*/);
                    rw.Write(LoopEnd /* * bitsPerSample / 8*/);
                    rw.Write((ulong)0);
                    rw.EndChunk();
                }

                //Data block.
                Audio.ChangeBlockSize((int)bitsPerSample / 8);
                rw.StartChunk("data");
                w.Position = rw.Position;
                Audio.Write(w);
                rw.Position = w.Position;
                while (rw.Position % 2 != 0)
                {
                    rw.Write((byte)0);
                }
                rw.EndChunk();

                //Close file.
                rw.CloseFile();
                Audio.ChangeBlockSize(-1);
            }
        }
Пример #7
0
        private static void WriteAudioFormatHeader(RiffWriter rw, AudioStreamInfo asi)
        {
            rw.BeginChunk(AviDemux.ID_strf);
            var bw = rw.binaryWriter;

            bw.Write((ushort)asi.audioFormat);                        // wFormatTag
            bw.Write((short)asi.channels);                            // nChannels
            bw.Write(asi.sampleRate);                                 // nSamplesPerSec
            bw.Write(asi.sampleRate * asi.sampleSize * asi.channels); // nAvgBytesPerSec @xxx true for PCM audio only, but this is a "soft" property
            bw.Write((short)asi.sampleSize);                          // nBlockAlign
            bw.Write((short)(8 * asi.sampleSize / asi.channels));     // wBitsPerSample
            bw.Write((short)0);                                       // cbSize. no extra coded info
            rw.EndChunk();
        }
Пример #8
0
        private static int WriteDummySuperIndex(RiffWriter rw, uint streamId, int entriesToReserve)
        {
            rw.BeginChunk(AviDemux.ID_indx);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write((short)4);                             // wLongsPerEntry is always 4 for super index
            bw.Write((byte)0);                              // bIndexSubType is always 0 for super index
            bw.Write((byte)AviStreamIndex.Type.SUPERINDEX); // bIndexType = AVI_INDEX_OF_INDEXES
            bw.Write((int)0);                               // nEntriesInUse. this'll be updated later!
            bw.Write(streamId);                             // dwChunkId ("##dc" and similar)
            // write 3 reserved UINTs and reserve some space for entries
            bw.Write(new byte[4 * 3 + entriesToReserve * 16]);
            rw.EndChunk();
            return(offset);
        }
Пример #9
0
        private static void WriteVideoFormatHeader(RiffWriter rw, VideoStreamInfo vsi)
        {
            rw.BeginChunk(AviDemux.ID_strf);
            var bw = rw.binaryWriter;

            bw.Write((int)40);                                       // biSize
            bw.Write(vsi.width);                                     // biWidth
            bw.Write(vsi.height);                                    // biHeight
            bw.Write((short)1);                                      // biPlanes
            bw.Write((short)vsi.bitsPerPixel);
            bw.Write(vsi.codecFourCC);                               // biCompression
            bw.Write(vsi.width * vsi.height * vsi.bitsPerPixel / 8); // biSizeImage
            bw.Write((int)0);                                        // biXPelsPerMeter
            bw.Write((int)0);                                        // biYPelsPerMeter
            bw.Write((int)0);                                        // biClrUsed
            bw.Write((int)0);                                        // biClrImportant
            rw.EndChunk();
        }
Пример #10
0
        private static int WriteMainHeader(RiffWriter rw, VideoStreamInfo vsi, bool hasAudioStream)
        {
            rw.BeginChunk(AviDemux.ID_avih);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write(Mathf.RoundToInt(1000000f / vsi.framerate));                           // swMicroSecPerFrame
            bw.Write((int)0);                                                               // dwMaxBytesPerSec
            bw.Write((int)0);                                                               // dwPaddingGranularity
            bw.Write((int)(AVIMainHeader.AVIF_HASINDEX | AVIMainHeader.AVIF_MUSTUSEINDEX)); // dwFlags. Maybe use AVIMainHeader.AVIF_MUSTUSEINDEX too?
            bw.Write(vsi.frameCount);                                                       // dwTotalFrames. this will be written over later!
            bw.Write((int)0);                                                               // dwInitialFrames
            bw.Write(hasAudioStream ? 2 : 1);
            bw.Write((int)0);                                                               // dwSuggestedBufferSize, not suggesting any value
            bw.Write(vsi.width);
            bw.Write(vsi.height);
            bw.Write((long)0);              // dwReserver0 and dwReserver1
            bw.Write((long)0);              // dwReserver2 and dwReserver3
            rw.EndChunk();
            return(offset);
        }
Пример #11
0
        private static int WriteAudioStreamHeader(RiffWriter rw, AudioStreamInfo asi)
        {
            rw.BeginChunk(AviDemux.ID_strh);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write(AviDemux.FCC_auds);
            bw.Write(asi.codecFourCC);
            bw.Write((int)0);              // dwFlags
            bw.Write((short)0);            // wPriority
            bw.Write((short)0);            // wLanguage
            bw.Write((int)0);              // dwInitialFrames
            bw.Write((int)1);              // dwScale
            bw.Write(asi.sampleRate);      // dwRate @xxx This is true for PCM audio only!
            bw.Write((int)0);              // dwStart
            bw.Write(asi.sampleCount);     // dwLength. will be written over later
            bw.Write((int)0);              // dwSuggestedBufferSize, not suggesting it
            bw.Write((int)-1);             // dwQuality = -1 meaning "default quality"
            bw.Write(asi.sampleSize);      // dwSampleSize
            bw.Write((long)0);             // rcFrame
            rw.EndChunk();
            return(offset);
        }
Пример #12
0
 private static int WriteAudioStreamHeader(RiffWriter rw, AudioStreamInfo asi)
 {
     rw.BeginChunk (AviDemux.ID_strh);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write (AviDemux.FCC_auds);
     bw.Write (asi.codecFourCC);
     bw.Write ((int)0); // dwFlags
     bw.Write ((short)0); // wPriority
     bw.Write ((short)0); // wLanguage
     bw.Write ((int)0); // dwInitialFrames
     bw.Write ((int)1); // dwScale
     bw.Write (asi.sampleRate); // dwRate @xxx This is true for PCM audio only!
     bw.Write ((int)0); // dwStart
     bw.Write (asi.sampleCount); // dwLength. will be written over later
     bw.Write ((int)0); // dwSuggestedBufferSize, not suggesting it
     bw.Write ((int)-1); // dwQuality = -1 meaning "default quality"
     bw.Write (asi.sampleSize); // dwSampleSize
     bw.Write ((long)0); // rcFrame
     rw.EndChunk ();
     return offset;
 }
Пример #13
0
 private static int WriteDmlhHeader(RiffWriter rw, int totalFrames)
 {
     rw.BeginChunk (AviDemux.ID_dmlh);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     rw.binaryWriter.Write (totalFrames); // will be written over later
     rw.EndChunk ();
     return offset;
 }
Пример #14
0
 private static int WriteDummySuperIndex(RiffWriter rw, uint streamId, int entriesToReserve)
 {
     rw.BeginChunk (AviDemux.ID_indx);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write ((short)4); // wLongsPerEntry is always 4 for super index
     bw.Write ((byte)0); // bIndexSubType is always 0 for super index
     bw.Write ((byte)AviStreamIndex.Type.SUPERINDEX); // bIndexType = AVI_INDEX_OF_INDEXES
     bw.Write ((int)0); // nEntriesInUse. this'll be updated later!
     bw.Write (streamId); // dwChunkId ("##dc" and similar)
     // write 3 reserved UINTs and reserve some space for entries
     bw.Write (new byte[4 * 3 + entriesToReserve * 16]);
     rw.EndChunk ();
     return offset;
 }
Пример #15
0
        /// <summary>
        /// Write the file.
        /// </summary>
        /// <param name="w2">The file writer.</param>
        public override void Write(FileWriter w2)
        {
            //Use a RIFF writer.
            using (RiffWriter w = new RiffWriter(w2.BaseStream)) {
                //Init file.
                w.InitFile("DLS ");

                //Instrument count.
                w.StartChunk("colh");
                w.Write((uint)Instruments.Count);
                w.EndChunk();

                //Instruments.
                w.StartListChunk("lins");
                foreach (var inst in Instruments)
                {
                    w.StartListChunk("ins ");
                    w.StartChunk("insh");
                    w.Write((uint)inst.Regions.Count);
                    w.Write(inst.BankId);
                    w.Write(inst.InstrumentId);
                    w.EndChunk();
                    w.StartListChunk("lrgn");
                    foreach (Region r in inst.Regions)
                    {
                        w.StartListChunk("rgn2");
                        w.StartChunk("rgnh");
                        w.Write(r.NoteLow);
                        w.Write(r.NoteHigh);
                        w.Write(r.VelocityLow);
                        w.Write(r.VelocityHigh);
                        w.Write((ushort)(r.DoublePlayback ? 1 : 0));
                        w.Write((ushort)r.KeyGroup);
                        w.Write(r.Layer);
                        w.EndChunk();
                        w.StartChunk("wsmp");
                        w.Write((uint)0x14);
                        w.Write((ushort)r.RootNote);
                        w.Write(r.Tuning);
                        w.Write(r.Gain);
                        uint flags = 0;
                        if (r.NoTruncation)
                        {
                            flags |= 0b1;
                        }
                        if (r.NoCompression)
                        {
                            flags |= 0b10;
                        }
                        w.Write(flags);
                        w.Write((uint)(r.Loops ? 1 : 0));
                        if (r.Loops)
                        {
                            w.Write((uint)0x10);
                            w.Write((uint)(r.LoopAndRelease ? 1 : 0));
                            w.Write(r.LoopStart);
                            w.Write(r.LoopLength);
                        }
                        w.EndChunk();
                        w.StartChunk("wlnk");
                        ushort flg = 0;
                        if (r.PhaseMaster)
                        {
                            flg |= 0b1;
                        }
                        if (r.MultiChannel)
                        {
                            flg |= 0b10;
                        }
                        w.Write(flg);
                        w.Write(r.PhaseGroup);
                        w.Write(r.ChannelFlags);
                        w.Write(r.WaveId);
                        w.EndChunk();
                        w.StartListChunk("lar2");
                        foreach (var a in r.Articulators)
                        {
                            w.StartChunk("art2");
                            w.Write((uint)8);
                            w.Write((uint)a.Connections.Count);
                            foreach (var c in a.Connections)
                            {
                                w.Write((ushort)c.SourceConnection);
                                w.Write(c.ControlConnection);
                                w.Write((ushort)c.DestinationConnection);
                                w.Write((ushort)c.TransformConnection);
                                w.Write(c.Scale);
                            }
                            w.EndChunk();
                        }
                        w.EndChunk();
                        w.EndChunk();
                    }
                    w.EndChunk();
                    if (inst.Name != "")
                    {
                        w.StartListChunk("INFO");
                        w.StartChunk("INAM");
                        w.Write(inst.Name.ToCharArray());
                        w.Write("\0".ToCharArray());
                        int len = inst.Name.Length + 1;
                        while (len % 4 != 0)
                        {
                            w.Write((byte)0);
                            len++;
                        }
                        w.EndChunk();
                        w.EndChunk();
                    }
                    w.EndChunk();
                }
                w.EndChunk();

                //Pointer table initializing.
                w.StartChunk("ptbl");
                w.Write((uint)8);
                w.Write((uint)Waves.Count);
                long ptblStart = w.BaseStream.Position;
                w.Write(new byte[Waves.Count * 4]);
                w.EndChunk();

                //Write waves.
                w.StartListChunk("wvpl");
                long waveTableStart = w.BaseStream.Position;
                int  waveNum        = 0;
                foreach (var wav in Waves)
                {
                    long wBak = w.BaseStream.Position;
                    w.BaseStream.Position = ptblStart + waveNum++ *4;
                    w.Write((uint)(wBak - waveTableStart));
                    w.BaseStream.Position = wBak;
                    w.WriteWave(wav);
                }
                w.EndChunk();

                //Write info.
                w.StartListChunk("INFO");
                w.StartChunk("INAM");
                w.Write("Instrument Set".ToCharArray());
                w.EndChunk();
                w.EndChunk();

                //Close file.
                w.CloseFile();
            }
        }
Пример #16
0
 private static int WriteMainHeader(RiffWriter rw, VideoStreamInfo vsi, bool hasAudioStream)
 {
     rw.BeginChunk (AviDemux.ID_avih);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write (Mathf.RoundToInt (1000000f / vsi.framerate)); // swMicroSecPerFrame
     bw.Write ((int)0); // dwMaxBytesPerSec
     bw.Write ((int)0); // dwPaddingGranularity
     bw.Write ((int)(AVIMainHeader.AVIF_HASINDEX | AVIMainHeader.AVIF_MUSTUSEINDEX)); // dwFlags. Maybe use AVIMainHeader.AVIF_MUSTUSEINDEX too?
     bw.Write (vsi.frameCount); // dwTotalFrames. this will be written over later!
     bw.Write ((int)0); // dwInitialFrames
     bw.Write (hasAudioStream ? 2 : 1);
     bw.Write ((int)0); // dwSuggestedBufferSize, not suggesting any value
     bw.Write (vsi.width);
     bw.Write (vsi.height);
     bw.Write ((long)0); // dwReserver0 and dwReserver1
     bw.Write ((long)0); // dwReserver2 and dwReserver3
     rw.EndChunk ();
     return offset;
 }
Пример #17
0
 private static void WriteVideoFormatHeader(RiffWriter rw, VideoStreamInfo vsi)
 {
     rw.BeginChunk (AviDemux.ID_strf);
     var bw = rw.binaryWriter;
     bw.Write ((int)40); // biSize
     bw.Write (vsi.width); // biWidth
     bw.Write (vsi.height); // biHeight
     bw.Write ((short)1); // biPlanes
     bw.Write ((short)vsi.bitsPerPixel);
     bw.Write (vsi.codecFourCC); // biCompression
     bw.Write (vsi.width * vsi.height * vsi.bitsPerPixel / 8); // biSizeImage
     bw.Write ((int)0); // biXPelsPerMeter
     bw.Write ((int)0); // biYPelsPerMeter
     bw.Write ((int)0); // biClrUsed
     bw.Write ((int)0); // biClrImportant
     rw.EndChunk ();
 }
Пример #18
0
 private static void WriteAudioFormatHeader(RiffWriter rw, AudioStreamInfo asi)
 {
     rw.BeginChunk (AviDemux.ID_strf);
     var bw = rw.binaryWriter;
     bw.Write ((ushort)asi.audioFormat); // wFormatTag
     bw.Write ((short)asi.channels); // nChannels
     bw.Write (asi.sampleRate); // nSamplesPerSec
     bw.Write (asi.sampleRate * asi.sampleSize * asi.channels); // nAvgBytesPerSec @xxx true for PCM audio only, but this is a "soft" property
     bw.Write ((short)asi.sampleSize); // nBlockAlign
     bw.Write ((short)(8 * asi.sampleSize / asi.channels)); // wBitsPerSample
     bw.Write ((short)0); // cbSize. no extra coded info
     rw.EndChunk ();
 }
Пример #19
0
        private static void WriteChunkIndex(RiffWriter rw, AviStreamIndex index, int superIndexChunkOffset, ref int superIndexEntryCount, long indexBaseOffset, int maxSuperindexEntries)
        {
            var bw = rw.binaryWriter;

            // the offset where this index will be written
            long streamIndexOffset = bw.Seek (0, SeekOrigin.Current);

            // update stream superindex
            superIndexEntryCount++;
            if (superIndexEntryCount > maxSuperindexEntries) {
                throw new MpException ("Not enough space was reserved for superindex. Please increase maxSuperindexEntries");
            }

            bw.Seek (superIndexChunkOffset + 1 * 4, SeekOrigin.Begin);
            bw.Write (superIndexEntryCount); // overwrite nEntriesInUse
            bw.Seek (superIndexChunkOffset + 6 * 4 + (superIndexEntryCount - 1) * 16, SeekOrigin.Begin);
            bw.Write (streamIndexOffset);
            bw.Write (32 + 8 * index.entries.Count); // dwSize
            bw.Write (index.entries.Count); // dwDuration in stream ticks. @todo this is OK only for video, for audio stream this should be ???

            // write stream chunk index
            // @xxx MSDN suggests not seeking BaseStream when using BinaryWriter, but there are no Seek(long)
            //      in BinaryWriter. According to this forum post, BinaryWriter.Seek is just a wrapper
            //      to BinaryWriter.BaseStream.Seek, so all should be ok.
            //      http://www.pcreview.co.uk/forums/binarywriter-seek-vs-binarywriter-basestream-seek-t1223754.html
            bw.BaseStream.Seek (streamIndexOffset, SeekOrigin.Begin);

            rw.BeginChunk ((RiffParser.ToFourCC ("ix__") & 0x0000FFFF) | ((index.streamId << 16) & 0xFFFF0000));
            bw.Write ((short)2); // wLongsPerEntry is always 2 here
            bw.Write ((byte)0); // bIndexSubType is always 0 here
            bw.Write ((byte)AviStreamIndex.Type.CHUNKS); // bIndexType = AVI_INDEX_OF_CHUNKS
            bw.Write (index.entries.Count); // nEntriesInUse.
            bw.Write (index.streamId); // dwChunkId ("##dc" and similar)
            bw.Write (indexBaseOffset); // qwBaseOffset
            bw.Write ((int)0); // dwReserved3

            foreach (var entry in index.entries) {
                long offset = entry.chunkOffset - indexBaseOffset;
                if (offset > int.MaxValue) {
                    throw new MpException ("Internal error. Can't write index, because chunk offset won't fit into 31 bits: " + offset);
                }
                bw.Write ((uint)offset); // bit31==0 indicating that this is a keyframe
                bw.Write (entry.chunkLength);
            }
            rw.EndChunk ();

            index.globalOffset += index.entries.Count;
            index.entries.Clear ();
        }
Пример #20
0
        private void bgWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            const int        COPY_LEN = 50 * 1024;
            BackgroundWorker worker   = sender as BackgroundWorker;

            string[] files = (string[])e.Argument;

            try {
                using (RiffReader rr = new RiffReader(files[0]))
                    using (RiffWriter rw = new RiffWriter(files[1])) {
                        // 読み取りファイル解析
                        bool b = rr.Parse();
                        if (!b)
                        {
                            e.Result = -2;
                            return;
                        }

                        WaveFormatEx wf = rr.WaveFormat;

                        // 拡張ヘッダーを無効化できる条件
                        if (wf.Channels <= 2 && wf.Extensible && wf.BitsPerSample != 32)
                        {
                            wf.Extensible = false;
                            wf.FormatTag  = WaveFormatTag.PCM;
                        }
                        // ヘッダーの書き出し
                        b = rw.WriteHeader(wf);
                        if (!b)
                        {
                            e.Result = -1;
                            return;
                        }

                        // ループ回数を計算。進捗にも使う
                        long max = rr.Length / COPY_LEN;
                        if ((rr.Length % COPY_LEN) > 0)
                        {
                            max++;
                        }

                        for (long i = 0; i < max; i++)
                        {
                            byte[] arr = rr.Read8(COPY_LEN);
                            if (!rw.WriteStream8(arr))
                            {
                                e.Result = -1;
                                return;
                            }

                            int percentage = (int)((i + 1) * 100 / max);
                            worker.ReportProgress(percentage);
                        }

                        if (!rw.WriteFinalize())
                        {
                            return;
                        }
                    }
            } catch {
                // エラー
                e.Result = -3;
                return;
            }
            e.Result = 0;
        }
Пример #21
0
        /// <summary>
        /// Write the file.
        /// </summary>
        /// <param name="w2">The writer.</param>
        public override void Write(FileWriter w2)
        {
            //Use a RIFF writer.
            using (RiffWriter w = new RiffWriter(w2.BaseStream)) {
                //Start file.
                w.InitFile("sfbk");

                //Start INFO.
                w.StartListChunk("INFO");

                //Version.
                w.StartChunk("ifil");
                w.Write((ushort)2);
                w.Write((ushort)1);
                w.EndChunk();

                //Sound engine.
                w.StartChunk("isng");
                w.WriteNullTerminated(SoundEngine);
                w.Align(2);
                w.EndChunk();

                //Bank name.
                w.StartChunk("INAM");
                w.WriteNullTerminated(BankName);
                w.Align(2);
                w.EndChunk();

                //ROM name.
                if (!RomName.Equals(""))
                {
                    w.StartChunk("irom");
                    w.WriteNullTerminated(RomName);
                    w.Align(2);
                    w.EndChunk();
                }

                //ROM version.
                if (RomVersion != null)
                {
                    w.StartChunk("iver");
                    w.Write(RomVersion.Item1);
                    w.Write(RomVersion.Item2);
                    w.EndChunk();
                }

                //Creation date.
                if (!CreationDate.Equals(""))
                {
                    w.StartChunk("ICRD");
                    w.WriteNullTerminated(CreationDate);
                    w.Align(2);
                    w.EndChunk();
                }

                //Sound designer.
                if (!SoundDesigner.Equals(""))
                {
                    w.StartChunk("IENG");
                    w.WriteNullTerminated(SoundDesigner);
                    w.Align(2);
                    w.EndChunk();
                }

                //Product.
                if (!Product.Equals(""))
                {
                    w.StartChunk("IPRD");
                    w.WriteNullTerminated(Product);
                    w.Align(2);
                    w.EndChunk();
                }

                //Copyright.
                if (!Copyright.Equals(""))
                {
                    w.StartChunk("ICOP");
                    w.WriteNullTerminated(Copyright);
                    w.Align(2);
                    w.EndChunk();
                }

                //Comment.
                if (!Comment.Equals(""))
                {
                    w.StartChunk("ICMT");
                    w.WriteNullTerminated(Comment);
                    w.Align(2);
                    w.EndChunk();
                }

                //Tools.
                if (!Tools.Equals(""))
                {
                    w.StartChunk("ISFT");
                    w.WriteNullTerminated(Tools);
                    w.Align(2);
                    w.EndChunk();
                }

                //End INFO.
                w.EndChunk();

                //Sample block.
                w.StartListChunk("sdta");
                w.StartChunk("smpl");
                long waveTableStart = w.Position;
                Dictionary <SampleItem, long> samplePositions = new Dictionary <SampleItem, long>();
                foreach (var s in Samples)
                {
                    samplePositions.Add(s, w.Position);
                    w.Write(new short[s.Wave.Audio.NumSamples]);
                    w.Write(new short[46]);
                }
                w.EndChunk();
                w.EndChunk();

                //The hydra.
                w.StartListChunk("pdta");

                //Presets.
                w.StartChunk("phdr");
                ushort      currBagIndex = 0;
                List <Zone> zones        = new List <Zone>();
                foreach (var p in Presets)
                {
                    p.ReadingBagIndex = currBagIndex;
                    currBagIndex     += (ushort)p.NumZones;
                    w.Write(p);
                    zones.AddRange(p.GetAllZones());
                }
                w.Write(new Preset()
                {
                    Name = "EOP", Bank = 255, PresetNumber = 255, ReadingBagIndex = currBagIndex
                });
                w.EndChunk();

                //Preset bags.
                w.StartChunk("pbag");
                ushort currGenIndex = 0;
                ushort currModIndex = 0;
                foreach (var z in zones)
                {
                    w.Write(currGenIndex);
                    w.Write(currModIndex);
                    currGenIndex += (ushort)z.Generators.Count;
                    currModIndex += (ushort)z.Modulators.Count;
                }
                w.Write(currGenIndex);
                w.Write(currModIndex);
                w.EndChunk();

                //Preset modulators.
                w.StartChunk("pmod");
                foreach (var z in zones)
                {
                    foreach (var v in z.Modulators)
                    {
                        w.Write(v);
                    }
                }
                w.Write(new Modulator());
                w.EndChunk();

                //Preset generators.
                w.StartChunk("pgen");
                foreach (var z in zones)
                {
                    foreach (var v in z.Generators)
                    {
                        w.Write(v);
                    }
                }
                w.Write(new Generator());
                w.EndChunk();

                //Instruments.
                w.StartChunk("inst");
                currBagIndex = 0;
                zones        = new List <Zone>();
                foreach (var p in Instruments)
                {
                    p.ReadingBagIndex = currBagIndex;
                    currBagIndex     += (ushort)p.NumZones;
                    w.Write(p);
                    zones.AddRange(p.GetAllZones());
                }
                w.Write(new Instrument()
                {
                    Name = "EOI", ReadingBagIndex = currBagIndex
                });
                w.EndChunk();

                //Instrument bags.
                w.StartChunk("ibag");
                currGenIndex = 0;
                currModIndex = 0;
                foreach (var z in zones)
                {
                    w.Write(currGenIndex);
                    w.Write(currModIndex);
                    currGenIndex += (ushort)z.Generators.Count;
                    currModIndex += (ushort)z.Modulators.Count;
                }
                w.Write(currGenIndex);
                w.Write(currModIndex);
                w.EndChunk();

                //Instrument modulators.
                w.StartChunk("imod");
                foreach (var z in zones)
                {
                    foreach (var v in z.Modulators)
                    {
                        w.Write(v);
                    }
                }
                w.Write(new Modulator());
                w.EndChunk();

                //Instrument generators.
                w.StartChunk("igen");
                foreach (var z in zones)
                {
                    foreach (var v in z.Generators)
                    {
                        w.Write(v);
                    }
                }
                w.Write(new Generator());
                w.EndChunk();

                //Samples.
                w.StartChunk("shdr");
                foreach (var s in Samples)
                {
                    w.CurrentOffset = samplePositions[s];
                    w.StructureOffsets.Push(waveTableStart);
                    w.Write(s);
                }
                w.Write("EOS".ToCharArray());
                w.Write(new byte[0x2B]);
                w.EndChunk();

                //End the hydra.
                w.EndChunk();

                //Close file.
                w.CloseFile();
            }
        }
Пример #22
0
 private static int WriteVideoStreamHeader(RiffWriter rw, VideoStreamInfo vsi)
 {
     rw.BeginChunk (AviDemux.ID_strh);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write (AviDemux.FCC_vids);
     bw.Write (vsi.codecFourCC);
     bw.Write ((int)0); // dwFlags
     bw.Write ((short)0); // wPriority
     bw.Write ((short)0); // wLanguage
     bw.Write ((int)0); // dwInitialFrames
     int scale, rate;
     FindScaleAndRate (out scale, out rate, vsi.framerate);
     bw.Write (scale); // dwScale
     bw.Write (rate); // dwRate
     bw.Write ((int)0); // dwStart
     bw.Write (vsi.frameCount); // dwLength. that's how many frames will be in this RIFF element, written over later
     bw.Write ((int)0); // dwSuggestedBufferSize, not suggesting any value
     bw.Write ((int)-1); // dwQuality = -1 meaning "default quality"
     bw.Write ((int)0); // dwSampleSize = 0 for video
     bw.Write ((short)0);
     bw.Write ((short)0);
     bw.Write ((short)vsi.width);
     bw.Write ((short)vsi.height);
     rw.EndChunk ();
     return offset;
 }