2017-01-20 2 views
0

Мне очень сложно выяснить, как получить несколько источников звука в один поток без значительных задержек. Я следовал за документацией NAudio, насколько это возможно, и написал следующее:Как смешивать несколько входов и сохранять синхронизацию?

public void Start() 
    { 
     _format = new WaveFormat(48000, 16, 2); 

     _mixingSampleProvider = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(48000, 2)); 

     _compressorStream = new SimpleCompressorStream(new MixingWaveStream(_mixingSampleProvider.ToWaveProvider())); 
     _compressorStream.Enabled = true; 

     foreach (var p in _activeRenderers) 
     { 
      p.Start(_compressorStream); 
     } 
    } 

    public void RegisterProvider(IAudioProvider provider) 
    { 
     var audioWaveProvider = new AudioWaveProvider(provider, _format); 
     _providers.Add(audioWaveProvider); 
     _mixingSampleProvider.AddMixerInput(audioWaveProvider.WaveProvider); 
    } 

MixingWaveStream является преобразование из IWaveProvider к WaveStream. p.Start() просто инициализирует WasapiOut в этот момент и вызывает Play(). Сейчас только один (я понимаю, что текущая настройка не будет работать с несколькими выходами). И мой AudioWaveProvider;

public AudioWaveProvider(IAudioProvider provider, WaveFormat format) 
    { 
     // Resample if necessary 
     if (provider.BitDepth != format.BitsPerSample || provider.Channels != format.Channels || provider.SampleRate != format.SampleRate) 
     { 
      _waveProviderToSendSamples = new BufferedWaveProvider(new WaveFormat(provider.SampleRate, provider.BitDepth, provider.Channels)); 
      WaveProvider = new MediaFoundationResampler(_waveProviderToSendSamples, format); 
     } 
     else 
     { 
      WaveProvider = new BufferedWaveProvider(format); 
      _waveProviderToSendSamples = (BufferedWaveProvider)WaveProvider; 
     } 

     AudioProvider = provider; 
     provider.ProvideSamples += Provider_ProvideSamples; 
    } 

    private void Provider_ProvideSamples(IAudioProvider provider, AudioSamples samples) 
    { 
     _waveProviderToSendSamples.AddSamples(samples.Samples, 0, (int)samples.Samples.Length); 
    } 

Мои аудио-провайдеры (в данном случае просто проигрываемые видео в формате libvlc) предоставляют образцы через событие.

Все работает однако со значительной задержкой (около 100 мс при просмотре видеокадров, которые я выводил). Я понимаю, что добавление микшера, BufferedWaveProvider и (потенциально) resampler добавит значительных накладных расходов, но я хотел бы знать, что лучше всего подходит для синхронизации видео и аудио.

Редактировать: Мой вход 44100 Гц, поэтому используется MediaFoundationResampler. После небольшого тестирования это причина большей части задержки, но у меня есть несколько входов с разными форматами.

Итак, как синхронизировать аудио и видео? Или как уменьшить время MediaFoundationResampler для повторной выборки? Какая здесь самая лучшая практика? Я мог бы использовать несколько выходов, но вместо этого было рекомендовано использовать микшер.

ответ

1

Да, MediaFoundationTransform имеет жестко запрограммированный размер считывания в одну секунду аудио, поскольку это позволяет легко определить размеры буферов источника и получателя. Я всегда хотел сделать это настраиваемым в будущем, экспериментируя с оптимальным размером, но поскольку я использовал его только в сценариях, где можно было читать вперед, я никогда не обходил его.

Если вы можете создать свою собственную сборку из NAudio, вы можете попробовать с меньшими размерами размера источника.