如何使用 C# 读取 WAV 文件的 SMPL 块?

How do I read the SMPL chunk of a WAV file with C#?

我需要读取 SMPL 块中的 dwStartdwEnd 属性,因为这些点应该指定示例中循环的起点和终点。 我正在将我的 Directwave 库转换为 Bitwig 的 .multisample 格式,这样我的应用程序就不需要播放 WAV 文件了。它只需要读取循环点,以便可以将其添加到如下所示的 XML 中:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multisample name="Test Bell">
    <generator>Bitwig Studio</generator>
    <category>Bell</category>
    <creator>John</creator>
    <description>Misc</description>
    <layer name="Default">
        <sample file="Bell_004 - C3.wav" gain="0.00" sample-start="0.000" sample-stop="88048.000">
            <key track="true" tune="0.00">
                <velocity />
                <loop mode="sustain" start="58709.000" stop="88048.000" />
            </key>
        </sample>
    </layer>
</multisample>

更新: Mark Heath 的代码用于在 Kontakt WAV 中找到 smpl 块和循环点,但它没有在创建的 WAV 文件中找到 smpl 块以DirectWave为例这个文件: http://stash.reaper.fm/28963/Flute_006_C3.wav

我使用了下面的代码,它只找到了一个 inst 块。如果没有 smpl 块,如何找到开始和结束循环点?

    var smp = reader.ExtraChunks.Where(ec => ec.IdentifierAsString != null); 
            foreach (var x in smp)
            {
                MessageBox.Show(x.IdentifierAsString.ToString());
            }

您可以使用 NAudio WaveFileReader 探索额外的区块。这是 "smpl" 块的一些代码:

var wavFilePath = @"E:\Recording\sfz\Equinox Steinway D\SteinwayDmA#0.wav";
using (var reader = new WaveFileReader(wavFilePath))
{
    var smp = reader.ExtraChunks.FirstOrDefault(ec => ec.IdentifierAsString == "smpl");
    if (smp != null)
    {
        var chunkData = reader.GetChunkData(smp);
        // https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl
        var midiNote = BitConverter.ToInt32(chunkData,12);
        var numberOfSamples = BitConverter.ToInt32(chunkData,28);
        Console.WriteLine($"MIDI {midiNote}, {numberOfSamples} samples");
        int offset = 36;
        for (int n = 0; n < numberOfSamples; n++)
        {
            var cuePointId = BitConverter.ToInt32(chunkData,offset);
            var type = BitConverter.ToInt32(chunkData, offset + 4); // 0 = loop forward, 1 = alternating loop, 2 = reverse

            var start = BitConverter.ToInt32(chunkData, offset + 8);
            var end = BitConverter.ToInt32(chunkData, offset + 12);
            var fraction = BitConverter.ToInt32(chunkData, offset + 16);
            var playCount = BitConverter.ToInt32(chunkData, offset + 20);
            Console.WriteLine($"Sample {cuePointId} Start {start} End {end}");
            offset+= 24;
        }
    }
}