7 |
|
{ |
8 |
|
#region Private data |
9 |
|
private bool convert_to_PCM; |
10 |
+ |
private bool do_pc_demo_test; |
11 |
|
|
12 |
|
private const int fcc_RIFF = 0x46464952; |
13 |
|
private const int fcc_WAVE = 0x45564157; |
86 |
|
}; |
87 |
|
#endregion |
88 |
|
|
89 |
< |
public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false) |
89 |
> |
public WavExporter(InstanceFileManager fileManager, string outputDirPath, bool convertToPCM = false, bool noDemo = false) |
90 |
|
: base(fileManager, outputDirPath) |
91 |
|
{ |
92 |
|
convert_to_PCM = convertToPCM; |
93 |
+ |
do_pc_demo_test = !noDemo; |
94 |
|
} |
95 |
|
|
96 |
|
private static void ClampToRange(ref int value, int lower, int upper) |
148 |
|
|
149 |
|
protected override void ExportInstance(InstanceDescriptor descriptor) |
150 |
|
{ |
151 |
< |
var sound = SoundData.Read(descriptor); |
151 |
> |
var sound = SoundData.Read(descriptor, do_pc_demo_test); |
152 |
|
|
153 |
|
using (var stream = File.Create(Path.Combine(OutputDirPath, descriptor.FullName + ".wav"))) |
154 |
|
using (var writer = new BinaryWriter(stream)) |
163 |
|
paddingBytes = blockSizeADPCM - leftoverBytes; |
164 |
|
var samplesPerBlock = 2 + (blockSizeADPCM - sound.ChannelCount * 7) * 8 / sound.ChannelCount / 4; |
165 |
|
|
166 |
< |
Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples; |
167 |
< |
|
166 |
> |
Int32 sampleCount = sampleCount = wholeBlocks * samplesPerBlock + leftoverSamples; |
167 |
> |
|
168 |
|
if (sound.IsIMA4) // IMA4 ADPCM format |
169 |
|
{ |
170 |
|
blockSizeADPCM = 34 * sound.ChannelCount; |
171 |
|
samplesPerBlock = 64; |
172 |
|
sampleCount = (sound.Data.Length / blockSizeADPCM) * samplesPerBlock; |
173 |
|
} |
172 |
– |
|
174 |
|
if (!convert_to_PCM) |
175 |
|
{ |
176 |
|
if (sound.IsIMA4) |
177 |
|
{ |
178 |
< |
throw new NotSupportedException("Transcoding from Mac/demo ADPCM to PC ADPCM not supported! Please use -extract:pcm"); |
178 |
> |
throw new NotSupportedException("Transcoding from IMA4 ADPCM (Mac) to MS ADPCM (PC) not supported! Please use -extract:pcm"); |
179 |
|
} |
180 |
|
var format = (byte[])formatTemplate_ADPCM.Clone(); |
181 |
|
var fact = (byte[])factTemplate.Clone(); // needed for ADPCM (to specify the actual sample count) |
271 |
|
if (predictorL > 32767) predictorL -= 65536; |
272 |
|
} |
273 |
|
stepIndexL = headerLoL & 0x7f; |
274 |
+ |
if (stepIndexL > 88) |
275 |
+ |
Console.WriteLine("Block {0} (L): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexL); |
276 |
+ |
ClampToRange(ref stepIndexL, 0, 88); |
277 |
+ |
|
278 |
|
for (int b = 0; b < 32; b++) |
279 |
|
{ |
280 |
|
Byte nibblesL = sound.Data[pos++]; |
295 |
|
if (predictorR > 32767) predictorR -= 65536; |
296 |
|
} |
297 |
|
stepIndexR = headerLoR & 0x7f; |
298 |
+ |
if (stepIndexR > 88) |
299 |
+ |
Console.WriteLine("Block {0} (R): Initial IMA4 step index is {1}, clamping to 88.", block, stepIndexR); |
300 |
+ |
ClampToRange(ref stepIndexR, 0, 88); |
301 |
|
|
302 |
|
for (int b = 0; b < 32; b++) |
303 |
|
{ |
367 |
|
samplesR[iSampleR++] = sample1R; |
368 |
|
} |
369 |
|
} |
370 |
< |
// read pair of nibbles |
371 |
< |
Byte nibbles = sound.Data[pos++]; |
372 |
< |
Byte nibbleHi = (Byte)(nibbles >> 4); |
373 |
< |
Byte nibbleLo = (Byte)(nibbles & 0xF); |
374 |
< |
samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi); |
375 |
< |
if (sound.ChannelCount == 2) |
376 |
< |
samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo); |
377 |
< |
else |
378 |
< |
samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo); |
370 |
> |
else // read pair of nibbles |
371 |
> |
{ |
372 |
> |
Byte nibbles = sound.Data[pos++]; |
373 |
> |
Byte nibbleHi = (Byte)(nibbles >> 4); |
374 |
> |
Byte nibbleLo = (Byte)(nibbles & 0xF); |
375 |
> |
samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleHi); |
376 |
> |
if (sound.ChannelCount == 2) |
377 |
> |
samplesR[iSampleR++] = NibbletoSampleMSADPCM(ref sample1R, ref sample2R, ref deltaR, pred_indexR, nibbleLo); |
378 |
> |
else |
379 |
> |
samplesL[iSampleL++] = NibbletoSampleMSADPCM(ref sample1L, ref sample2L, ref deltaL, pred_indexL, nibbleLo); |
380 |
> |
} |
381 |
|
} |
382 |
|
} |
383 |
|
writer.Write(fcc_data); |