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

New Post: midi instruments

$
0
0
the third parameter is the MIDI channel number and there are only 16 channels
so you'd need to send a patch change message first to one of the channels
and then send a start note to that channel

New Post: Midi playing with Timer

$
0
0
Hello,

I've recently been fiddling around with creating a multitrack wave player using NAudio.
(Tracks are mixed using a customized MixingSampleProvider that also incorporates track pan, volume, etc.)

Since I finally got everything working reasonably well through WaveOut, I'm thinking about adding Midi since NAudio provides excellent Midi file event handling capabilities.
(Incidentally, using Mark's PianoRoll (Part2) as a base, I've gotten the Midi data adequately visualized.)

But I'm not sure exactly how to play the Midi in synch with my WaveOut...
I imagine it will involve a timer (I'm already implementing a custom timer which I use for time display and movement of a play position marker), and sending MidiMessage.StartNote, etc. to the designated MidiOut device?
If so, any ideas on the best way to go about it?

My timer already updates a "PlayPosition" property (in milliseconds), so I have that.
So, my first thought is to cycle through each midi NoteOn event, and play it if the PlayPosition is between its AbsoluteTime and the next noteoff, but that seems like the most poorly efficient way to do it.

There's a much better way, isn't there...?

New Post: MeteringSampleProvider and AsioOut

$
0
0
Hello, I have managed to combine NAudio's MixingSampleProvider and MeteringSampleProvider together into one class, in order to provide a volume peak display for the sample provider in real time.

It actually works as expected but only if I use WaveOut.
If I use AsioOut instead, when the AsioOut is played I get an error to the effect that "This object belongs to a different thread, and the calling thread cannot access the object".
(No such error occurs with WaveOut)

The following is the Read Function of my custom ISampleProvider (translated from VB to C#):
public int Read(float[] buffer, int offset, int count)
{
    int outputSamples = 0;
    this.sourceBuffer = BufferHelpers.Ensure(this.sourceBuffer, count);
    lock (sources) {
        //cycle through each input source, backwards
        for (int sourceindex = sources.Count - 1; sourceindex >= 0; sourceindex += -1) {

            if (sources(sourceindex).hasData) {
                int samplesRead = sources(sourceindex).Read(this.sourceBuffer, 0, count);
                int outIndex = offset;

                for (int inIndex = 0; inIndex <= samplesRead - 2; inIndex += 2) {
                    if (inIndex >= outputSamples) {
                        buffer(outIndex) = this.sourceBuffer(inIndex) * MasterVolFac;
                        buffer(outIndex + 1) = this.sourceBuffer(inIndex + 1) * MasterVolFac;
                    } else {
                        buffer(outIndex) += this.sourceBuffer(inIndex) * MasterVolFac;
                        buffer(outIndex + 1) += this.sourceBuffer(inIndex + 1) * MasterVolFac;
                    }
//*******************  for metering display
                    if (ShowOutputMeters) {
                        for (int chno = 0; chno <= channels - 1; chno++) {
                            thissampleValue = Math.Abs(buffer(offset + inIndex + chno));
                            maxSamples(chno) = Math.Max(maxSamples(chno), thissampleValue);
                            sampleCount += 1;
                            if (sampleCount >= SamplesPerNotification) {
                                if (StreamVolume != null) {
                                    StreamVolume(this, args);
                                }
                                sampleCount = 0;
                                Array.Clear(maxSamples, 0, channels);
                            }
                        }
                    }
                    //******************
                    outIndex += 2;
                }

                outputSamples = Math.Max(samplesRead, outputSamples);

            }

        }

    }

    return outputSamples;
}
Cheers,
Michael

New Post: WASAPI recording basics

$
0
0
In case one is making a recording app, one use case scenario can be that the user may want to record then seek back (reverse) and overwrite a part which he wants to be corrected. This may require seek in the WaveFileWriter.

New Post: Midi playing with Timer

$
0
0
Ok, somewhat later I figured out at least one better way which when crudely implemented seems to work properly....

I keep a "CurrentIndex" for the MidiEvents, and every time the timer ticks, it checks if MidiEvent(CurrentIndex).AbsoluteTime is < or = the PlayPosition.
If it is, it sends the MidiMessage.StartNote for that note, and increments the CurrentIndex by 1.
So, next timer tick, it simply checks the incremented MidiEvent(CurrentIndex), and so on.

(Now just have to modify that to include program changes, and especially note off events...)

I assume in theory that's that the best way to do it...?

New Post: midi instruments

$
0
0
Thank you for your message! I will try to find information about the patch change message!

Best regards, g.

New Post: How to dispose MMDeviceEnumerator / MMDevice

$
0
0
MMDeviceEnumerator is not disposable. Garbage collection does nothing if I set device to null. (v1.7.3.0)

New Post: Missing WaveOut in UWP Projects

$
0
0
Hi,

I'm, trying to convert an app which uses NAudio to the UWP (Universal Windows Platform) platform. I have installed the Nuget package for NAudio to my UWP solution, but the WaveOut object no longer seems to exist.

Has this been removed for UWP projects? If so what is the alternative and is there any documentation on this? If not then does anyone know why it appears to be missing. I have exactly the same version (1.7.3) running just fine in a standard Windows Forms app so it definitely seems to be a problem related to the UWP platform.

Many thanks,

Damien

New Post: Mp3FileReader not returning CurrentTime and Position

$
0
0
I was using the following routine to trim (grab pieces of) MP3 files. Not sure when it stopped working, but now I find that no matter how many ReadNextFrames I issue the reader.CurrentTime and reader.Position remain 0. I'm running on Windows 10 Prof, and using Visual Studio 2013. I've tried the code with Naudio 1.7, 1.7.2, and 1.7.3 - same result. Any ideas as to where I'm going wrong would be appreciated. Here's the code ...
 public static void TrimMp3File(string inputPath, string outputPath, TimeSpan? begin, TimeSpan? end)
        {
            //  This routine trims an MP3 file
            //     Ref: http://stackoverflow.com/questions/7932951/trimming-mp3-files-using-naudio
            //             original code from Mark Heath (Naudio creator)

            // ********************** DEBUG: Start ************************* 
            TimeSpan Zero = new TimeSpan(0,0,0);  
            TimeSpan CurrentTime;
            TimeSpan CalculatedCurrentTime, CalculatedCurrentTimeBasedOnBytesRead;
            bool ProbePoint; 
            long BytesRead = 0;
            // **********************  DEBUG: End  *************************                                             

            if (begin.HasValue && end.HasValue && begin > end)
                throw new ArgumentOutOfRangeException("end", "end should be greater than begin");

            using (var reader = new Mp3FileReader(inputPath))
            {
                using (var writer = File.Create(outputPath))
                {
                    Mp3Frame frame;
                    while ((frame = reader.ReadNextFrame()) != null)
                    {
                        // ********************** DEBUG: Start **************************
                        //  BUG: reader.Position and reader.CurrentTime are never updated
                        // ************************************************************** 
                        CurrentTime = reader.CurrentTime;  
                        CalculatedCurrentTime = TimeSpan.FromSeconds((double)reader.Position / reader.WaveFormat.AverageBytesPerSecond); 
                        BytesRead += frame.RawData.Length;
                        CalculatedCurrentTimeBasedOnBytesRead = TimeSpan.FromSeconds((double)BytesRead / reader.WaveFormat.AverageBytesPerSecond); ;
                        if (CurrentTime != Zero) 
                        {
                           ProbePoint = true ;
                        }  
                        // **********************  DEBUG: End  *************************

                        if (reader.CurrentTime >= begin || !begin.HasValue)
                        {
                            if (reader.CurrentTime <= end || !end.HasValue)
                                writer.Write(frame.RawData, 0, frame.RawData.Length);
                            else break;
                        }

                    }

                }
            }
            
        }

New Post: Mp3FileReader not returning CurrentTime and Position

$
0
0
As a work around, I altered the program to calculate it's own CurrentTime rather than relying on reader.CurrentTime as follows.
I'm back in business ...

public static void TrimMp3File(string inputPath, string outputPath, TimeSpan? begin, TimeSpan? end)
        {
            //  This routine trims an MP3 file
            //     Ref: http://stackoverflow.com/questions/7932951/trimming-mp3-files-using-naudio
            //            * original code from Mark Heath (Naudio creator)
            //          http://stackoverflow.com/questions/6220660/calculating-the-length-of-mp3-frames-in-milliseconds
            //            * frame length in ms formula: lucianolev

            double currentSecond = 0.0D; //                                         2016-11-26: Start - fix: replaced reliance on reader.CurrentTime (which is not being updated)
            double beginSecond = 0.0D;   //                                                                  with the calculated currentSecond.
            double endSecond = 9999.0D;                                                             
            TimeSpan totalDuration = new TimeSpan(0, 0, 0); //                      2016-11-26: End
           
            if (begin.HasValue && end.HasValue && begin > end)
                throw new ArgumentOutOfRangeException("end", "end should be greater than begin");

            using (var reader = new Mp3FileReader(inputPath)) {
                totalDuration = reader.TotalTime; //                                2016-11-26: Start
                if (begin.HasValue) beginSecond = ((TimeSpan)begin).TotalSeconds;
                if (end.HasValue) endSecond = ((TimeSpan)end).TotalSeconds;
                else endSecond = totalDuration.TotalSeconds; //                     2016-11-26: End
                
                using (var writer = File.Create(outputPath)) {
                    Mp3Frame frame;
                    while ((frame = reader.ReadNextFrame()) != null) {
                         currentSecond += ((double)frame.SampleCount / (double)frame.SampleRate); //    2016-11-26
                         if (currentSecond >= beginSecond) { //                                         2016-11-26                                                    
                            if (currentSecond <= endSecond)  //                                         2016-11-26
                                writer.Write(frame.RawData, 0, frame.RawData.Length);
                            else break;
                        }
                    }
                }
            }
        }

New Post: SoundFont presets

$
0
0
Hi,
Im using the NAudio SoundFont class to access the parts of an sf2 file.
I see how to access the SampleHeaders and get the raw audio sample data bytes from the Start and End times, and their Loop starts/ends.
But I don't get how to connect the Presets to their associated SampleHeader data.
That is, if I want to get the Sample data for, say, the preset named "Organ 2", I need some sort of index which points to the SampleHeader for that preset. (The Preset.Name and SampleHeader.SampleName strings don't necessarily match.)

Thanks,

New Post: MediaFoundationResampler

$
0
0
Hi everyone...

I got an issue with the MediaFoundationResampler. I try to resample a Wavestream to 32000 Hz. If I feed the resampler with very short samples (60 bytes) the resampler outputs just bytes containing zeros. If I change the format to 44100 Hz it works fine. Every samplerate below 32000 -> the same. Changing the bitdepth or the amount of channels does nothing.

The file is a IEEE float (32bit, 44100Hz, stereo) wav and I read it in by using a WaveFileReader.

Code:
var outFormat = new WaveFormat(32000, 16, 1);
int bps = (int)inStream.WaveFormat.AverageBytesPerSecond;
float diff = (int)outFormat.AverageBytesPerSecond;
diff /= bps;

using (var Resampler = new MediaFoundationResampler(inStream, outFormat))
{
          bytes = new byte[(int)(inStream.Length * diff)];
          Resampler.Read(bytes, 0, (int)bytes.Length);
 }
Any idea or known issue?

New Post: Missing WaveOut in UWP Projects

$
0
0
After some further research I've found that WaveOut is replaced by WasapiOutRT for Windows Store Apps. I have had to make quite a few code changes. However, I'm having problem making any sound. My code is as follows:
WasapiOutRT _wavePlayer;
BufferedWaveProvider _bufferProvider;

public Audio()
{
_wavePlayer = new WasapiOutRT(NAudio.CoreAudioApi.AudioClientShareMode.Shared, 100);

            _wavePlayer.Init(() =>
            {
                WaveFormat waveFormat = new WaveFormat(SAMPLE_RATE, 16, 2);
                _bufferProvider = new BufferedWaveProvider(waveFormat);
                _bufferProvider.DiscardOnBufferOverflow = true;
                return _bufferProvider;
            });
}

public bool TrySubmitBuffer(byte[] buffer, int buffer_size)
        {
            if (buffer_size >= SUBMIT_SIZE)
            {
                if (_wavePlayer.PlaybackState == PlaybackState.Stopped)
                {
                    _wavePlayer.Play();
                }
                else
                {
                    _bufferProvider.AddSamples(buffer, 0, buffer_size);
                }

                return true;
            }

            return false;
        }
Does this look right? Audio is called once to set up the class then TrySubmitBuffer is continually called by my AY sound chip emulator. I can see the data is passed into the BufferProvider instance but I can't see it being passed to the WasapiOutRT instance.

New Post: License and eccn (export control classification number)

New Post: Changing the incoming buffer size in WaveIn

$
0
0
Hi,

I'm using Naudio dll to read and process data. I want to know if it is possible to change the buffer size that each buffer is being read in. This is to see if processing times are more efficient if each buffer is a smaller.

CreateBuffers() in WaveIn seems to create the buffer size:
int bufferSize = BufferMilliseconds * WaveFormat.AverageBytesPerSecond / 1000;

I tried changing WaveFormat.AverageBytesPerSecond but it is read-only.

New Post: MPEG Audio Layer 2

$
0
0
I've noticed that I cannot decode files with NAudio that are MPEG Audio Layer 2 compressed. I understand that this is a codec issue, but I am having difficulties finding the right codec for it.

QDesign seemed to have developed a layer-2 ACM codec but they no longer exist. It is a bit of a bummer, since a regular Media Player on my Windows Machine has no problems playing back the file.
Does anyone have a suggestion or perhaps a hyperlink to a working (ACM) codec?
Another way might be to use DirectShow for decoding. If there is some info on how to use DShow together with NAudio, I'd be happy to know it.

Thanks in advance!

~Rob

New Post: MeteringSampleProvider and AsioOut

$
0
0
You can only change the UI on the UI thread. In WinForms this is done with Control.BeginInvoke, and in WPF you use the Dispatcher for this. It depends on the threading model for WaveOut whether audio processing happens on the UI thread, but with ASIO it's always a background thread

New Post: Midi playing with Timer

$
0
0
I'm afraid NAudio has no built-in sequencer, but you might want to have a look in the WPF demo's drum machine sample to see how I attempted to schedule drums to happen at the right time. It's probably not the perfect solution, but it does work reasonable well.

New Post: Midi playing with Timer

$
0
0
Thanks,

I've been looking over and studying your drum machine sample and borrowed parts of it to try to get it to play SoundFont samples.
At this point I have it where the midi notes properly trigger playing of samples (that is, at the right times), but the samples aren't getting looped properly :-(
This is to say, the samples stutter for the duration of each note. Obviously a problem with how Im looping them...

I'll try to post some code later...
I've been translating all NAudio code to VB for my own use, so when I post code, is VB ok, or should I translate to C#?

New Post: PianoRoll

$
0
0
I have customized Mark's Pianoroll2 so that you can display, edit and zoom notes based on MidiEvents.
I would like to post it, is this the proper place?![Image]

When implement it looks like this:
(https://i.imgsafe.org/3ca723d9d1.jpg)

Incidentally, I associate the PianoRoll not with a MidiEventCollection, as the original piano roll does, but rather with a single list of MIdiEvents (one track). This is because for most purposes you want to view your tracks separately (which is presumably the reason for having midi type 1 files).
(You wouldn't want all your track note data mixed together on one piano roll)
So, you create an instance of the piano roll for each track that you get when you open Naudio.Midi.MidiFile("")
Viewing all 5831 articles
Browse latest View live


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