Пример #1
0
        public static void WriteSingleChunkHeader(WavSingleChunkHeader header, Stream wavStream)
        {
            BinaryEndianWriter w = new BinaryEndianWriter(wavStream);

            w.Write(Encoding.Default.GetBytes(header.FileId));
            w.Write(header.FileLength);
            w.Write(Encoding.Default.GetBytes(header.RiffType));

            w.Write(Encoding.Default.GetBytes(header.ChunkHeaderId));
            w.Write(header.ChunkHeaderLength);
            w.Write(header.FormatTag);
            w.Write(header.Channels);
            w.Write(header.SamplesPerSec);
            w.Write(header.AvgBytesPerSec);
            w.Write(header.BlockAlign);
            w.Write(header.BitsPerSample);
            w.Write(header.ExtraBytes);
            w.Write(Encoding.Default.GetBytes(header.ChunkId));
            w.Write(header.ChunkLength);
        }
Пример #2
0
        public static void CreatePreview(int offset, int length, int fade, float volume, bool volumeApplied, string dstFilename, params AudioFile[] srcFilenames)
        {
            if (srcFilenames == null || srcFilenames.Length == 0 || (srcFilenames.Length == 1 && (srcFilenames[0] == null || srcFilenames[0].Name.Length == 0)))
                return;

            FileHelper.Delete(dstFilename);

            WavSingleChunkHeader[] whi = new WavSingleChunkHeader[srcFilenames.Length];
            BinaryEndianReader[] br = new BinaryEndianReader[srcFilenames.Length];
            float[] vols = new float[srcFilenames.Length];

            int outWav = 0; //use this input wav as the format for the output wav
            int maxLen = 0;

            for (int c = 0; c < srcFilenames.Length; c++)
            {
                br[c] = new BinaryEndianReader(File.OpenRead(srcFilenames[c].Name));
                whi[c] = ParseWavSingleChunkHeader(br[c].BaseStream);
                if (!volumeApplied)
                    vols[c] = srcFilenames[c].Volume / 100F; //get percentage
                else
                    vols[c] = 1; //100%

                //move to the correct point in each wav
                uint wOffset = (uint)(whi[c].AvgBytesPerSec * ((float)offset / 1000));
                wOffset -= wOffset % whi[c].BlockAlign;
                br[c].BaseStream.Seek((long)wOffset, SeekOrigin.Current);

                if (whi[c].AudioLength > maxLen)
                    maxLen = whi[c].AudioLength;

                if (whi[c].Channels == 2)
                    outWav = c;
            }

            WavSingleChunkHeader who = new WavSingleChunkHeader();

            if (length == 0)
                length = maxLen;

            uint wLength = (uint)(whi[outWav].AvgBytesPerSec * ((float)length / 1000));
            wLength -= wLength % whi[outWav].BlockAlign;

            who.FileId = "RIFF";
            who.FileLength = (uint)(br[outWav].BaseStream.Length - whi[outWav].FileLength) + wLength;
            who.RiffType = "WAVE";

            who.ChunkHeaderId = "fmt ";
            who.ChunkHeaderLength = whi[outWav].ChunkHeaderLength;
            who.FormatTag = whi[outWav].FormatTag;
            who.Channels = whi[outWav].Channels;
            who.SamplesPerSec = whi[outWav].SamplesPerSec;
            who.AvgBytesPerSec = whi[outWav].AvgBytesPerSec;
            who.BlockAlign = whi[outWav].BlockAlign;
            who.BitsPerSample = whi[outWav].BitsPerSample;
            who.ExtraBytes = whi[outWav].ExtraBytes;

            who.ChunkId = "data";
            who.ChunkLength = wLength;

            using (FileStream fso = File.OpenWrite(dstFilename))
            {
                WriteSingleChunkHeader(who, fso);

                int loops = (int)((who.AvgBytesPerSec / who.BlockAlign) * ((float)length / 1000));
                int fadeLen = (int)((who.AvgBytesPerSec / who.BlockAlign) * ((float)fade / 1000));

                Double maxVol = (volume / (float)srcFilenames.Length);  //reduce volume Audio in game
                maxVol *= 1F + ((srcFilenames.Length - 1) * 0.33F);  //add an extra third per file to cater for volume loss

                Double vol = 0; //initial volume
                if (fade == 0)
                    vol = maxVol;

                int b32;

                BinaryEndianWriter bw = new BinaryEndianWriter(fso);

                Double step = (double)(maxVol - 0) / fadeLen; //fade in
                if (Double.IsInfinity(step))
                    step = 0;
                int allLeft = 0;
                int allRight = 0;

                long[] streamPos = new long[br.Length]; //fast way to track pos in stream
                for (int c = 0; c < br.Length; c++)
                    streamPos[c] = br[c].BaseStream.Position;
                long[] streamLen = new long[br.Length]; //fast way to get length of stream
                for (int c = 0; c < br.Length; c++)
                    streamLen[c] = br[c].BaseStream.Length;

                for (int i = 0; i != loops; i++)
                {
                    if (i == fadeLen)
                        step = 0; //use max volume
                    if (i == loops - fadeLen) //fade out
                        step = (double)(0 - maxVol) / fadeLen;

                    allLeft = 0;
                    allRight = 0;

                    for (int c = 0; c < br.Length; c++) //each input stream
                    {
                        BinaryEndianReader b = br[c];
                        WavSingleChunkHeader w = whi[c];

                        //Left channel
                        b32 = 0;
                        if (streamPos[c] + 2 < streamLen[c])
                        {
                            b32 = (int)(b.ReadInt16(EndianType.Little) * vols[c]);
                            streamPos[c] += 2;
                        }
                        allLeft += (int)(b32 * vol);
                        allLeft = (short)Math.Max((int)short.MinValue, Math.Min((int)short.MaxValue, allLeft));

                        if (who.Channels > 1)
                        {
                            if (w.Channels > 1)
                            {
                                //Right channel
                                b32 = 0;
                                if (streamPos[c] + 2 < streamLen[c])
                                {
                                    b32 = (int)(b.ReadInt16(EndianType.Little) * vols[c]);
                                    streamPos[c] += 2;
                                }
                            }
                            allRight += (int)(b32 * vol);
                            allRight = (short)Math.Max((int)short.MinValue, Math.Min((int)short.MaxValue, allRight));
                        }
                    }

                    bw.Write((short)allLeft);
                    if (who.Channels > 1)
                        bw.Write((short)allRight);

                    vol += step;
                }

                foreach (BinaryEndianReader b in br)
                    b.Close();

                fso.Flush();
            }
        }
Пример #3
0
        public static void CreateSilentWav(int length, string dstFilename, bool stereo, int samplesPerSec)
        {
            FileHelper.Delete(dstFilename);

            ushort bits = 16;
            ushort channels = (ushort)(stereo ? 2 : 1);
            ushort blockAlign = (ushort)(channels * 2);

            WavSingleChunkHeader who = new WavSingleChunkHeader();

            uint wLength = (uint)((float)(blockAlign * samplesPerSec) * (float)(length / 1000F));
            wLength -= wLength % blockAlign;

            who.FileId = "RIFF";
            who.FileLength = (uint)(wLength + 46) - 8;
            who.RiffType = "WAVE";

            who.ChunkHeaderId = "fmt ";
            who.ChunkHeaderLength = 18;
            who.FormatTag = 1; //raw wav
            who.Channels = channels;
            who.SamplesPerSec = (uint)samplesPerSec;
            who.AvgBytesPerSec = (uint)(blockAlign * samplesPerSec);
            who.BlockAlign = blockAlign;
            who.BitsPerSample = bits;
            who.ExtraBytes = new byte[2];

            who.ChunkId = "data";
            who.ChunkLength = wLength;

            using (FileStream fso = File.OpenWrite(dstFilename))
            {
                WriteSingleChunkHeader(who, fso);

                byte[] buffer = new byte[who.AvgBytesPerSec];
                for (int i = 0; i < buffer.Length; i++)
                    buffer[i] = 0;
                long written = 0;

                while (written + buffer.Length < wLength)
                {
                    fso.Write(buffer, 0, buffer.Length);
                    written += buffer.Length;
                }

                if (written != wLength)
                    fso.Write(buffer, 0, (int)(wLength - written));

                fso.Flush();
            }
        }
Пример #4
0
        public static WavSingleChunkHeader ParseWavSingleChunkHeader(Stream wavStream)
        {
            WavSingleChunkHeader w = new WavSingleChunkHeader();
            byte[] b;

            BinaryEndianReader r = new BinaryEndianReader(wavStream);

            b = r.ReadBytes(4);
            w.FileId = Encoding.Default.GetString(b);
            w.FileLength = r.ReadUInt32(EndianType.Little);
            b = r.ReadBytes(4);
            w.RiffType = Encoding.Default.GetString(b);

            b = r.ReadBytes(4);
            w.ChunkHeaderId = Encoding.Default.GetString(b);
            w.ChunkHeaderLength = r.ReadUInt32(EndianType.Little);
            long p = wavStream.Position;
            w.FormatTag = r.ReadUInt16(EndianType.Little);
            w.Channels = r.ReadUInt16(EndianType.Little);
            w.SamplesPerSec = r.ReadUInt32(EndianType.Little);
            w.AvgBytesPerSec = r.ReadUInt32(EndianType.Little);
            w.BlockAlign = r.ReadUInt16(EndianType.Little);
            w.BitsPerSample = r.ReadUInt16(EndianType.Little);

            if (wavStream.Position - p != w.ChunkHeaderLength)
                w.ExtraBytes = r.ReadBytes((int)(w.ChunkHeaderLength - (wavStream.Position - p)));

            b = r.ReadBytes(4);
            w.ChunkId = Encoding.Default.GetString(b);
            w.ChunkLength = r.ReadUInt32(EndianType.Little);

            w.DataOffset = (int)wavStream.Position;
            return w;
        }
Пример #5
0
        public static void CreateSilentWav(int length, string dstFilename, params string[] srcFilenames)
        {
            if (srcFilenames == null || (srcFilenames.Length == 1 && srcFilenames[0].Length == 0))
                return;

            FileHelper.Delete(dstFilename);

            WavSingleChunkHeader[] whi = new WavSingleChunkHeader[srcFilenames.Length];
            BinaryEndianReader[] br = new BinaryEndianReader[srcFilenames.Length];

            int outWav = 0; //use this input wav as the format for the output wav

            for (int c = 0; c < srcFilenames.Length; c++)
            {
                br[c] = new BinaryEndianReader(File.OpenRead(srcFilenames[c]));
                whi[c] = ParseWavSingleChunkHeader(br[c].BaseStream);

                if (whi[c].Channels == 2)
                    outWav = c;
            }

            WavSingleChunkHeader who = new WavSingleChunkHeader();

            uint wLength = (uint)((float)whi[outWav].AvgBytesPerSec * (float)(length / 1000F));
            wLength -= wLength % whi[outWav].BlockAlign;

            who.FileId = "RIFF";
            who.FileLength = (uint)(whi[outWav].DataOffset + wLength) - 8;
            who.RiffType = "WAVE";

            who.ChunkHeaderId = "fmt ";
            who.ChunkHeaderLength = whi[outWav].ChunkHeaderLength;
            who.FormatTag = whi[outWav].FormatTag;
            who.Channels = whi[outWav].Channels;
            who.SamplesPerSec = whi[outWav].SamplesPerSec;
            who.AvgBytesPerSec = whi[outWav].AvgBytesPerSec;
            who.BlockAlign = whi[outWav].BlockAlign;
            who.BitsPerSample = whi[outWav].BitsPerSample;
            who.ExtraBytes = whi[outWav].ExtraBytes;

            who.ChunkId = "data";
            who.ChunkLength = wLength;

            foreach (BinaryEndianReader b in br)
                b.Close();

            using (FileStream fso = File.OpenWrite(dstFilename))
            {
                WriteSingleChunkHeader(who, fso);

                byte[] buffer = new byte[who.AvgBytesPerSec];
                for (int i = 0; i < buffer.Length; i++)
                    buffer[i] = 0;
                long written = 0;

                while (written + buffer.Length < wLength)
                {
                    fso.Write(buffer, 0, buffer.Length);
                    written += buffer.Length;
                }

                if (written != wLength)
                    fso.Write(buffer, 0, (int)(wLength - written));

                fso.Flush();
            }
        }