Example #1
0
        /// ------------------------------------------------------------------------------------
        public static Tuple <float, float>[,] GetSamples(IWaveStreamReader stream,
                                                         uint numberOfSamplesToReturn)
        {
            var sampleCount = stream.SampleCount;

            if (numberOfSamplesToReturn == 0 || sampleCount == 0 ||
                (stream.BitsPerSample == 32 && stream.Encoding != WaveFormatEncoding.IeeeFloat))
            {
                return(new Tuple <float, float> [0, 0]);
            }

            if (sampleCount < numberOfSamplesToReturn)
            {
                numberOfSamplesToReturn = (uint)sampleCount;
            }

            stream.Seek(0, SeekOrigin.Begin);
            var channels = stream.SamplingChannelCount;

            var samplesPerAggregate = sampleCount / (double)numberOfSamplesToReturn;
            var samplesToReturn     = new Tuple <float, float> [numberOfSamplesToReturn, stream.NativeChannelCount];

            // To avoid compounding rounding errors as we get further along in the file, we need to separately track
            // the number of samples we've actually read and the ideal (unrounded) number of samples we should have
            // processed. Every time the rounding error builds to a whole integer, we read an extra sample to get them
            // back in synch. The buffer needs to be big enough to hold the extra sample for the times through the loop
            // when we're reading the higher number of samples.
            double idealSamplesProcessed = 0;
            var    buffer       = new float[(int)(Math.Ceiling(samplesPerAggregate)) * channels];
            int    valuesToRead = (int)(Math.Floor(samplesPerAggregate)) * channels;

            int  sampleIndex = 0;
            int  read;
            long totalRead = 0;

            while (sampleIndex < numberOfSamplesToReturn && (read = stream.Read(buffer, valuesToRead)) > 0)
            {
                for (var c = 0; c < stream.NativeChannelCount; c++)
                {
                    var biggestSample  = float.MinValue;
                    var smallestSample = float.MaxValue;

                    for (int i = 0; i < read; i += channels)
                    {
                        biggestSample  = Math.Max(biggestSample, buffer[i + c]);
                        smallestSample = Math.Min(smallestSample, buffer[i + c]);
                    }

                    samplesToReturn[sampleIndex, c] = new Tuple <float, float>(biggestSample, smallestSample);
                }

                // See big comment above.
                valuesToRead           = (int)(Math.Floor(samplesPerAggregate)) * channels;
                totalRead             += (read / channels);
                idealSamplesProcessed += samplesPerAggregate;
                if (totalRead < Math.Floor(idealSamplesProcessed))
                {
                    valuesToRead += channels;
                }

                sampleIndex++;
            }

            return(samplesToReturn);
        }
Example #2
0
 /// ------------------------------------------------------------------------------------
 /// <summary>
 /// Constructor to facilitate testing
 /// </summary>
 /// ----------------------------------------------------------------------------------------
 public AutoSegmenter(IWaveStreamReader sampleProvider, IAutoSegmenterSettings settings)
 {
     _streamReader = sampleProvider;
     _settings     = settings;
 }