예제 #1
1
 /// <summary>
 /// Helper function to go from IWaveProvider to a SampleProvider
 /// Must already be PCM or IEEE float
 /// </summary>
 /// <param name="waveProvider">The WaveProvider to convert</param>
 /// <returns>A sample provider</returns>
 public static ISampleProvider ConvertWaveProviderIntoSampleProvider(IWaveProvider waveProvider)
 {
     ISampleProvider sampleProvider;
     if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.Pcm)
     {
         // go to float
         if (waveProvider.WaveFormat.BitsPerSample == 8)
         {
             sampleProvider = new Pcm8BitToSampleProvider(waveProvider);
         }
         else if (waveProvider.WaveFormat.BitsPerSample == 16)
         {
             sampleProvider = new Pcm16BitToSampleProvider(waveProvider);
         }
         else if (waveProvider.WaveFormat.BitsPerSample == 24)
         {
             sampleProvider = new Pcm24BitToSampleProvider(waveProvider);
         }
         else
         {
             throw new InvalidOperationException("Unsupported operation");
         }
     }
     else if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
     {
         sampleProvider = new WaveToSampleProvider(waveProvider);
     }
     else
     {
         throw new ArgumentException("Unsupported source encoding");
     }
     return sampleProvider;
 }
예제 #2
1
 public static SampleSource CreateFromWaveFile(string fileName)
 {
     using (var reader = new WaveFileReader(fileName))
     {
         ISampleProvider sp;
         int sourceSamples;
         if (reader.WaveFormat.Encoding == WaveFormatEncoding.Pcm)
         {
             if (reader.WaveFormat.BitsPerSample == 16)
             {
                 sp = new Pcm16BitToSampleProvider(reader);
                 sourceSamples = (int)(reader.Length / 2);
             }
             else if (reader.WaveFormat.BitsPerSample == 24)
             {
                 sp = new Pcm24BitToSampleProvider(reader);
                 sourceSamples = (int)(reader.Length / 3);
             }
             else
             {
                 throw new ArgumentException("Currently only 16 or 24 bit PCM samples are supported");
             }
         }
         else if (reader.WaveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
         {
             sp = new WaveToSampleProvider(reader);
             sourceSamples = (int)(reader.Length / 4);
         }
         else
         {
             throw new ArgumentException("Must be PCM or IEEE float");
         }
         float[] sampleData = new float[sourceSamples];
         int n = sp.Read(sampleData, 0, sourceSamples);
         if (n != sourceSamples)
         {
             throw new InvalidOperationException(String.Format("Couldn't read the whole sample, expected {0} samples, got {1}", n, sourceSamples));
         }
         SampleSource ss = new SampleSource(sampleData, sp.WaveFormat);
         return ss;
     }
 }
예제 #3
0
        /// <summary>
        /// Helper function to go from IWaveProvider to a SampleProvider
        /// Must already be PCM or IEEE float
        /// </summary>
        /// <param name="waveProvider">The WaveProvider to convert</param>
        /// <returns>A sample provider</returns>
        public static ISampleProvider ConvertWaveProviderIntoSampleProvider(IWaveProvider waveProvider)
        {
            ISampleProvider sampleProvider;

            if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.Pcm)
            {
                // go to float
                if (waveProvider.WaveFormat.BitsPerSample == 8)
                {
                    sampleProvider = new Pcm8BitToSampleProvider(waveProvider);
                }
                else if (waveProvider.WaveFormat.BitsPerSample == 16)
                {
                    sampleProvider = new Pcm16BitToSampleProvider(waveProvider);
                }
                else if (waveProvider.WaveFormat.BitsPerSample == 24)
                {
                    sampleProvider = new Pcm24BitToSampleProvider(waveProvider);
                }
                else
                {
                    throw new InvalidOperationException("Unsupported operation");
                }
            }
            else if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
            {
                sampleProvider = new WaveToSampleProvider(waveProvider);
            }
            else
            {
                throw new ArgumentException("Unsupported source encoding");
            }
            return(sampleProvider);
        }
예제 #4
0
        public static float[] BuildPeaks(UWavePart part, System.ComponentModel.BackgroundWorker worker)
        {
            const double peaksRate = 4000;
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            float[] peaks;
            using (var stream = new AudioFileReader(part.FilePath))
            {
                int channels = part.Channels;
                double peaksSamples = (int)((double)stream.Length / stream.WaveFormat.BlockAlign / stream.WaveFormat.SampleRate * peaksRate);
                peaks = new float[(int)(peaksSamples + 1) * channels];
                double blocksPerPixel = stream.Length / stream.WaveFormat.BlockAlign / peaksSamples;

                var converted = new WaveToSampleProvider(stream);

                float[] buffer = new float[4096];

                int readed;
                int readPos = 0;
                int peaksPos = 0;
                double bufferPos = 0;
                float lmax = 0, lmin = 0, rmax = 0, rmin = 0;
                while ((readed = converted.Read(buffer, 0, 4096)) != 0)
                {
                    readPos += readed;
                    for (int i = 0; i < readed; i += channels)
                    {
                        lmax = Math.Max(lmax, buffer[i]);
                        lmin = Math.Min(lmin, buffer[i]);
                        if (channels > 1)
                        {
                            rmax = Math.Max(rmax, buffer[i + 1]);
                            rmin = Math.Min(rmin, buffer[i + 1]);
                        }
                        if (i > bufferPos)
                        {
                            lmax = -lmax; lmin = -lmin; rmax = -rmax; rmin = -rmin; // negate peaks to fipped waveform
                            peaks[peaksPos * channels] = lmax == 0 ? lmin : lmin == 0 ? lmax : (lmin + lmax) / 2;
                            peaks[peaksPos * channels + 1] = rmax == 0 ? rmin : rmin == 0 ? rmax : (rmin + rmax) / 2;
                            peaksPos++;
                            lmax = lmin = rmax = rmin = 0;
                            bufferPos += blocksPerPixel * stream.WaveFormat.Channels;
                        }
                    }
                    bufferPos -= readed;
                    worker.ReportProgress((int)((double)readPos * sizeof(float) * 100 / stream.Length));
                }
            }
            sw.Stop();
            System.Diagnostics.Debug.WriteLine("Build peaks {0} ms", sw.Elapsed.TotalMilliseconds);
            return peaks;
        }
예제 #5
0
        public static ISampleProvider ConvertWaveProviderIntoSampleProvider(IWaveProvider waveProvider)
        {
            ISampleProvider result;

            if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.Pcm)
            {
                if (waveProvider.WaveFormat.BitsPerSample == 8)
                {
                    result = new Pcm8BitToSampleProvider(waveProvider);
                }
                else if (waveProvider.WaveFormat.BitsPerSample == 16)
                {
                    result = new Pcm16BitToSampleProvider(waveProvider);
                }
                else if (waveProvider.WaveFormat.BitsPerSample == 24)
                {
                    result = new Pcm24BitToSampleProvider(waveProvider);
                }
                else
                {
                    if (waveProvider.WaveFormat.BitsPerSample != 32)
                    {
                        throw new InvalidOperationException("Unsupported bit depth");
                    }
                    result = new Pcm32BitToSampleProvider(waveProvider);
                }
            }
            else
            {
                if (waveProvider.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat)
                {
                    throw new ArgumentException("Unsupported source encoding");
                }
                if (waveProvider.WaveFormat.BitsPerSample == 64)
                {
                    result = new WaveToSampleProvider64(waveProvider);
                }
                else
                {
                    result = new WaveToSampleProvider(waveProvider);
                }
            }
            return(result);
        }
예제 #6
0
        /// <summary>
        /// Initialises a new instance of SampleChannel
        /// </summary>
        /// <param name="waveProvider">Source wave provider, must be PCM or IEEE</param>
        public SampleChannel(IWaveProvider waveProvider)
        {
            ISampleProvider sampleProvider;

            if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.Pcm)
            {
                // go to float
                if (waveProvider.WaveFormat.BitsPerSample == 8)
                {
                    sampleProvider = new Pcm8BitToSampleProvider(waveProvider);
                }
                else if (waveProvider.WaveFormat.BitsPerSample == 16)
                {
                    sampleProvider = new Pcm16BitToSampleProvider(waveProvider);
                }
                else if (waveProvider.WaveFormat.BitsPerSample == 24)
                {
                    sampleProvider = new Pcm24BitToSampleProvider(waveProvider);
                }
                else
                {
                    throw new InvalidOperationException("Unsupported operation");
                }
            }
            else if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
            {
                sampleProvider = new WaveToSampleProvider(waveProvider);
            }
            else
            {
                throw new ArgumentException("Unsupported source encoding");
            }
            if (sampleProvider.WaveFormat.Channels == 1)
            {
                sampleProvider = new MonoToStereoSampleProvider(sampleProvider);
            }
            this.waveFormat = sampleProvider.WaveFormat;
            // let's put the meter before the volume (useful for drawing waveforms)
            this.preVolumeMeter = new MeteringSampleProvider(sampleProvider);
            this.volumeProvider = new VolumeSampleProvider(preVolumeMeter);
        }
예제 #7
0
 /// <summary>
 /// Initialises a new instance of SampleChannel
 /// </summary>
 /// <param name="waveProvider">Source wave provider, must be PCM or IEEE</param>
 public SampleChannel(IWaveProvider waveProvider)
 {
     ISampleProvider sampleProvider;
     if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.Pcm)
     {
         // go to float
         if (waveProvider.WaveFormat.BitsPerSample == 8)
         {
             sampleProvider = new Pcm8BitToSampleProvider(waveProvider);
         }
         else if (waveProvider.WaveFormat.BitsPerSample == 16)
         {
             sampleProvider = new Pcm16BitToSampleProvider(waveProvider);
         }
         else if (waveProvider.WaveFormat.BitsPerSample == 24)
         {
             sampleProvider = new Pcm24BitToSampleProvider(waveProvider);
         }
         else
         {
             throw new InvalidOperationException("Unsupported operation");
         }
     }
     else if (waveProvider.WaveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
     {
         sampleProvider = new WaveToSampleProvider(waveProvider);
     }
     else
     {
         throw new ArgumentException("Unsupported source encoding");
     }
     if (sampleProvider.WaveFormat.Channels == 1)
     {
         sampleProvider = new MonoToStereoSampleProvider(sampleProvider);
     }
     this.waveFormat = sampleProvider.WaveFormat;
     // let's put the meter before the volume (useful for drawing waveforms)
     this.preVolumeMeter = new MeteringSampleProvider(sampleProvider);
     this.volumeProvider = new VolumeSampleProvider(preVolumeMeter);
 }
예제 #8
0
        private void _play()
        {
            /* Audio chain */

            // Sampling
            _wavesampler = new WaveToSampleProvider(new Wave16ToFloatProvider(_wavebuffer));

            // Fading component
            _fade = new FadeInOutSampleProvider(_wavesampler);
            _fade.BeginFadeIn(1500);

            // Notifying component
            var _notify = new NotifyingSampleProvider(_fade);
            _notify.Sample += new EventHandler<SampleEventArgs>(_notify_Sample);

            // Gain adjustment component
            _volume = new VolumeSampleProvider(_notify);
            _volume.Volume = this.Volume;

            // Output
            Output.Init(new SampleToWaveProvider16(_volume));

            /* Playback loop */
            do
            {
                if (_cancel_play.IsCancellationRequested)
                {
                    Console.WriteLine("[Playback thread] Cancellation requested.");

                    // Fade out and stop
                    Console.WriteLine("[Playback thread] Fading out and stopping...");
                    _fade.BeginFadeOut(500);
                    Thread.Sleep(500);
                    Output.Stop();
                    Console.WriteLine("[Playback thread] Output stopped.");
                    this.Status = StreamStatus.Stopped;
                    Console.WriteLine("[Playback thread] Acknowledged as status.");

                    //_cancel_play_token.ThrowIfCancellationRequested();
                    //Console.WriteLine("[Playback thread] WARNING: Cancellation token is not cleanly set!");
                    return;
                }

                if (Output.PlaybackState != PlaybackState.Playing && _wavebuffer.BufferedDuration.TotalMilliseconds > 2750)
                {
                    // Buffer is filled enough
                    Console.WriteLine("[Playback thread] Buffer is okay now, start playback!");
                    this.Status = StreamStatus.Playing;
                    Output.Play();
                }
                else if (Output.PlaybackState == PlaybackState.Playing && _wavebuffer.BufferedDuration.TotalMilliseconds < 2250)
                {
                    // Buffer is underrunning
                    Console.WriteLine("[Playback thread] Buffer is underrunning, pausing playback...");
                    this.Status = StreamStatus.Buffering;
                    Output.Pause();
                }

                if (_bufferThread.Exception != null)
                {
                    Console.WriteLine("[Playback thread] Buffering thread is faulted, aborting playback");
                    throw new Exception("Buffering thread faulted, aborting playback");
                }

                Thread.Sleep(100);
            }
            while (true);
        }
예제 #9
0
        public static SampleSource[] CreateFromWaveFile(string fileName)
        {
            using (var reader = new WaveFileReader(fileName))
            {
                ISampleProvider sp;
                int sourceSamples;
                if (reader.WaveFormat.Encoding == WaveFormatEncoding.Pcm)
                {
                    if (reader.WaveFormat.BitsPerSample == 16)
                    {
                        sp = new Pcm16BitToSampleProvider(reader);
                        sourceSamples = (int)(reader.Length / 2);
                    }
                    else if (reader.WaveFormat.BitsPerSample == 24)
                    {
                        sp = new Pcm24BitToSampleProvider(reader);
                        sourceSamples = (int)(reader.Length / 3);
                    }
                    else
                    {
                        throw new ArgumentException("Currently only 16 or 24 bit PCM samples are supported");
                    }
                }
                else if (reader.WaveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
                {
                    sp = new WaveToSampleProvider(reader);
                    sourceSamples = (int)(reader.Length / 4);
                }
                else
                {
                    throw new ArgumentException("Must be PCM or IEEE float");
                }
                float[] sampleData = new float[sourceSamples];
                int n = sp.Read(sampleData, 0, sourceSamples);
                if (n != sourceSamples)
                {
                    throw new InvalidOperationException(String.Format("Couldn't read the whole sample, expected {0} samples, got {1}", n, sourceSamples));
                }

                SampleSource[] result = new SampleSource[9];
                // Normal pitch
                int normal = 4;
                result[normal] = new SampleSource(sampleData, sp.WaveFormat);
                int pitch = 5;

                for (int currentPitch = 0; currentPitch < normal; currentPitch++, pitch--)
                {
                    float[] changedPitchData = new float[sampleData.Length/pitch];
                    for (int j = 0, i = 0; i  < sampleData.Length && j < changedPitchData.Length; i++)
                    {
                        if (i % pitch == 0)
                        {
                            changedPitchData[j] = sampleData[i];
                            j++;
                        }
                    }

                    result[currentPitch] = new SampleSource(changedPitchData, sp.WaveFormat);
                }

                pitch = 2;

                for (int currentPitch = normal+1; currentPitch < result.Length; currentPitch++, pitch++)
                {
                    float[] changedPitchData = new float[sampleData.Length * pitch];
                    for (int j = 0, i = 0; i < sampleData.Length && j < changedPitchData.Length; j++)
                    {
                        changedPitchData[j] = sampleData[i];

                        if (j % pitch == 0)
                        {
                            i++;
                        }
                    }

                    result[currentPitch] = new SampleSource(changedPitchData, sp.WaveFormat);
                }
                return result;
            }
        }