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

New Post: Try this Reverb ISampleProvider

$
0
0
Ok, I reposted the ReverbSampleProvider class to the download link above.

Notes:
  • I think I solved the overdrive issue noted by Freefall. It does result in volume somewhat lower than the original signal, but you can use the Gain property to increase it.
  • New mixing algo may have softened the "effect too hard" issue noted by Freefall. You can play with the mixing in the Process method if you want a different reverb quality.
  • This is not a textbook implementation of reverb sound reflection so purists may scoff, but I kinda like the sound. Your results may vary. ;-)
  • The DirectSignalLevel property was removed for this revision.
  • Usage notes were added to the comments at the top of the ReverbSampleProvider class code.

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: how do you know what the correct value should be? Maybe directsound thinks there are 8 devices? What happens if you do DirectSoundOut.Devices.ToList().Count

New Post: How to improve FFT results accuracy ?

$
0
0
I'm trying to make an application to show pitch of microphone input in a pitch contour in real-time using NAudio. To check the FFT results I inputted an A4 note on a clarinet which has the known f0 of 440Hz. But I got 430.6641Hz and got 904.3945Hz once in a blue moon.

Button_Click Event
            var inputStream = new AudioFileReader("a4.wav");
            fileStream = inputStream;
            var aggregator = new SampleAggregator(inputStream);
            aggregator.NotificationCount = inputStream.WaveFormat.SampleRate / 100;
            aggregator.PerformFFT = true;
            aggregator.FftCalculated+=OnFftCalculated;
            playback = new WaveOut();
            playback.Init(aggregator);

            int read = 0;
            float[] buffer = new float[1024];

            do
            {
                read = aggregator.Read(buffer, 0, buffer.Length);
            } while (read > 0);

            playback.Play();
OnFFTCalculated Event
            float[] magnitudes = new float[e.Result.Length / 2];

            for (int i = 0; i < e.Result.Length / 2; i++)
                magnitudes[i] = ((float)Math.Sqrt((e.Result[i].X * e.Result[i].X) + (e.Result[i].Y * e.Result[i].Y)));


            float max_mag = float.MinValue;
            float max_index = -1;
            for (int i = 0; i < e.Result.Length / 2; i++)
                if (magnitudes[i] > max_mag)
                {
                    max_mag = magnitudes[i];
                    max_index = i;
                }

            var frequency = max_index * samplingFrequency / 1024; // CurrentSamplerate gets set dynamically incase some tracks have a different samplerate.
            Dispatcher.Invoke(new Action(() =>
            {
                Debug.WriteLine(frequency.ToString() + "Hz");
            }));
NAudio's Sample Aggregator Class
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; }
    }
}
What can be the issue? How can I improve the accuracy of the results?

New Post: Plays in speakers, but not in headphones

$
0
0
Hi,

is there yet a solution for switching the "default audio device" in Windows?
I'm now having the same problem.

Once I have created a naudio WaveOut object and the users switches the windows audio device, the sound still is played on the old device.

Regards
Der_Knob

New Post: Try this Reverb ISampleProvider

$
0
0
Sorry for my late reply, I´m currently in the process of moving to a new city. I´ll test your Reverb revision.

I also optimized above SMBPitchShiftingSampleProvider, see Edit 3.

If there is an interest in it, I´ll post the speed provider based on the smb shifter (after optimizing).

New Post: Try this Reverb ISampleProvider

$
0
0
Hi Freefall,
I confess I haven't had time to setup and test your PitchShifter.

For these two lines, where is the SMBPitchShifter class?
Private ShifterLeft As New SMBPitchShifter()
Private ShifterRight As New SMBPitchShifter()

New Post: Try this Reverb ISampleProvider

$
0
0
See post # 2, it can be found at the C# port of SMB´s shifter:

https://sites.google.com/site/mikescoderama/pitch-shifting

The class is too big to post here (restricted to post max. 10.000 characters), that´s why I didn´t do so.

As written in post # 2 you need to do with the c# port:
  • Change "PitchShifter" class name -> "SMBPitchShifter" class name
  • Remove all static attributes
Then it should work - feedback is appreciated.

New Post: Try this Reverb ISampleProvider

$
0
0
Ok, thanks. I got the SMBPitchShifter class to compile. So now I guess I have to make two separate class libraries because one class is in C# and one is in Basic. Is that how you got this to build? Not a VBasic programmer so this is getting 'interesting'. But that's my skills limit problem so I'll figure it out. :-)

Good luck moving. That is such a blast.

New Post: Try this Reverb ISampleProvider

$
0
0
You can convert my vbasic code to c# using a code converter like this.

Yeah, moving means very much work. I´ll see how much time i can invest in audio programming, today was my first free day this week.

New Post: How to improve FFT results accuracy ?

$
0
0
Only idea I got in mind on first view: You could use double instead of float to improve precision.

New Post: Try this Reverb ISampleProvider

$
0
0
Here is a quick C# conversion of my shifter class:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using NAudio.Wave;

public class SMBPitchShiftingSampleProvider : ISampleProvider
{

    private ISampleProvider SourceStream = null;
    private WaveFormat WFormat = null;
    private float Pitch = 1f;
    private int _FFTSize = null;
    private long _osamp = null;
    private SMBPitchShifter ShifterLeft = new SMBPitchShifter();
    private SMBPitchShifter ShifterRight = new SMBPitchShifter();
    private float volscale = 1f; //Recommended to scale volume down, as SMB seems to clip with pitching

    private object PitchLock = new object();
    public SMBPitchShiftingSampleProvider(ISampleProvider SourceProvider, int FFTSize, long osamp, float InitialPitch = 1f)
    {
        SourceStream = SourceProvider;
        WFormat = SourceProvider.WaveFormat;
        _FFTSize = FFTSize;
        _osamp = osamp;
        PitchFactor = InitialPitch;
    }

    public int Read(float[] buffer, int offset, int count)
    {
        lock (PitchLock) {
            int SampRead = SourceStream.Read(buffer, offset, count);
            if (Pitch == 1f)    
                //Nothing to do.
                return SampRead;
            if (WFormat.Channels == 1) {
                float[] Mono = new float[SampRead];
                int index = 0;
                for (int sample = offset; sample <= SampRead - 1; sample++) {
                    Mono[index] = buffer[sample];
                    index += 1;
                }
                ShifterLeft.PitchShift(Pitch, SampRead, _FFTSize, _osamp, WFormat.SampleRate, Mono);
                index = 0;
                for (int sample = offset; sample <= SampRead - 1; sample++) {
                    buffer[sample] = Mono[index] * volscale * 0.707f;
                    index += 1;
                }
                return SampRead;
            } else if (WFormat.Channels == 2) {
                float[] Left = new float[(SampRead >> 1)];
                float[] Right = new float[(SampRead >> 1)];
                int index = 0;
                for (int sample = offset; sample <= SampRead - 1; sample += 2) {
                    Left(index) = buffer[sample];
                    Right(index) = buffer[sample + 1];
                    index += 1;
                }
                ShifterLeft.PitchShift(Pitch, SampRead >> 1, _FFTSize, _osamp, WFormat.SampleRate, Left);
                ShifterRight.PitchShift(Pitch, SampRead >> 1, _FFTSize, _osamp, WFormat.SampleRate, Right);
                index = 0;
                for (int sample = offset; sample <= SampRead - 1; sample += 2) {
                    buffer[sample] = Left(index) * volscale * 0.707f;
                    buffer[sample + 1] = Right(index) * volscale * 0.707f;
                    index += 1;
                }
                return SampRead;
            } else {
                throw new Exception("Shifting of more than 2 channels is currently not supported.");
            }
        }
    }

    public NAudio.Wave.WaveFormat WaveFormat {
        get { return WFormat; }
    }

    public float PitchFactor {
        get { return Pitch; }
        set {
            lock (PitchLock) {
                Pitch = value;
                ScaleVolume();
            }
        }
    }

    private void ScaleVolume()
    {
        if (Pitch > 1f) {
            volscale = 1f / Pitch;
        } else {
            volscale = Pitch;
        }
    }
}
Happy testing!

New Post: Try this Reverb ISampleProvider

$
0
0
Hey Freefall, I got the PitchShifter working. Thanks for all your help.

Test results:
1) It's pretty cool sounding effect. I played a music file with PitchFactor = 1.9 and the singers voice sounds like Alvin the chipmunk. So it's working. :-)
2) Pitch definitely shifts when I change the PitchFactor in increments of 0.1. It can make a guitar sound like a chello.
3) What is the valid value range for PitchFactor?
4) I hear a regular click sound (like a static click). Probably as often as each Read method call. No idea what causes it.

The calculated value for L/R channels stays within the range of +1 to -1. So I assume the clicking is not from overdriven values.
Novice question: As a general rule, is it true that the output values should stay within this range (+1...-1) to avoid overdrive?


And thanks for that VBasic code converter. It works pretty good. I bookmarked the link for future use. It has a problem with converting array index parens "(" and ")" to C# syntax "[" and "]". Easy enough to fix with a text editor after converting. I only mention that in case anyone grabs your converted code above, "Left(index)" and "Right(index)" should have the square brackets syntax.

It's clear this PitchShifter deserved it's own discussion thread.
PS. And don't feel rushed to reply. I know you are throttled with the move.

New Post: Try this Reverb ISampleProvider

$
0
0
Thanks for testing. Concerning your questions:

3) Valid range is from between 0.5f (one octave down) and 2f (one octave up) - see the comments on the SMB port.
4) That click sound may be caused from overlapping windows. Try to increase the oversampling factor (=osamp) to 16 or 32. But note, that this will increase CPU usage heavily.

Yes, generally sound samples should stay in the -1 ... +1 range. All above or beyound this would be clipped and would result in crackling sound.

Perhaps Mark can include this Class for the next NAudio release, I´ve seen many people struggling searching for that.

New Post: Try this Reverb ISampleProvider

$
0
0
Freefall, Thanks for those answers.

I tried it with Osamp = 16L and = 32L
The sound was strange at those values. Sounded like original samples went missing. It got worse with 32L value. The click noise was still there. The source is a 16bit stereo MP3 @44100

I recorded CPU usage with the various Osamp values, My laptop CPU is Intel i5 @ 2.53Ghz

Osamp =8L
CPU 30% avg, spikes to 50%

Osamp =16L
strange sound, like some of original sound is missing
CPU 40% avg spikes to 50%

Osamp = 32L
worse sound, more missing sound
CPU usage about the same as 16L

New Post: Try this Reverb ISampleProvider

$
0
0
I think the missing sound comes from the high CPU usage, when the playback thread got too few resources.

You could try a FFT Size of 1024 or 2048 (higher size means higher precision although).

New Post: Try this Reverb ISampleProvider

$
0
0
Tried it with both FFT Size of 1024 or 2048.
I still hear a static click with both of these values, but it is a little less noticeable (lower volume click).

Do you hear any static when you play it on your machine? My laptop audio card is Realtek HD audio.

New Post: Try this Reverb ISampleProvider

$
0
0
No, I can´t find any clicking sounds after pitching. Perhaps your hardware is broken or your input file.

As I said before, the clicking could also be a windowing issue of the algorithm.

New Post: Try this Reverb ISampleProvider

$
0
0
I don't think it is 'broken' hardware, because my other ISampleProviders are not causing this click.
And the input file plays fine with my other ISampleProviders or with no ISampleProvider just playing a standard Naudio waveOut device.

Most of the Pitch Shifting is done by the CPU. So with it running at 30% CPU, maybe it isn't finished processing the previous Read event when the next Read event pops. This definitely a mid-range power laptop -- not a high performance machine.

Not sure what "windowing issue of the algorithm" means.

New Post: Try this Reverb ISampleProvider

$
0
0
Ok, then I´m almost sure the high CPU usage causes this problem. On my 4 core machine its also clicking (rather stuttering) when CPU usage is >25%.

With windowing issue I mean, that in the process of overlapping sample packets maybe aliasing effects could happen. Not sure about this, I´m not the algorithm designer. But this is probably not the reason, rather the CPU.

I´d try in your situation to decrease CPU usage to a safe performance zone, e.g. about 10% CPU. I´ve optimized the SampleProvider as much as I could and the algorithm itself won´t be much optimizeable; hence I recommend to find the best compromise between FFT Size and osamp value. In my case, it was 4096 for FFT Size and 8 for osamp. That provided a nice sound with ~ 10% CPU usage.

New Post: Try this Reverb ISampleProvider

$
0
0
Ok, thanks Freefall. Yeah, I've tried various combinations of values. I don't think my machine has the power for this one. The effect takes a lot of computations, no way to get around that. But it's still a really cool effect and the click is not all that noticeable. People with a fast machine will love it.
Viewing all 5831 articles
Browse latest View live


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