【问题标题】:NAudio - Change pitch of buffered microphone audio and send to Virtual Audio CableNAudio - 更改缓冲麦克风音频的音高并发送到虚拟音频电缆
【发布时间】:2018-01-02 16:10:52
【问题描述】:

我决定尝试使用 NAudio 和虚拟音频线创建一个用于 Discord(或类似软件)的音板。我能够将麦克风中的音频“注入”到音频线,这样我就可以通过在 Discord 中选择虚拟音频线作为输入设备,将声音文件和麦克风音频播放到 Discord。

为了好玩,我想我会看看是否可以修改麦克风音频以使其“吱吱”或“深沉”。所以我开始研究修改音频的音高。我发现 NAudio 有一个 SmbPitchShiftingSampleProvider,然后发现 this question 有助于处理缓冲音频,但我不知道该怎么做。到目前为止,这是我所得到的:

    //Inject Mic Audio
    WaveIn injectMicIn = null;
    WaveOut injectMicOut = null;
    private BufferedWaveProvider bufferedWaveProvider; //Buffer for mic audio
    public int micDeviceID; //Device ID of selected microphone
    public int virtualAudioCableID; //Device ID of selected virtual audio cable
    ISampleProvider sampleP; //#### TO DO: Remove this if I don't use it.
    NAudio.Wave.SampleProviders.SmbPitchShiftingSampleProvider pitchProvider; //#### TO DO: Remove this if I don't use it

    private void InjectMicrophone()
    {
        //Mic Input
        if (injectMicIn == null)
        {
            injectMicIn = new WaveIn();
            injectMicIn.RecordingStopped += new EventHandler<StoppedEventArgs>(OnRecordingStopped);
            injectMicIn.DataAvailable += InjectMicOnDataAvailable;
            injectMicIn.WaveFormat = new WaveFormat(44100, 1);
        }

        injectMicIn.DeviceNumber = SharedVars.micInjectInputDeviceID; //Set the users selected input device

        //Mic Output
        if (injectMicOut == null)
        {
            injectMicOut = new WaveOut();
            injectMicOut.PlaybackStopped += new EventHandler<StoppedEventArgs>(OnPlaybackStopped);

        }

        bufferedWaveProvider = new BufferedWaveProvider(injectMicIn.WaveFormat); //Prepare the buffer for the microphone audio

        sampleP = bufferedWaveProvider.ToSampleProvider(); //#### TO DO: Remove this if I don't use it for pitch shifting

        injectMicOut.DeviceNumber = SharedVars.micInjectOutputDeviceID; //Set the users selected output device
        //injectMicOut.Init(bufferedWaveProvider);

        SharedVars.currentlyInjectingMic = true;
        injectMicIn.StartRecording(); //Record the mic and
        //injectMicOut.Play(); //out play it on the selected output device

    }

    bool init = false;
    private void InjectMicOnDataAvailable(object sender, WaveInEventArgs e)
    {
        bufferedWaveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded); //Add the mic audio to the buffer

        //#### TO DO: REMOVE THIS TEST CODE
        var bytesPerFrame = (injectMicIn.WaveFormat.BitsPerSample / 8) * injectMicIn.WaveFormat.Channels;
        var bufferedFrames = e.BytesRecorded / bytesPerFrame;

        var frames = new float[bufferedFrames];
        sampleP.Read(frames, 0, bufferedFrames);

        pitchProvider = new NAudio.Wave.SampleProviders.SmbPitchShiftingSampleProvider(sampleP);
        pitchProvider.PitchFactor = 2.0f;

        if (!init)
        {
            injectMicOut.Init(pitchProvider);
            init = true;
        }

        injectMicOut.Play();
        //#### TO DO: REMOVE THIS TEST CODE
    }

任何帮助将不胜感激。

编辑:最终代码

    //Inject Mic Audio
    WaveIn injectMicIn = null;
    WaveOut injectMicOut = null;
    private BufferedWaveProvider bufferedWaveProvider; //Buffer for mic audio
    public int micDeviceID; //Device ID of selected microphone
    public int virtualAudioCableID; //Device ID of selected virtual audio cable
    SmbPitchShiftingSampleProvider pitchProvider; //Used to adjust the pitch of the mic audio if required

    private void InjectMicrophone()
    {
        //Mic Input
        if (injectMicIn == null)
        {
            injectMicIn = new WaveIn();
            injectMicIn.RecordingStopped += new EventHandler<StoppedEventArgs>(OnRecordingStopped);
            injectMicIn.DataAvailable += InjectMicOnDataAvailable;
            injectMicIn.WaveFormat = new WaveFormat(44100, 1);
        }

        injectMicIn.DeviceNumber = SharedVars.micInjectInputDeviceID; //Set the users selected input device

        //Mic Output
        if (injectMicOut == null)
        {
            injectMicOut = new WaveOut();
            injectMicOut.PlaybackStopped += new EventHandler<StoppedEventArgs>(OnMicPlaybackStopped);    
        }

        injectMicOut.DeviceNumber = SharedVars.micInjectOutputDeviceID; //Set the users selected output device

        bufferedWaveProvider = new BufferedWaveProvider(injectMicIn.WaveFormat); //Prepare the buffer for the microphone audio

        pitchProvider = new SmbPitchShiftingSampleProvider(bufferedWaveProvider.ToSampleProvider()); //Create a pitch shifting sample provider to adjust the pitch of the mic audio if required
        pitchProvider.PitchFactor = 1.0f; //#### TO DO: Retrieve value from a UI control

        injectMicOut.Init(pitchProvider);

        SharedVars.currentlyInjectingMic = true;
        injectMicIn.StartRecording(); //Record the mic and
        injectMicOut.Play(); //out play it on the selected output device

    }

    private void InjectMicOnDataAvailable(object sender, WaveInEventArgs e)
    {
        bufferedWaveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded); //Add the mic audio to the buffer
    }

【问题讨论】:

    标签: c# audio audio-recording naudio


    【解决方案1】:

    你已经很接近了

    在录音设备上,直接将录制好的音频放入BufferedWaveProvider即可。

    在播放设备上,传入一个从BufferedWaveProvider 读取的SmbPitchShiftingProvider(使用ToSampleProvider 将其转换为ISampleProvider

    【讨论】:

    • 再次非常感谢您。还有什么我可以玩的东西来进一步调整声音的声音,这是相对简单的实现还是唯一的音调?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 2020-09-11
    • 2017-10-26
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    相关资源
    最近更新 更多