public static WavePeakData GenerateEmptyPeaks(string peakFileName, int totalSeconds)
        {
            int peaksPerSecond = Configuration.Settings.VideoControls.WaveformMinimumSampleRate;
            var peaks          = new List <WavePeak>
            {
                new WavePeak(1000, -1000)
            };
            var totalPeaks = peaksPerSecond * totalSeconds;

            for (int i = 0; i < totalPeaks; i++)
            {
                peaks.Add(new WavePeak(1, -1));
            }
            peaks.Add(new WavePeak(1000, -1000));

            // save results to file
            using (var stream = File.Create(peakFileName))
            {
                WaveHeader.WriteHeader(stream, peaksPerSecond, 2, 16, peaks.Count);
                byte[] buffer = new byte[4];
                foreach (var peak in peaks)
                {
                    WriteValue16Bit(buffer, 0, peak.Max);
                    WriteValue16Bit(buffer, 2, peak.Min);
                    stream.Write(buffer, 0, 4);
                }
            }

            return(new WavePeakData(peaksPerSecond, peaks));
        }
Exemple #2
0
        public static void WriteWaveformData(Stream stream, int sampleRate, List <WavePeak> peaks)
        {
            WaveHeader.WriteHeader(stream, sampleRate, 2, 16, peaks.Count);
            var buffer = new byte[4];

            foreach (var peak in peaks)
            {
                WriteValue16Bit(buffer, 0, peak.Max);
                WriteValue16Bit(buffer, 2, peak.Min);
                stream.Write(buffer, 0, 4);
            }
        }
        /// <summary>
        /// Generates peaks and saves them to disk.
        /// </summary>
        /// <param name="delayInMilliseconds">Delay in milliseconds (normally zero)</param>
        /// <param name="peakFileName">Path of the output file</param>
        public WavePeakData GeneratePeaks(int delayInMilliseconds, string peakFileName)
        {
            int peaksPerSecond = Math.Min(Configuration.Settings.VideoControls.WaveformMinimumSampleRate, _header.SampleRate);

            // ensure that peaks per second is a factor of the sample rate
            while (_header.SampleRate % peaksPerSecond != 0)
            {
                peaksPerSecond++;
            }

            int delaySampleCount = (int)(_header.SampleRate * (delayInMilliseconds / TimeCode.BaseUnit));

            // ignore negative delays for now (pretty sure it can't happen in mkv and some places pass in -1 by mistake)
            delaySampleCount = Math.Max(delaySampleCount, 0);

            var   peaks = new List <WavePeak>();
            var   readSampleDataValue   = GetSampleDataReader();
            float sampleAndChannelScale = (float)GetSampleAndChannelScale();
            long  fileSampleCount       = _header.LengthInSamples;
            long  fileSampleOffset      = -delaySampleCount;
            int   chunkSampleCount      = _header.SampleRate / peaksPerSecond;

            byte[]  data         = new byte[chunkSampleCount * _header.BlockAlign];
            float[] chunkSamples = new float[chunkSampleCount * 2];

            _stream.Seek(_header.DataStartPosition, SeekOrigin.Begin);

            // for negative delays, skip samples at the beginning
            if (fileSampleOffset > 0)
            {
                _stream.Seek(fileSampleOffset * _header.BlockAlign, SeekOrigin.Current);
            }

            while (fileSampleOffset < fileSampleCount)
            {
                // calculate how many samples to skip at the beginning (for positive delays)
                int startSkipSampleCount = 0;
                if (fileSampleOffset < 0)
                {
                    startSkipSampleCount = (int)Math.Min(-fileSampleOffset, chunkSampleCount);
                    fileSampleOffset    += startSkipSampleCount;
                }

                // calculate how many samples to read from the file
                long fileSamplesRemaining = fileSampleCount - Math.Max(fileSampleOffset, 0);
                int  fileReadSampleCount  = (int)Math.Min(fileSamplesRemaining, chunkSampleCount - startSkipSampleCount);

                // read samples from the file
                if (fileReadSampleCount > 0)
                {
                    int fileReadByteCount = fileReadSampleCount * _header.BlockAlign;
                    _stream.Read(data, 0, fileReadByteCount);
                    fileSampleOffset += fileReadSampleCount;

                    int chunkSampleOffset = 0;
                    int dataByteOffset    = 0;
                    while (dataByteOffset < fileReadByteCount)
                    {
                        float valuePositive = 0F;
                        float valueNegative = -0F;
                        for (int iChannel = 0; iChannel < _header.NumberOfChannels; iChannel++)
                        {
                            var v = readSampleDataValue(data, ref dataByteOffset);
                            if (v < 0)
                            {
                                valueNegative += v;
                            }
                            else
                            {
                                valuePositive += v;
                            }
                        }

                        chunkSamples[chunkSampleOffset] = valueNegative * sampleAndChannelScale;
                        chunkSampleOffset++;
                        chunkSamples[chunkSampleOffset] = valuePositive * sampleAndChannelScale;
                        chunkSampleOffset++;
                    }
                }

                // calculate peaks
                peaks.Add(CalculatePeak(chunkSamples, fileReadSampleCount * 2));
            }

            // save results to file
            using (var stream = File.Create(peakFileName))
            {
                WaveHeader.WriteHeader(stream, peaksPerSecond, 2, 16, peaks.Count);
                byte[] buffer = new byte[4];
                foreach (var peak in peaks)
                {
                    WriteValue16Bit(buffer, 0, peak.Max);
                    WriteValue16Bit(buffer, 2, peak.Min);
                    stream.Write(buffer, 0, 4);
                }
            }

            return(new WavePeakData(peaksPerSecond, peaks));
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="stream">Stream of a wave file</param>
 public WavePeakGenerator(Stream stream)
 {
     _stream = stream;
     _header = new WaveHeader(_stream);
 }