衰落声音输入/输出用n音讯 [英] Fading Sound In/Out using NAudio

查看:241
本文介绍了衰落声音输入/输出用n音讯的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个背景声音无限循环播放。我希望它淡出当用户按下一个按钮

I have a background sound playing in an endless loop. I want it to fade out when the user presses a button.

我试过如下:
-A DirectSoundOut与的WaveStream
启动 - ,一个定时器改变WaveChannel32的音量

I tried the following: -A DirectSoundOut is initiated with the WaveStream -A Timer changes the volume of the WaveChannel32.

问题:
- 改变音量的同时播放声音时产生的噪音: - (

The Problem: -Changing the volume while the sound is playing produces noises:-(.

有谁知道一个更好的解决方案?

Does anyone knows a better solution?

Thx提前。

推荐答案

要在淡入执行光滑或淡出,你需要在采样级别这样做。然后,通过逐渐增加或减少数量乘以每个样本。您正在使用WaveChannel32,让您的音频已经被转换为32位浮点。然后,我会创建另一个IWaveProvider实施者,这是负责做淡入和淡出。通常情况下,将通过样本不变,但在读取方法,如果你是在淡入或淡出,这将乘每个样品(或配对如果是立体声)。

To perform a smooth fade-in or fade-out, you need to do so at the sample level. You then multiply each sample by a gradually increasing or decreasing number. You are using WaveChannel32, so your audio has already been converted to 32 bit float. I would then create another IWaveProvider implementer that was responsible for doing the fade in and fade out. Normally it would pass through samples unchanged, but in the Read method, if you are in a fade in or fade out, it would multiply each sample (or pair if it is stereo).

在n音讯1.5 ISampleProvider界面设计,使这种类型的事情要容易得多,因为它可以让你已经处理样品32位浮动,而不是实施IWaveProvider这就需要你从一个byte []转换为浮动[]。下面是淡入和淡出我只是做了我会在下次n音讯,并希望很快在博客它SampleProvider。只需拨打 BeginFadeIn BeginFadeOut 用适当的衰落期。

The ISampleProvider interface in NAudio 1.5 was designed to make this type of thing much easier, as it allows you to deal samples already as 32 bit floats, rather than implementing IWaveProvider which requires you to convert from a byte[] to float[]. Here's a SampleProvider for fade-in and fade-out I just made which I will include in the next NAudio, and hopefully blog about it soon. Just call BeginFadeIn or BeginFadeOut with the appropriate fade duration.

public class FadeInOutSampleProvider : ISampleProvider
{
    enum FadeState
    {
        Silence,
        FadingIn,
        FullVolume,
        FadingOut,
    }

    private readonly object lockObject = new object();
    private readonly ISampleProvider source;
    private int fadeSamplePosition;
    private int fadeSampleCount;
    private FadeState fadeState;

    public FadeInOutSampleProvider(ISampleProvider source)
    {
        this.source = source;
        this.fadeState = FadeState.FullVolume;
    }

    public void BeginFadeIn(double fadeDurationInMilliseconds)
    {
        lock (lockObject)
        { 
            fadeSamplePosition = 0;
            fadeSampleCount = (int)((fadeDurationInMilliseconds * source.WaveFormat.SampleRate) / 1000);
            fadeState = FadeState.FadingIn;
        }
    }

    public void BeginFadeOut(double fadeDurationInMilliseconds)
    {
        lock (lockObject)
        {
            fadeSamplePosition = 0;
            fadeSampleCount = (int)((fadeDurationInMilliseconds * source.WaveFormat.SampleRate) / 1000);
            fadeState = FadeState.FadingOut;
        }
    }

    public int Read(float[] buffer, int offset, int count)
    {
        int sourceSamplesRead = source.Read(buffer, offset, count);
        lock (lockObject)
        {
            if (fadeState == FadeState.FadingIn)
            {
                FadeIn(buffer, offset, sourceSamplesRead);
            }
            else if (fadeState == FadeState.FadingOut)
            {
                FadeOut(buffer, offset, sourceSamplesRead);
            }
            else if (fadeState == FadeState.Silence)
            {
                ClearBuffer(buffer, offset, count);
            }
        }
        return sourceSamplesRead;
    }

    private static void ClearBuffer(float[] buffer, int offset, int count)
    {
        for (int n = 0; n < count; n++)
        {
            buffer[n + offset] = 0;
        }
    }

    private void FadeOut(float[] buffer, int offset, int sourceSamplesRead)
    {
        int sample = 0;
        while (sample < sourceSamplesRead)
        {
            float multiplier = 1.0f - (fadeSamplePosition / (float)fadeSampleCount);
            for (int ch = 0; ch < source.WaveFormat.Channels; ch++)
            {
                buffer[offset + sample++] *= multiplier;
            }
            fadeSamplePosition++;
            if (fadeSamplePosition > fadeSampleCount)
            {
                fadeState = FadeState.Silence;
                // clear out the end
                ClearBuffer(buffer, sample + offset, sourceSamplesRead - sample);
                break;
            }
        }
    }

    private void FadeIn(float[] buffer, int offset, int sourceSamplesRead)
    {
        int sample = 0;
        while (sample < sourceSamplesRead)
        {
            float multiplier = (fadeSamplePosition / (float)fadeSampleCount);
            for (int ch = 0; ch < source.WaveFormat.Channels; ch++)
            {
                buffer[offset + sample++] *= multiplier;
            }
            fadeSamplePosition++;
            if (fadeSamplePosition > fadeSampleCount)
            {
                fadeState = FadeState.FullVolume;
                // no need to multiply any more
                break;
            }
        }
    }

    public WaveFormat WaveFormat
    {
        get { return source.WaveFormat; }
    }
}

这篇关于衰落声音输入/输出用n音讯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆