【问题标题】:How to mix thousands of WAV files into a single file using NAudio's MixingSampleProvider?如何使用 NAudio 的 MixingSampleProvider 将数千个 WAV 文件混合成一个文件?
【发布时间】:2022-10-06 14:35:10
【问题描述】:

我正在寻找一种使用 NAudio 的 MixingSampleProvider 将数千个 WAV 文件混合到一个文件中的方法。我正在构建一个鼓采样器,我希望能够创建一整首歌曲(基于 MIDI 信息),然后可以将其导出到单个 WAV 文件中.

我遇到的问题是MixingSampleProvider 有一个1024 个来源的限制如果达到该限制,则抛出和异常说Too many mixer inputs。我确信这个限制是有原因的,我想知道如何实现我的目标。

我已经搜索了 NAudio 演示和 Mark Heath\'s blog,但我还没有找到我真正需要的东西。

我在想我可以将歌曲分割成更小的片段(在 1024 个采样器输入下)然后合并单独的部分。这是要走的路,还是有更好的路?感谢您的任何建议。

这是我的代码的一部分:

public class DrumSampler
{
    private readonly MixingSampleProvider _mixer;
    private readonly Dictionary<string, SampleSource> _cachedSamples = new();

    public DrumSampler()
    {
        var waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(44100, 2);
        _mixer = new MixingSampleProvider(waveFormat);

        LoadSamples();
    }

    private void LoadSamples()
    {
        LoadSample(\"kick\", @\"C:\\Samples\\kick.wav\");
        LoadSample(\"snare\", @\"C:\\Samples\\snare.wav\");
        LoadSample(\"crash\", @\"C:\\Samples\\crash.wav\");
    }

    private void LoadSample(string key, string filePath)
    {
        _cachedSamples.Add(key, SampleSource.CreateFromWaveFile(filePath, _mixer.WaveFormat));
    }

    public void ExportSong()
    {
        AddDrums();

        WaveFileWriter.CreateWaveFile16(\"song.wav\", _mixer);
    }

    private void AddDrums()
    {
        //simulate adding drum samples based on MIDI information 
        for (int i = 0; i < 1000; i++)
        {
            var sample = _cachedSamples[\"kick\"];
            var delayed = new DelayedSampleProvider(sample, TimeSpan.FromSeconds(123));
            _mixer.AddMixerInput(delayed);
        }
    }
}

SampleSource 的实现取自 NAudio 的 DrumMachineDemo

DelayedSampleProvider 的实现受到 NAudio 的 OffsetSampleProvider 的启发。

    标签: c# wav naudio mixing


    【解决方案1】:

    我已经能够通过将歌曲分成更小的 chungs(在 1024 个混音器输入下)来解决这个问题,每个块都有自己的 MixingSampleProvider,然后使用 ConcatenatingSampleProvider 连接所有的 chungs。

    它有效,但是,我想知道是否有更优雅的解决方案......

    这是我的代码:

    public class DrumSampler
    {
        private readonly WaveFormat _waveFormat;
        private readonly Dictionary<string, SampleSource> _cachedSamples = new();
    
        public DrumSampler()
        {
            _waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(44100, 2);
    
            LoadSamples();
        }
    
        private void LoadSamples()
        {
            LoadSample("kick", @"C:\Samples\kick.wav");
            LoadSample("snare", @"C:\Samples\snare.wav");
            LoadSample("crash", @"C:\Samples\crash.wav");
        }
    
        private void LoadSample(string key, string filePath)
        {
            _cachedSamples.Add(key, SampleSource.CreateFromWaveFile(filePath, _mixer.WaveFormat));
        }
    
        public void ExportSong()
        {
            var result = GenerateDrumAudio();
            WaveFileWriter.CreateWaveFile16("song.wav", result);
        }
    
        private ISampleProvider GenerateDrumAudio()
        {
            //simulate reading drum hits from MIDI
            var drumHits = Enumerable.Range(0, 10_000).ToList();
    
            //split drum hits into chunks of 1024 (max input limit of the mixing sample provider)
            var drumHitChunks = drumHits.Chunk(1024);
    
            //store all chunk mixers in a list
            var mixers = new List<MixingSampleProvider>();
    
            foreach (var drumHitChunk in drumHitChunks)
            {
                //for each chunk: create a mixer, add drum hits to it and add it to the mixers list
                var mixer = new MixingSampleProvider(_waveFormat);
    
                foreach (var drumHit in drumHitChunk)
                {
                    var sample = _cachedSamples["kick"];
                    var delayed = new DelayedSampleProvider(sample, TimeSpan.FromSeconds(123));
                    mixer.AddMixerInput(delayed);
                }
    
                mixers.Add(mixer);
            }
    
            //concatenate all chunk mixers into a single ISampleProvider
            var mixersConcatenated = new ConcatenatingSampleProvider(mixers);
    
            return mixersConcatenated;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      相关资源
      最近更新 更多