Naudio:听不到声音

Posted

技术标签:

【中文标题】Naudio:听不到声音【英文标题】:Naudio: No audible sound 【发布时间】:2019-06-27 10:59:57 【问题描述】:

我已尝试按照此处的教程进行操作:https://markheath.net/post/fire-and-forget-audio-playback-with ,出于我的目的对其进行了一些修改,但我无法从扬声器中听到任何声音。

我也尝试直接使用教程的代码也没有成功。然而,我知道我使用的声音文件是有效的,因为我可以通过其他播放器读取它。

这是我修改后的代码:

public class AudioPlaybackEngine : IDisposable

    private readonly IWavePlayer            outputDevice;
    private readonly MixingSampleProvider   mixer;
    public readonly WaveFormat              Format;

    public AudioPlaybackEngine(int sampleRate = 44100, int channelCount = 2)
    
        WaveOutEvent    waveOutEvent = new WaveOutEvent();
        outputDevice = waveOutEvent;
        Format = WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channelCount);
        mixer = new MixingSampleProvider(Format);
        mixer.ReadFully = true;
            waveOutEvent.DeviceNumber = -1;
        Logger.writeLine("Selected sound device : " + waveOutEvent.DeviceNumber, "AudioPlaybackEngine");
        outputDevice.Init(mixer);
        outputDevice.Play();
    

    public float    MasterVolume
    
        get  return outputDevice.Volume; 
        set  outputDevice.Volume = value; 
    

    /// <summary> Only use this if you want to play a sound a single time (not cached) </summary>
    public void PlaySound(string fileName)
    
        var input = new AudioFileReader(fileName);
        AddMixerInput(new AutoDisposeFileReader(input));
    

    private ISampleProvider ConvertToRightChannelCount(ISampleProvider input)
    
        if (input.WaveFormat.Channels == mixer.WaveFormat.Channels)
        
            return input;
        
        if (input.WaveFormat.Channels == 1 && mixer.WaveFormat.Channels == 2)
        
            return new MonoToStereoSampleProvider(input);
        
        throw new NotImplementedException("Not yet implemented this channel count conversion");
    

    /// <summary> Play new sounds here using new SoundInstance(cachedSound) </summary>
    public void     PlaySoundInstance(ISampleProvider soundInstance)
    
        AddMixerInput(soundInstance);
    

    public void     StopSoundInstance(ISampleProvider soundInstance)
    
        mixer.RemoveMixerInput(soundInstance);
    

    private void    AddMixerInput(ISampleProvider input)
    
        mixer.AddMixerInput(ConvertToRightChannelCount(input));
    

    private void    RemoveMixerInput(ISampleProvider input)
    
        mixer.RemoveMixerInput(input);
    

    public void     Dispose()
    
        outputDevice.Dispose();
    

    public static readonly AudioPlaybackEngine Instance = new AudioPlaybackEngine(44100, 2);


public class CachedSound

    public float[]      AudioData  get; private set; 
    public WaveFormat   WaveFormat  get; private set; 

    public CachedSound(string audioFileName)
    
        AudioFileReader         afr = new AudioFileReader(audioFileName);
        WaveToSampleProvider    wts = new WaveToSampleProvider(new MediaFoundationResampler(new SampleToWaveProvider(afr), AudioPlaybackEngine.Instance.Format));
        int samplesRead;
        var wholeFile = new List<float>((int)(afr.Length / 4));
        var readBuffer= new float[wts.WaveFormat.SampleRate * wts.WaveFormat.Channels];
        while((samplesRead = wts.Read(readBuffer,0,readBuffer.Length)) > 0)
        
            wholeFile.AddRange(readBuffer.Take(samplesRead));
        
        WaveFormat = wts.WaveFormat;
        AudioData = wholeFile.ToArray();
    


/// <summary> Class using a cached buffer as data and providing access to volume </summary>
public class SoundInstance : ISampleProvider

    public readonly CachedSound     cachedSound;
    public long                     Position = 0;
    public float                    Volume = 1f;
    public bool                     LoopingEnabled = true;
    public bool                     StopASAP = false;

    public      SoundInstance(CachedSound cachedSound)
    
        this.cachedSound = cachedSound;
    

    public int  Read(float[] buffer, int offset, int count)
    
        int totalBytesRead = 0;

        while (totalBytesRead < count)
        
            if (StopASAP)
                return 0;
            // we have reached the end of the file
            if (cachedSound.AudioData.Length == Position)
            
                if (LoopingEnabled)
                    Position = 0; // reset position if looping enabled
                else
                    return totalBytesRead; // otherwise, stop reading.
            

            // copy data
            buffer[totalBytesRead + offset] = cachedSound.AudioData[Position] * Volume;

            ++Position;
            ++totalBytesRead;
        
        return totalBytesRead;
    

    public WaveFormat WaveFormat  get  return cachedSound.WaveFormat;  


// This class automatically disposes the file reader that it contains.
class AutoDisposeFileReader : ISampleProvider

    private readonly AudioFileReader reader;
    private bool isDisposed;
    public AutoDisposeFileReader(AudioFileReader reader)
    
        this.reader = reader;
        this.WaveFormat = reader.WaveFormat;
    

    public int Read(float[] buffer, int offset, int count)
    
        if (isDisposed)
            return 0;
        int read = reader.Read(buffer, offset, count);
        if (read == 0)
        
            reader.Dispose();
            isDisposed = true;
        
        return read;
    

    public WaveFormat WaveFormat  get; private set; 


public class SoundManager

    private Dictionary<string, CachedSound>     _soundsInMemory = new Dictionary<string, CachedSound>();
    private List<SoundInstance>                 _soundsInstances = new List<SoundInstance>();

    public                  SoundManager()
    

    

    public void             unloadSound(string soundName)
    
        if (_soundsInMemory.ContainsKey(soundName))
            _soundsInMemory.Remove(soundName);
    

    public void             loadSound(string soundName, string fileName)
    
        _soundsInMemory.Add(soundName, new CachedSound(fileName));
    

    public CachedSound      getLoadedSound(string soundName)
    
        if (_soundsInMemory.ContainsKey(soundName))
            return _soundsInMemory[soundName];
        return null;
    

    public SoundInstance    createSoundInstance(string soundName, float volume = 1f, bool enableLooping = true)
    
        SoundInstance       sound = new SoundInstance(getLoadedSound(soundName));
        sound.Volume = volume;
        sound.LoopingEnabled = enableLooping;
        //_soundsInstances.Add(sound);
        return sound;
    

这是我现在开始声音的方式:

            SoundManager    sm = new SoundManager();

            string          soundName = "test";
            sm.loadSound(soundName, "sounds/1.wav");

            SoundInstance   si = sm.createSoundInstance(soundName);
            AudioPlaybackEngine.Instance.PlaySoundInstance(si);

有趣的是,我可以看到绿色条在 Windows 的“音量混合器”中上下移动,但“设置”面板->“扬声器的音量”中没有显示任何内容(而其他播放器应用程序确实在此处显示了一些内容)最后一个面板)。

请帮忙?

【问题讨论】:

目前看来音量设置为 1f。您可以将其设置为更高的值,例如 50 或 100f 吗? 我尝试将其修改为 100f,但我的扬声器也没有任何输出,尽管事实上“音量混合器”似乎为我的应用程序显示了一个完全饱和的绿色条。 “设置面板”中仍然没有任何内容,并且没有声音。 【参考方案1】:

解决办法是去掉:

 ̶p̶u̶b̶l̶i̶c̶ ̶s̶t̶a̶t̶i̶c̶ ̶r̶e̶a̶d̶o̶n̶l̶y̶ ̶A̶u̶d̶i̶o̶P̶l̶a̶y̶b̶a̶c̶k̶E̶n̶g̶i̶n̶e̶ ̶I̶n̶s̶t̶a̶n̶c̶e̶ ̶=̶ ̶n̶e̶w̶ ̶A̶u̶d̶i̶o̶P̶l̶a̶y̶b̶a̶c̶k̶E̶n̶g̶i̶n̶e̶(̶4̶4̶1̶0̶0̶,̶ ̶2̶)̶;̶

并且在同一个线程中实例化它,而不是调用 PlaySound()。

【讨论】:

以上是关于Naudio:听不到声音的主要内容,如果未能解决你的问题,请参考以下文章

使用 NAudio 使用 asioout 录制时如何使声音更大?

C# NAudio 3D 声音

使用 NAudio 在特定频道上播放声音

使用 NAudio 改变左右声道的声音平衡

Naudio 声音正常化

naudio 从麦克风录制声音然后保存