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

New Post: Error when play/stop recording

$
0
0

Hi Mark,
I have a problem with start/stop playing recording.
I have to play a sample which have to be recorded to disk every time it is played because it could be set with different volume level. I do the following:
Play recording:

recorder = new WaveRecorder(file, recordingFileName);
playbackDevice.Init(recorder);
playbackDevice.Play();

Stop playing:
playbackDevice.Stop();

The problem is that if the user press start/stop several times in a hurry. the following error occurred:
NAudio.MmException: AlreadyAllocated calling waveOutOpen

I know that I must avoid Init() waveOut every time I play but I have to do the recording every time because I need it for later use.
How can I properly release these objects when stop playing?


New Comment on "MP3"

$
0
0
Doesn't work here. In a 4.0 WPF, it loads painfully, then the mp3 is playing chunk by chunk.

New Post: Error when play/stop recording

$
0
0

call Dispose when you have finished with any input or output devises

New Post: How to play an a-law-encoded network stream

$
0
0

there is an example of playing a-law from the network in the NAudio source-code. Look at the network streaming demo in the NAudioDemo project. The basic solution is to use a BufferedWaveProvider, and insert audio data into the buffer as it become available from the network

New Post: Error when play/stop recording

$
0
0

I call Dispose only for recorder object. For the playbackDevice I only use 1 instance and just call Play/Stop on every request. I thought it is not a good idea to create new WaveOut instance every time i want to play the recording and then every time call Dispose.

New Post: ASIO input

$
0
0

Hi,

Based on a recent request:

Sorry it's taken a while to get around to this, but here's what I did. It probably isn't good style with respect to the rest of naudio and it's based on what may now be a pretty old revision of the code, but this is most of what I had to do. It's also been ages since I worked on this so my ability to help out with it may be limited.

It expands outputBufferInfos with additional entries for input. outputBufferInfos is now misnamed, but it shouldn't be a breaking change as the output buffers are still at the same indices in the array; the appropriate solution is probably to create a new bufferInfos array and deprecate outputBufferInfos (but assign it to bufferInfos for back compat). Then it'll need wrapping up to support all the appropriate interfaces, but that's beyond me. Otherwise, just listen for ASIOFillBufferCallback, observe the buffer index and read the latter half of the outputBufferInfos array.

In short, it's a terrible hack job. Anyway, here it is.

using System;

namespace NAudio.Wave.Asio
{

    /// <summary>
    /// ASIODriverCapability holds all the information from the ASIODriver.
    /// Use ASIODriverExt to get the Capabilities
    /// </summary>
    internal class ASIODriverCapability
    {
        public String DriverName;  
      
        public int NbInputChannels;
        public int NbOutputChannels;

        public int InputLatency;
        public int OutputLatency;

        public int BufferMinSize;
        public int BufferMaxSize;
        public int BufferPreferredSize;
        public int BufferGranularity;

        public double SampleRate;

        public ASIOChannelInfo[] InputChannelInfos;
        public ASIOChannelInfo[] OutputChannelInfos;
    }

    /// <summary>
    /// Callback used by the ASIODriverExt to get wave data
    /// </summary>
    internal delegate void ASIOFillBufferCallback(IntPtr[] bufferChannels);

    /// <summary>
    /// ASIODriverExt is a simplified version of the ASIODriver. It provides an easier
    /// way to access the capabilities of the Driver and implement the callbacks necessary 
    /// for feeding the driver.
    /// Implementation inspired from Rob Philpot's with a managed C++ ASIO wrapper BlueWave.Interop.Asio
    /// http://www.codeproject.com/KB/mcpp/Asio.Net.aspx
    /// 
    /// Contributor: Alexandre Mutel - email: alexandre_mutel at yahoo.fr
    /// </summary>
    internal class ASIODriverExt
    {
        private ASIODriver driver;
        private ASIOCallbacks callbacks;
        private ASIODriverCapability capability;
        private ASIOBufferInfo[] outputBufferInfos;
        private bool isOutputReadySupport;
        private IntPtr[] currentBuffers;
        private int nbOutputChannels;
        private ASIOFillBufferCallback fillBufferCallback;
        private int bufferSize;
        private int channelOffset;

        /// <summary>
        /// Initializes a new instance of the <see cref="ASIODriverExt"/> class based on an already
        /// instantiated ASIODriver instance.
        /// </summary>
        /// <param name="driver">A ASIODriver already instantiated.</param>
        public ASIODriverExt(ASIODriver driver)
        {
            this.driver = driver;

            if (!driver.init(IntPtr.Zero))
            {
                throw new ApplicationException(driver.getErrorMessage());
            }

            callbacks = new ASIOCallbacks();
            callbacks.pasioMessage = AsioMessageCallBack;
            callbacks.pbufferSwitch = BufferSwitchCallBack;
            callbacks.pbufferSwitchTimeInfo = BufferSwitchTimeInfoCallBack;
            callbacks.psampleRateDidChange = SampleRateDidChangeCallBack;

            BuildCapabilities();
        }

        /// <summary>
        /// Allows adjustment of which is the first output channel we write to
        /// </summary>
        /// <param name="channelOffset">Channel offset</param>
        public void SetChannelOffset(int channelOffset)
        {
            if (channelOffset + nbOutputChannels <= Capabilities.NbOutputChannels)
            {
                this.channelOffset = channelOffset;
            }
            else
            {
                throw new ArgumentException("Invalid channel offset");
            }
       }

        /// <summary>
        /// Gets the driver used.
        /// </summary>
        /// <value>The ASIOdriver.</value>
        public ASIODriver Driver
        {
            get { return driver; }
        }

        /// <summary>
        /// Starts playing the buffers.
        /// </summary>
        public void Start()
        {
            driver.start();
        }

        /// <summary>
        /// Stops playing the buffers.
        /// </summary>
        public void Stop()
        {
            driver.stop();
        }

        /// <summary>
        /// Shows the control panel.
        /// </summary>
        public void ShowControlPanel()
        {
            driver.controlPanel();
        }

        /// <summary>
        /// Releases this instance.
        /// </summary>
        public void ReleaseDriver()
        {
            try
            {
                driver.disposeBuffers();
            } catch (Exception ex)
            {
                Console.Out.WriteLine(ex.ToString());
            }
            driver.ReleaseComASIODriver();
        }

        /// <summary>
        /// Determines whether the specified sample rate is supported.
        /// </summary>
        /// <param name="sampleRate">The sample rate.</param>
        /// <returns>
        /// 	<c>true</c> if [is sample rate supported]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsSampleRateSupported(double sampleRate)
        {
            return driver.canSampleRate(sampleRate);
        }

        /// <summary>
        /// Sets the sample rate.
        /// </summary>
        /// <param name="sampleRate">The sample rate.</param>
        public void SetSampleRate(double sampleRate)
        {
            driver.setSampleRate(sampleRate);
            // Update Capabilities
            BuildCapabilities();
        }

        /// <summary>
        /// Gets or sets the fill buffer callback.
        /// </summary>
        /// <value>The fill buffer callback.</value>
        public ASIOFillBufferCallback FillBufferCallback
        {
            get { return fillBufferCallback; }
            set { fillBufferCallback = value; }
        }

        /// <summary>
        /// Gets the capabilities of the ASIODriver.
        /// </summary>
        /// <value>The capabilities.</value>
        public ASIODriverCapability Capabilities
        {
            get { return capability; }
        }

        /// <summary>
        /// Creates the buffers for playing.
        /// </summary>
        /// <param name="nbOutputChannelsArg">The number of outputs channels.</param>
        /// <param name="useMaxBufferSize">if set to <c>true</c> [use max buffer size] else use Prefered size</param>
        public int CreateBuffers(int nbOutputChannelsArg, bool useMaxBufferSize)
        {
            if (nbOutputChannelsArg <= 0 || nbOutputChannelsArg > capability.NbOutputChannels)
            {
                throw new ArgumentException(String.Format(
                                                "Invalid number of channels {0}, must be in the range [1,{1}]",
                                                nbOutputChannelsArg, capability.NbOutputChannels));
            }

            // each channel needs a buffer info
            nbOutputChannels = nbOutputChannelsArg;
            // Ask for maximum of output channels even if we use only the nbOutputChannelsArg
            int nbTotalChannels = capability.NbInputChannels + capability.NbOutputChannels;
            outputBufferInfos = new ASIOBufferInfo[nbTotalChannels];
            currentBuffers = new IntPtr[nbOutputChannelsArg];

            // and do the same for output channels
            // ONLY work on output channels (just put isInput = true for InputChannel)
            int totalIndex = 0;
            for (int index = 0; index < capability.NbInputChannels; index++, totalIndex++)
            {
                outputBufferInfos[totalIndex].isInput = true;
                outputBufferInfos[totalIndex].channelNum = index;
                outputBufferInfos[totalIndex].pBuffer0 = IntPtr.Zero;
                outputBufferInfos[totalIndex].pBuffer1 = IntPtr.Zero;
            }

            for (int index = 0; index < capability.NbOutputChannels; index++, totalIndex++)
            {
                outputBufferInfos[totalIndex].isInput = false;
                outputBufferInfos[totalIndex].channelNum = index;
                outputBufferInfos[totalIndex].pBuffer0 = IntPtr.Zero;
                outputBufferInfos[totalIndex].pBuffer1 = IntPtr.Zero;
            }

            if (useMaxBufferSize)
            {
                // use the drivers maximum buffer size
                bufferSize = capability.BufferMaxSize;
            }
            else
            {
                // use the drivers preferred buffer size
                bufferSize = capability.BufferPreferredSize;
            }

            unsafe
            {
                fixed (ASIOBufferInfo* infos = &outputBufferInfos[0])
                {
                    IntPtr pOutputBufferInfos = new IntPtr(infos);

                    // Create the ASIO Buffers with the callbacks
                    driver.createBuffers(pOutputBufferInfos, nbTotalChannels, bufferSize, ref callbacks);
                }
            }

            // Check if outputReady is supported
            isOutputReadySupport = (driver.outputReady() == ASIOError.ASE_OK);
            return bufferSize;
        }

        /// <summary>
        /// Builds the capabilities internally.
        /// </summary>
        private void BuildCapabilities()
        {
            capability = new ASIODriverCapability();

            capability.DriverName = driver.getDriverName();

            // Get nb Input/Output channels
            driver.getChannels(out capability.NbInputChannels, out capability.NbOutputChannels);

            capability.InputChannelInfos = new ASIOChannelInfo[capability.NbInputChannels];
            capability.OutputChannelInfos = new ASIOChannelInfo[capability.NbOutputChannels];

            // Get ChannelInfo for Inputs
            for (int i = 0; i < capability.NbInputChannels; i++)
            {
                capability.InputChannelInfos[i] = driver.getChannelInfo(i, true);
            }

            // Get ChannelInfo for Output
            for (int i = 0; i < capability.NbOutputChannels; i++)
            {
                capability.OutputChannelInfos[i] = driver.getChannelInfo(i, false);
            }

            // Get the current SampleRate
            capability.SampleRate = driver.getSampleRate();


            // Get Latencies
            driver.getLatencies(out capability.InputLatency, out capability.OutputLatency);

            // Get BufferSize
            driver.getBufferSize(out capability.BufferMinSize, out capability.BufferMaxSize, out capability.BufferPreferredSize, out capability.BufferGranularity);
        }

        /// <summary>
        /// Callback called by the ASIODriver on fill buffer demand. Redirect call to external callback.
        /// </summary>
        /// <param name="doubleBufferIndex">Index of the double buffer.</param>
        /// <param name="directProcess">if set to <c>true</c> [direct process].</param>
        private void BufferSwitchCallBack(int doubleBufferIndex, bool directProcess)
        {
            for (int i = 0; i < nbOutputChannels; i++)
                currentBuffers[i] = outputBufferInfos[i + channelOffset + capability.NbInputChannels].Buffer(doubleBufferIndex);

            if (fillBufferCallback != null)
                fillBufferCallback(currentBuffers);

            if (isOutputReadySupport)
                driver.outputReady();            
        }

        /// <summary>
        /// Callback called by the ASIODriver on event "Samples rate changed".
        /// </summary>
        /// <param name="sRate">The sample rate.</param>
        private void SampleRateDidChangeCallBack(double sRate)
        {
            // Check when this is called?
            capability.SampleRate = sRate;
        }

        /// <summary>
        /// Asio message call back.
        /// </summary>
        /// <param name="selector">The selector.</param>
        /// <param name="value">The value.</param>
        /// <param name="message">The message.</param>
        /// <param name="opt">The opt.</param>
        /// <returns></returns>
        private int AsioMessageCallBack(ASIOMessageSelector selector, int value, IntPtr message, IntPtr opt)
        {
            // Check when this is called?
            switch (selector)
            {
                case ASIOMessageSelector.kAsioSelectorSupported:
                    ASIOMessageSelector subValue = (ASIOMessageSelector)Enum.ToObject(typeof(ASIOMessageSelector), value);
                    switch (subValue)
                    {
                        case ASIOMessageSelector.kAsioEngineVersion:
                            return 1;
                        case ASIOMessageSelector.kAsioResetRequest:
                            return 0;
                        case ASIOMessageSelector.kAsioBufferSizeChange:
                            return 0;
                        case ASIOMessageSelector.kAsioResyncRequest:
                            return 0;
                        case ASIOMessageSelector.kAsioLatenciesChanged:
                            return 0;
                        case ASIOMessageSelector.kAsioSupportsTimeInfo:
//                            return 1; DON'T SUPPORT FOR NOW. NEED MORE TESTING.
                            return 0;
                        case ASIOMessageSelector.kAsioSupportsTimeCode:
//                            return 1; DON'T SUPPORT FOR NOW. NEED MORE TESTING.
                            return 0;
                    }
                    break;
                case ASIOMessageSelector.kAsioEngineVersion:
                    return 2;
                case ASIOMessageSelector.kAsioResetRequest:
                    return 1;
                case ASIOMessageSelector.kAsioBufferSizeChange:
                    return 0;
                case ASIOMessageSelector.kAsioResyncRequest:
                    return 0;
                case ASIOMessageSelector.kAsioLatenciesChanged:
                    return 0;
                case ASIOMessageSelector.kAsioSupportsTimeInfo:
                    return 0;
                case ASIOMessageSelector.kAsioSupportsTimeCode:
                    return 0;
            }
            return 0;            
        }
        /// <summary>
        /// Buffers switch time info call back.
        /// </summary>
        /// <param name="asioTimeParam">The asio time param.</param>
        /// <param name="doubleBufferIndex">Index of the double buffer.</param>
        /// <param name="directProcess">if set to <c>true</c> [direct process].</param>
        /// <returns></returns>
        private IntPtr BufferSwitchTimeInfoCallBack(IntPtr asioTimeParam, int doubleBufferIndex, bool directProcess)
        {
            // Check when this is called?
            return IntPtr.Zero;   
        }
    }
}

New Post: How to play an a-law-encoded network stream

$
0
0

Hi Mark,

inspired by the network streaming demo (NetworkChatPanel.cs) I simplified the code like this:

BufferedWaveProvider myBufferedWaveProvider = new BufferedWaveProvider(WaveFormat.CreateALawFormat(8000, 1));
WaveOut myWaveOut = new WaveOut();
myWaveOut.Init(myBufferedWaveProvider);
myWaveOut.Play();

Now an MMException (WaveBadFormat calling waveOutOpen) is thrown in myWaveOut.Init(). I'm wondering about the WaveBadFormat, because at this time the buffer does contain no samples at all.

Any idea?

Norbert

New Post: How do i create a wave viewer without having to play the music?

$
0
0

I'm new to NAudio and need to create a wave viewer, but do not want to play the selected song,

How do you doing?

 

Tanks.

 

PS: I'm developing from the demo version, I can I do?


New Post: How to play an a-law-encoded network stream

$
0
0

You can't directly play A-law audio. At some point it must be converted to PCM with a WaveFormatConversionStream. You can do that either before you put it into the BufferedWaveProvider, or convert it afterwards.

New Post: How do i create a wave viewer without having to play the music?

$
0
0

you just need to call the Read method repeatedly on the WaveProvider that you would normally give to WaveOut. This pulls all the audio data through and the events that the waveform drawer is listening to will fire

New Post: ASIO input

$
0
0

thanks for this, I'll refer back to this when I get round to adding ASIO in support which is long overdue

Commented Issue: NAudio resampler exception when deployed to Azure [16350]

$
0
0
I'm resampling wav file for my web app using ResamplerDmoStream. This works fine running locally, but I'm getting a registration error when deployed to Azure:

Exception thrown = System.Runtime.InteropServices.COMException (0x80040154): Retrieving the COM class factory for component with CLSID {F447B69E-1884-4A7E-8055-346F74D6EDB3} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
at NAudio.Dmo.Resampler..ctor()
at NAudio.Wave.ResamplerDmoStream..ctor(IWaveProvider inputProvider, WaveFormat outputFormat)

I'm using version 1.5.4 of NAudio.dll. Thanks!
Comments: this is because the DMO resampler COM object does not exist on Azure. You could try using the WaveFormatConversionStream instead

New Post: How do i create a wave viewer without having to play the music?

New Post: Merge/mix several wav files into one

$
0
0

Hi,

 

I have several wav files (for instance, 60 files) that I need to mix into one WAV file, but not by concatenating the wav files, but instead, every wav file must be placed on a specific position like in a movie timeline. I hope I explained clearly.

 

Is this possible ? Is there a demo that I can take a look ?

 

TIA

 

 

New Post: Merge/mix several wav files into one

$
0
0

yes, you can do this with NAudio, but I'm afraid there is no demo.

You build an audio graph like this:

1) each WAV file is converted into a 32 bit floating point stream
2) you then use a WaveStream/WaveProvider that can prepend silence to position your inputs relative to one another
3) you use a mixer stream to mix them together
4) you optionally go back down to 16 bit audio

NAudio has WaveChannel32 for steps 1&2, WaveMixerStream32 for step 3 and Wave32To16Stream for step 4, so you can use them.

You can also do this with ISampleProvider based classes, but you have to make a class to do step 2 yourself.

Mark


New Post: Merge/mix several wav files into one

$
0
0

Thank you for your answer.

 

Some of the wav files overlaps, that is to say, maybe the position of a wav file is between the start and end position of another wav file. Point 2) needs some modification, because there is no silence ?

 

TIA

 

New Post: Merge/mix several wav files into one

$
0
0

that is not a problem. the amount of silence is measured from the start of the mixed WAV. it doesn't matter if there are overlaps, since everything will be mixed

New Post: Multimedia application list

$
0
0

Is it possible with NAudio to get a list of all running multimedia applications, i.e. the applications which appear in the standard Windows 7 speakers volume mixer window?

Currently I can get the speakers MMDevice itself, but not the registered applications down below.

Norbert

New Post: change frequency at runtime

$
0
0

Here is the code of the wavetone class:

  public class WaveTone : WaveStream
{
private double frequency;
private double amplitude;
private double time;

public WaveTone(double f, double a)
{
this.time = 0;
this.frequency = f;
this.amplitude = a;
}

public override long Position
{
get;
set;
}

public override long Length
{
get { return long.MaxValue; }
}

public override WaveFormat WaveFormat
{
get { return new WaveFormat(44100, 16, 1); }
}

public override int Read(byte[] buffer, int offset, int count)
{
int samples = count / 2;
for (int i = 0; i < samples; i++)
{
double sine = amplitude * Math.Sin(Math.PI * 2 * frequency * time);
time += 1.0 / 44100;
short truncated = (short)Math.Round(sine * (Math.Pow(2, 15) - 1));
buffer[i * 2] = (byte)(truncated & 0x00ff);
buffer[i * 2 + 1] = (byte)((truncated & 0xff00) >> 8);
}

return count;
}
}

New Post: How to play multiple wave files simultaniously using ASIO

$
0
0

Hi ,

  I tried this but I am not getting this please provide me with some samples which will be really helpful.

 

Thanks in advance

Viewing all 5831 articles
Browse latest View live


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