如何使用 C# 读取 WAV 文件的 SMPL 块?
How do I read the SMPL chunk of a WAV file with C#?
我需要读取 SMPL 块中的 dwStart
和 dwEnd
属性,因为这些点应该指定示例中循环的起点和终点。
我正在将我的 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;
}
}
}
我需要读取 SMPL 块中的 dwStart
和 dwEnd
属性,因为这些点应该指定示例中循环的起点和终点。
我正在将我的 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;
}
}
}