Применение звуковых эффектов к токовому выходу с использованием библиотеки Bass. Net - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь применить эффекты эха, реверберации и темпа к аудиовыходу Windows плюс активному микрофону и воспроизвести его на аудиовыходе Windows, и все это в проекте *. 1012 * Core 3.1. Я попробовал обе библиотеки Bass. Net и ManagedBass, но безуспешно. Я пытался следовать этому руководству (https://mathewsachin.github.io/blog/2017/07/28/mixing-audio.html), но я не совсем понял весь процесс и, по-видимому, есть некоторые проблемы совместимости с ManagedBass и. net core 3.1.

Поэтому я попытался следовать той же идее и преобразовать код в исходную библиотеку Bass. Net следующим образом:

    private void btnPlay_onClick(object sender, RoutedEventArgs e)
    {
        // init BASS using the default output device
        Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);

        // Enable Loopback Recording.
        //Bass.Configure(Configuration.LoopbackRecording, true);

        mixer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT);

        Bass.BASS_RecordInit(recordDeviceIndex);
        Bass.BASS_RecordSetDevice(recordDeviceIndex);

        var info = Bass.BASS_RecordGetInfo();

        recording = Bass.BASS_RecordStart(info.freq, info.Channels, BASSFlag.BASS_MUSIC_FLOAT | BASSFlag.BASS_RECORD_PAUSE, null, IntPtr.Zero);

        BassMix.BASS_Mixer_StreamAddChannel(mixer, recording, BASSFlag.BASS_MIXER_DOWNMIX);

        playback = FindPlaybackDevice(recording);

        // Initialize the device to play silence on.
        Bass.BASS_Init(playback, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
        Bass.BASS_SetDevice(playback);

        // ManagedBass provides a default implementation of Stream Procedure producing silence.
        silence = Bass.BASS_StreamCreate(44100, 2, BASSFlag.BASS_MUSIC_FLOAT, SilenceProc, IntPtr.Zero);

        Bass.BASS_RecordInit(loopbackDeviceIndex);
        Bass.BASS_RecordSetDevice(loopbackDeviceIndex);

        var recordingInfo = Bass.BASS_RecordGetInfo();

        // Loopback recording requires that the Default frequency and number of channels be used.
        loopback = Bass.BASS_RecordStart(recordingInfo.freq, info.Channels, BASSFlag.BASS_MUSIC_FLOAT | BASSFlag.BASS_RECORD_PAUSE, null, IntPtr.Zero);

        // Add to mixer.
        BassMix.BASS_Mixer_StreamAddChannel(mixer, loopback, BASSFlag.BASS_MIXER_DOWNMIX);

        Bass.BASS_ChannelSetAttribute(mixer, BASSAttribute.BASS_ATTRIB_VOL, 0);

        Bass.BASS_ChannelSetDSP(mixer, Procedure, IntPtr.Zero, 2);

        // Start playing silence.
        Bass.BASS_ChannelPlay(silence, false);

        // Start Recording and Loopback.
        Bass.BASS_ChannelPlay(recordDeviceIndex, false);
        Bass.BASS_ChannelPlay(loopbackDeviceIndex, false);

        // Play the mixer.
        Bass.BASS_ChannelPlay(mixer, false);

    }

    private int SilenceProc(int handle, IntPtr buffer, int length, IntPtr user)
    {
        throw new NotImplementedException();
    }

    int FindPlaybackDevice(int LoopbackDevice)
    {
        var driver = Bass.BASS_GetDeviceInfo(LoopbackDevice).driver;

        var devicesInfo = Bass.BASS_GetDeviceInfos();

        // Enumerate Playback devices
        for (int i = 0; i <= devicesInfo.Length; ++i)
            // Compare drivers
            if (devicesInfo[i].driver == driver)
                return i;

        return 0;
    }

    byte[] _buffer;

    void Procedure(int Handle, int Channel, IntPtr Buffer, int Length, IntPtr User)
    {
        // Increase the buffer size if necessary.
        if (_buffer == null || _buffer.Length < Length)
            _buffer = new byte[Length];

        // Copy data into buffer.
        Marshal.Copy(Buffer, _buffer, 0, Length);

        // USE THE DATA. e.g. You can write it to a file.
    }


    private void btnStop_onClick(object sender, RoutedEventArgs e)
    {
        Bass.BASS_StreamFree(mixer);

        Bass.BASS_StreamFree(recording);
        Bass.BASS_StreamFree(loopback);

        Bass.BASS_StreamFree(silence);

        // Free the Playback device.
        Bass.BASS_SetDevice(playback);
        Bass.BASS_Free();

        // Free the Recording device.
        Bass.BASS_RecordSetDevice(recordDeviceIndex);
        Bass.BASS_RecordFree();

        // Free the Loopback device.
        Bass.BASS_RecordSetDevice(loopbackDeviceIndex);
        Bass.BASS_RecordFree();
    }

    private void Pause()
    {
        Bass.BASS_ChannelPause(mixer);

        Bass.BASS_ChannelPause(recording);
        Bass.BASS_ChannelPause(loopback);

        Bass.BASS_ChannelPause(silence);
    }

Как вы можете видеть, я не смог преобразовать весь код, как это сделал я. действительно не знал, как справиться с Bass.Configure и обработкой тишины. Так что любые примеры кода того, как можно заставить это работать, будут в значительной степени оценены!

...