Quantcast
Channel: NAudio
Viewing all 5831 articles
Browse latest View live

New Post: Stopped playing event

$
0
0
I have a problem knowing when a source stream has stopped playing. If one is playing a single source stream into a WaveOut device then it is easy, just catch the event the WaveOut raises. My signal chain is a little more complex than that since I have multiple source streams being played through a mixer to the WaveOut. Basically what I have is Other providers may be added later):

<AudioFileReader><FadeInOutSampleProvider><MixingSampleProvider><WaveOut>

The MixingSampleProvider can have multiple inputs.

The FadeInOutSampleProvider I have modified to return zero bytes when it enters "Silence" state.

My issue is that I need to know when the source is silenced at the end of a fade out so that the source and that signal chain may be disposed where necessary. The fade out can occur at almost any time because the application sequences a number of files and some of the files are marked to be "exclusive" so any playing file must be faded out and then any resources used by it disposed.

Is there a way of detecting this? It seems that the "MixingSampleProvider" is almost doing this when the "ReadFully" property is true, it removes the input from the mixer. Maybe a solution is to add an event when this occurs?

Any ideas would be much appreciated,
Sid

New Post: AdsrSampleProvider Not Producing Adsr Effect

$
0
0
Adapting AdsrSampleProvider for stereo was fairly simple. I just modified a few lines of code in the AdsrSampleProvider class Read method. This mod was based on the code in the FadeInOutSampleProvider class so I don't claim any points for original thinking.
       public int Read(float[] buffer, int offset, int count)
        {
            if (adsr.State == EnvelopeGenerator.EnvelopeState.Idle) return 0; // we've finished
            var samples = source.Read(buffer, offset, count);
            int sample = 0;
            int numChannels = source.WaveFormat.Channels;
            float adsrValue = 1.0f;

            while (sample < count)
            {
                adsrValue = adsr.Process();
                for (int ch = 0; ch < numChannels; ch++)
                {
                    buffer[offset + sample++] *= adsrValue; 
                }
            }
            return samples;
        }

New Post: My program gets very slow to respond/stuck while fft is calculated

$
0
0
Im trying to get the pitch of microphone input in real time. I have a capture base class which includes the sample rate, channels etc., and the sample aggregator class has taken from Mark's WPF demo

Capture Base
    public class CaptureBase : IDisposable
    {
        static int fftLength = 1024;
        const int samplingFrequency = 44100;
        const int channels = 1;
        const int noOfBuffers = 5;
        const int bufferMilisecs = 10;
        const int latency = 50;
        WaveIn sourceStream;
        DirectSoundOut soundOut;
        SampleAggregator sampleAggregator;
        bool disposed = false;
        bool isCapturing = false;

        public void StartCapture(Guid selectedDevice)
        {
            isCapturing = true;
           
            sampleAggregator = new SampleAggregator(fftLength);
            sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated);
            sampleAggregator.PerformFFT = true;

            sourceStream = new WaveIn();
            sourceStream.NumberOfBuffers = noOfBuffers;
            sourceStream.BufferMilliseconds = bufferMilisecs;
            sourceStream.WaveFormat = new WaveFormat(samplingFrequency, channels);
            sourceStream.DataAvailable += new EventHandler<WaveInEventArgs>(sourceStream_DataAvailable);
            sourceStream.StartRecording();
        }

        private void FftCalculated(object sender, FftEventArgs e)
        {
            for (var i = 0; i < e.Result.Length; i++)
            {
                Debug.WriteLine("FFT output.");
                Debug.WriteLine(e.Result[i].X);
                Debug.WriteLine(e.Result[i].Y);
                //Analysis.HPS hps = new Analysis.HPS();
                //hps.HarmonicProductSpectrum(e.Result);
            }
        }

        public SampleAggregator SampleAggregator
        {
            get
            {
                return sampleAggregator;
            }
        }
      
        private void sourceStream_DataAvailable(object sender, WaveInEventArgs e)
        {
            byte[] buffer = e.Buffer;
            int bytesRecorded = e.BytesRecorded;
           
            for (int i = 0; i < e.BytesRecorded; i += 2)
            {
                short sample = (short)((buffer[i + 1] << 8) | buffer[i + 0]);
                float sample32 = (sample / 32758f);
                sampleAggregator.Add(sample32);
            }
        }

        public void Stop()
        {
            if (isCapturing)
            {
                isCapturing = false;
            }
        }

        public void Dispose(bool disposing)
        {
            if (disposed) return;

            disposed = true;
            GC.SuppressFinalize(this);
            if (isCapturing) Stop();
        }

        void IDisposable.Dispose()
        {
            Dispose(true);
        }
    }
}
Sample Aggregator
 public class SampleAggregator
    {
        private readonly Complex[] fftBuffer;
        private readonly FftEventArgs fftArgs;
        private int fftPos;
        private readonly int fftLength;
        private int m;
        public event EventHandler<FftEventArgs> FftCalculated;

        public bool PerformFFT { get; set; }

        public SampleAggregator(int fftLength)
        {
            if (!IsPowerOfTwo(fftLength))
            {
                throw new ArgumentException("FFT Length must be a power of two");
            }
            this.m = (int)Math.Log(fftLength, 2.0);
            this.fftLength = fftLength;
            this.fftBuffer = new Complex[fftLength];
            this.fftArgs = new FftEventArgs(fftBuffer);
        }

        bool IsPowerOfTwo(int x)
        {
            return (x & (x - 1)) == 0;
        }

        public void Add(float value)
        {
            if (PerformFFT && FftCalculated != null)
            {
                // Remember the window function! There are many others as well.
                fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HammingWindow(fftPos, fftLength));
                fftBuffer[fftPos].Y = 0; // This is always zero with audio.
                fftPos++;
                if (fftPos >= fftLength)
                {
                    fftPos = 0;
                    FastFourierTransform.FFT(true, m, fftBuffer);
                    FftCalculated(this, fftArgs);
                }
            }
        }
    }

    public class FftEventArgs : EventArgs
    {
        [DebuggerStepThrough]
        public FftEventArgs(Complex[] result)
        {
            this.Result = result;
        }
        public Complex[] Result { get; private set; }
    }
}
}
Please can someone explain what i have done wrong.

New Post: Error: WaveOut auto stop

$
0
0
Hi All,

I am developing a software based on NAudio. I use WaveOut, BufferedWaveProvider and MixingSampleProvider to play multi recorded sound data. Sometime, WaveOut stop, I can not detect PlaybackStopped event. Does anyone know how to detect WaveOut errors?

Full my code (run on .Net Framework 4.0):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Threading;
using NAudio.Wave;
using NAudio;
using NAudio.Wave.SampleProviders;
using System.Diagnostics;
using System.Windows.Forms;

namespace Teaching_Tool_Client
{
class PlayAudio
{
    public static int sampleRate = 8000;


    private static WaveOut waveOut = null;
    private static MixingSampleProvider mix = null;
    private static BufferedWaveProvider bufferWaveOut = null;
    public static Queue<byte[]> audioBufferQueue = new Queue<byte[]>();

    private static BufferedWaveProvider bufferWaveOut1 = null;
    public static Queue<byte[]> audioBufferQueue1 = new Queue<byte[]>();

    public static string waveOutStatus = "";

    private static Thread threadPlay = null;

    public static void Play()
    {

        try
        {

            WaveFormat format = WaveFormat.CreateIeeeFloatWaveFormat(8000, 1);

            bufferWaveOut = new BufferedWaveProvider(new WaveFormat(sampleRate, 1));
            bufferWaveOut1 = new BufferedWaveProvider(new WaveFormat(sampleRate, 1));

            bufferWaveOut.BufferLength = 5000;
            bufferWaveOut1.BufferLength = 5000;

            bufferWaveOut.DiscardOnBufferOverflow = true;
            bufferWaveOut1.DiscardOnBufferOverflow = true;

            mix = new MixingSampleProvider(format);
            mix.ReadFully = true;

            mix.AddMixerInput(bufferWaveOut);
            mix.AddMixerInput(bufferWaveOut1);

            waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());
            //waveOut = new WaveOut();
            waveOut.PlaybackStopped += new EventHandler<StoppedEventArgs>(WaveOutStopEvent);

            waveOut.Init(mix);
            waveOut.Play();


            // add sound buffer vào waveOutBuffer
            //while (waveOut.PlaybackState == PlaybackState.Playing)
            while(true)
            {
                if (audioBufferQueue.Count > 0)
                {
                    byte[] buffer = audioBufferQueue.Dequeue();
                    bufferWaveOut.AddSamples(buffer, 0, buffer.Length);
                }

                if(audioBufferQueue1.Count>0)
                {
                    byte[] buffer1 = audioBufferQueue1.Dequeue();
                    bufferWaveOut1.AddSamples(buffer1, 0, buffer1.Length);
                }

                Thread.Sleep(20);


                //waveOutStatus = bufferWaveOut.BufferedBytes.ToString();


            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("play: " + ex.Message);

            // tạm nghỉ
            Thread.Sleep(50);

            // stop
            Stop();

            // chạy lại
            Thread t = new Thread(a => PlayAudio.Play());
            t.Start();
        }
    }


    private static void WaveOutStopEvent(object sender, StoppedEventArgs e)
    {
        MessageBox.Show("Error to stop");
    }
    public static void Stop()
    {
        try
        {
            if (waveOut != null)
            {
                if (waveOut.PlaybackState == PlaybackState.Playing || waveOut.PlaybackState == PlaybackState.Paused)
                    try
                    {
                        waveOut.Stop();
                        waveOut.Dispose();
                    }
                    catch (Exception ex) { }
            }
        }
        catch (Exception ex1) { }
    }


}
}

New Post: Stopped playing event

$
0
0
yes, for playback to stop, the provider being passed to WaveOut must return 0 from the Read method. To dispose mixer inputs, I've sometimes created a simple wrapper using the decorator pattern, that converts an ISampleProvider into something that can run a custom action after its Read method returns 0. In the future I'd like to add a better way of handling this in the MixingSampleProvider (probably raising events when inputs are removed).

New Post: FadeInOutSampleProvider

$
0
0
Yes, that would be a helpful addition to FadeInOutSampleProvider.

New Post: Synchronizing play starting time with PC clock

$
0
0
Hi,

Very new to NAudio…
I have a few ready wave files (.wav) which I need to play (about 10 files, each ~1 second long)
The only tricky requirement (at least tricky for me) is that I need to control (synchronize) the exact timing (tick count) at which the audio actually starts playing.
I care less about large latencies.
Alternatively if that is not feasible, querying and retroactively obtaining the “Audio Start timestamp” anytime during the playback is also fine.
The only important thing is for that timestamp to be accurate and reliable at a millisecond resolution.
The purpose of this is to accurately measure the time elapsing between that audio signal and some response from the user.
I mentioned the small sized wave files which I use because any solution requiring pre-loading / caching / initializing stuff beforehand would also be great.

Many thanks!!!
J (-:

New Post: How to create waveform of full audio

$
0
0
Can the above process be executed on a video file or is it necessary to first convert the video file to audio?

New Post: Stopped playing event

$
0
0
Mark, Since I wrote this I have reorganized my signal chain a little because I needed to have sample rate conversion and also handle mono files seamlessly. Inspired by your SampleChannel I have put together a channel signal flow that meets my needs. Each of these channels feeds the MixiingSampleProvider and I made a small change to that class to add an EndOfMedia event that is raised when the "read" method returns zero samples My mixer class then catches this event and takes the required action. It was very simple to add requiring only the definition of the event and raising it at the appropriate place.
    public class MixerEndOfMediaEventArgs : EventArgs
    {
        /// <summary>
        /// The stream that ended
        /// </summary>
        public ISampleProvider source {get;set;}
    }

    public event EventHandler<MixerEndOfMediaEventArgs> EndOfMedia;
And this small update to the "Read" method of MixingSampleProvider:
                    if (samplesRead == 0)
                    {
                        args.source = sources[index];
                        EndOfMedia(this,args);
                        sources.RemoveAt(index);
                    }
                    index--;
Sid

New Post: Try this Reverb ISampleProvider

$
0
0
Hi All,
I wrote a Reverb ISampleProvider.
You can down load it here if you want to play with it or modify it for your own use. You should be able to drop this class into any NAudio project and try it out.

Download link: http://breakthrusoftware.com/downloads/Utils/ReverbSampleProvider.txt

I'm hoping this will inspire others to write some other FX Effects for NAudio and post them here for open source use. My pipe dream is to see a set of NAudio implementations that cover the DirectX FX effects: chorus / compressor / distortion / echo / flanger / gargle / parametric eq / reverb

If you try the code, let me know what you think: ways it can be improved, bugs, etc.

Here is the sample code to run it. Just fill in an MP3 filename.
        string fname = @"MyAudio.mp3";

            WaveOut outputDeviceWaveOut = new WaveOut()
            {
                DesiredLatency = 300,
                NumberOfBuffers = 2,
            };
            outputDeviceWaveOut.DeviceNumber = 0;
            IWavePlayer waveOutDevice = outputDeviceWaveOut;
            AudioFileReader afrFile = new AudioFileReader(fname);  // sampler reader           
            ReverbSampleProvider reverbSamplr = new ReverbSampleProvider(afrFile);
            // change these properties for different effect
            reverbSamplr.ReverbLevel = 1.0f;  
            reverbSamplr.ReverbDepth = 4;
            reverbSamplr.DirectSignalLevel = 1.0f;
            reverbSamplr.Gain =  1.0f;
            waveOutDevice.Init(reverbSamplr);
            waveOutDevice.Play();

New Post: Try this Reverb ISampleProvider

$
0
0
Cool, a delay line based reverb using several combs. I´ve also created some effects, e.g. yesterday I completed a pitch shifting sampleprovider with the c# port of stephan m. bernsee´s shifter class (SMBPitchShifter C# Port):
Imports NAudio.Wave

Public Class SMBPitchShiftingSampleProvider
    Implements ISampleProvider

    Private SourceStream As ISampleProvider = Nothing
    Private WFormat As WaveFormat = Nothing
    Private Pitch As Single = 1.0F
    Private _FFTSize As Integer = Nothing
    Private _osamp As Long = Nothing
    Private ShifterLeft As New SMBPitchShifter()
    Private ShifterRight As New SMBPitchShifter()
    Private volscale As Single = 1.0F 'Recommended to scale volume down, as SMB seems to clip with pitching

    Sub New(ByVal SourceProvider As ISampleProvider, ByVal FFTSize As Integer, ByVal osamp As Long, Optional ByVal InitialPitch As Single = 1.0F)
        SourceStream = SourceProvider
        WFormat = SourceProvider.WaveFormat
        _FFTSize = FFTSize
        _osamp = osamp
        Pitch = InitialPitch
    End Sub

    Public Function Read(ByVal buffer() As Single, ByVal offset As Integer, ByVal count As Integer) As Integer Implements NAudio.Wave.ISampleProvider.Read
        Dim SampRead = SourceStream.Read(buffer, offset, count)
        If Pitch = 1.0F Then Return SampRead 'Nothing to do.
        'If offset <> 0 Then Throw New Exception("Offset is not taking into account with this pitch shifter!")
        If WFormat.Channels = 1 Then
            ShifterLeft.PitchShift(Pitch, SampRead, _FFTSize, _osamp, WFormat.SampleRate, buffer)
            Return SampRead
        ElseIf WFormat.Channels = 2 Then
            Dim Left As Single() = New Single((SampRead / 2) - 1) {}
            Dim Right As Single() = New Single((SampRead / 2) - 1) {}

            Dim index As Integer = 0
            For sample As Integer = 0 To SampRead - 1 Step 2
                Left(index) = buffer(sample)
                Right(index) = buffer(sample + 1)
                index += 1
            Next
            ShifterLeft.PitchShift(Pitch, SampRead / 2, _FFTSize, _osamp, WFormat.SampleRate, Left)
            ShifterRight.PitchShift(Pitch, SampRead / 2, _FFTSize, _osamp, WFormat.SampleRate, Right)
            index = 0
            For sample As Integer = offset To SampRead - 1 Step 2
                buffer(sample) = Left(index) * volscale
                buffer(sample + 1) = Right(index) * volscale
                index += 1
            Next
            Return SampRead
        End If
    End Function

    Public ReadOnly Property WaveFormat() As NAudio.Wave.WaveFormat Implements NAudio.Wave.ISampleProvider.WaveFormat
        Get
            Return WFormat
        End Get
    End Property

    Public Property PitchFactor() As Single
        Get
            Return Pitch
        End Get
        Set(ByVal value As Single)
            Pitch = value
            ScaleVolume()
        End Set
    End Property

    Private Sub ScaleVolume()
        If Pitch > 1.0F Then
            volscale = 1.0F / Pitch
        Else
            volscale = Pitch
        End If
    End Sub
End Class
The PitchShifter of above link must be changed to non-static (simply remove all "shared"/"static" keywords) and I called the class "SMBPitchShifter" after its author.

The output has a bit "phasy" transposing, but sounds not bad and very interestingly. And, compared to soundtouch, no choppy double samples when beats are missed. As a con, sound output seems a bit compressed and overdrives with shifting distance (I try to face this with a linear volume scaling, but is not ideal).

Usage:
'4096 = FFT Size recommended; 8L = Oversampling Quality; 1.5f = half octave higher shifted;
Dim SMB = New SMBPitchShiftingSampleProvider(new AudioFileReader("<Path to your audio file>"), 4096, 8L, 2.0f)
Dim WaveOut as New WaveOut()
WaveOut.Init(SMB);
WaveOut.Play();
I´ll try your Reverb, thx for posting.


EDIT: I forgot to implement, for thread safety you must Lock around the get Node of the "PitchFactor" property and the complete read method.

New Post: Try this Reverb ISampleProvider

$
0
0
Ok, I tried your reverb. It throws an error here:
            while (offset < count)
            {
                for (int ch = 0; ch < numChannels; ch++)
                {
                    currOffset = offset++; // + sample;
                    inValue = buffer[currOffset];
                    modValue = Process(inValue);
                    //modValue = FxUtils.NormalizeTo1toNeg1(modValue);
                    buffer[currOffset] = modValue; // 
                }
            }
I changed it to:
            while (offset < count - 2)
            {
                     ...
            }
to get it working. The effect itself sounds a bit too hard and overdrives, I recommend at first sight two things:
  • Use prime numbers for delay lengths to avoid overlap
  • Use varying dampening, don´t scale it linearly
A good example is the standford NReverb class, here is a C# port: https://github.com/keijiro/unity-custom-reverb-filter/blob/master/Assets/Standard%20Assets/NReverb.cs

New Post: Try this Reverb ISampleProvider

$
0
0
Hi Freefall,
Thanks I'll take a look at both of those links. The pitch shifter looks very interesting. I'll try that tomorrow.

Thanks for testing the reverb class and reporting that error.
I've been testing with several MP3s and never got that error. I probably should have incremented the offset AFTER the sample is processed ( currOffset = offset++) , not BEFORE.

And thanks for the enhancement suggestions. I admit I'm a novice at effects.

New Post: Tasks: Cut, Merge, Transcript

$
0
0
Download Mp3-Mp4 from youtube or spotify.

Then Cut mp3s-mp4 files, and then merge fragments ?

Transcript MP3s to Text ?

New Post: Try this Reverb ISampleProvider

$
0
0
I´ve added thread safety and fixed the missing inital volume scaling in above code, see Edit 2.

I also created a SampleProvider that allows to modify speed scaling without altering the pitch. I can post it here if there is an interest in this.

For both pitch and speed I´ve been making two versions, one using the frequency domain phase vocoder of the stephan m. bernsee (smb) implementation (see above) and one using the time domain overlap and add method of soundtouch surina.

Note, that there is a fully managed port of soundtouch available here, so both are possible to include statically. Each of them has its pros and cons, which would lead too far here. The best way to decide is to try them out.

New Post: Try this Reverb ISampleProvider

$
0
0
this is awesome. looking forward to giving it a try. thanks for sharing

Created Unassigned: DirectSoundOut.Devices.Count() [16497]

$
0
0
Here is the code

Dim dscount As Integer = 0
dscount = DirectSoundOut.Devices.Count()

dscount value is 8. the correct value is 4.
if i see in watch window and evaluate expression " DirectSoundOut.Devices.Count() " then it gives integer and value 4.

What is wrong?

Edited Unassigned: DirectSoundOut.Devices.Count() returns wrong value [16497]

$
0
0
Here is the code

Dim dscount As Integer = 0
dscount = DirectSoundOut.Devices.Count()

dscount value is 8. the correct value is 4.
if i see in watch window and evaluate expression " DirectSoundOut.Devices.Count() " then it gives integer and value 4.

What is wrong?

Commented Unassigned: DirectSoundOut.Devices.Count() returns wrong value [16497]

$
0
0
Here is the code

Dim dscount As Integer = 0
dscount = DirectSoundOut.Devices.Count()

dscount value is 8. the correct value is 4.
if i see in watch window and evaluate expression " DirectSoundOut.Devices.Count() " then it gives integer and value 4.

What is wrong?
Comments: WaveOut.DeviceCount works correct!

Commented Unassigned: DirectSoundOut.Devices.Count() returns wrong value [16497]

$
0
0
Here is the code

Dim dscount As Integer = 0
dscount = DirectSoundOut.Devices.Count()

dscount value is 8. the correct value is 4.
if i see in watch window and evaluate expression " DirectSoundOut.Devices.Count() " then it gives integer and value 4.

What is wrong?
Comments: Here is a code section with watch window.
Viewing all 5831 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>