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

时间:2016-11-24 19:20:49

标签: c# naudio

我需要读取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());
            }

1 个答案:

答案 0 :(得分:1)

您可以使用NAudio WaveFileReader来探索额外的块。这是&#34; smpl&#34;的一些代码。块:

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;
        }
    }
}