source: OniSplit/Sound/WavFile.cs@ 1155

Last change on this file since 1155 was 1154, checked in by geyser, 4 years ago

Implemented import/export of "fact" chunk for .wav files. Added a -demo tag for storing sounds in the PC demo format (if compatible).

File size: 3.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4//using System.Runtime.Remoting.Metadata.W3cXsd2001;
5
6namespace Oni.Sound
7{
8 internal class WavFile
9 {
10 #region Private data
11 private const int fcc_RIFF = 0x46464952;
12 private const int fcc_WAVE = 0x45564157;
13 private const int fcc_fmt = 0x20746d66;
14 private const int fcc_fact = 0x74636166;
15 private const int fcc_data = 0x61746164;
16
17 private WavFormat format;
18 private int channelCount;
19 private int sampleRate;
20 private int averageBytesPerSecond;
21 private int blockAlign;
22 private int bitsPerSample;
23 private int sampleCount;
24 private byte[] extraData;
25 private byte[] soundData;
26 #endregion
27
28 public static WavFile FromFile(string filePath)
29 {
30 using (var reader = new BinaryReader(filePath))
31 {
32 if (reader.ReadInt32() != fcc_RIFF)
33 throw new InvalidDataException("Not a WAV file");
34
35 int size = reader.ReadInt32();
36
37 if (reader.ReadInt32() != fcc_WAVE)
38 throw new InvalidDataException("Not a WAV file");
39
40 var header = new WavFile()
41 {
42 sampleCount = 0
43 };
44
45 for (int chunkType, chunkSize, chunkStart; reader.Position < size; reader.Position = chunkStart + chunkSize)
46 {
47 chunkType = reader.ReadInt32();
48 chunkSize = reader.ReadInt32();
49 chunkStart = reader.Position;
50
51 if (chunkType == fcc_fmt)
52 header.ReadFormatChunk(reader, chunkSize);
53 if (chunkType == fcc_fact)
54 header.ReadFactChunk(reader, chunkSize);
55 if (chunkType == fcc_data)
56 header.ReadDataChunk(reader, chunkSize);
57 }
58
59 header.ValidateSampleCount();
60 return header;
61 }
62 }
63
64 private void ReadFormatChunk(BinaryReader reader, int chunkSize)
65 {
66 format = (WavFormat)reader.ReadInt16();
67 channelCount = reader.ReadInt16();
68 sampleRate = reader.ReadInt32();
69 averageBytesPerSecond = reader.ReadInt32();
70 blockAlign = reader.ReadInt16();
71 bitsPerSample = reader.ReadInt16();
72
73 if (chunkSize > 16)
74 extraData = reader.ReadBytes(reader.ReadInt16());
75 else
76 extraData = new byte[0];
77 }
78
79 private void ReadFactChunk(BinaryReader reader, int chunkSize)
80 {
81 sampleCount = reader.ReadInt32();
82 }
83
84 private void ReadDataChunk(BinaryReader reader, int chunkSize)
85 {
86 soundData = reader.ReadBytes(chunkSize);
87 }
88 private void ValidateSampleCount() // TODO: ACTUAL VALIDATION/CORRECTION
89 {
90 int sampleCountFromData = 0;
91 int wholeBlocks = soundData.Length / blockAlign;
92 if(sampleCount == 0) // not explicitly set (no fact chunk present)
93 {
94 Console.WriteLine("The imported WAV file has no FACT chunk.");
95 }
96 else // TODO: calculate sampleCountFromData, compare with sampleCount
97 {
98
99 }
100 }
101
102 public WavFormat Format => format;
103 public int ChannelCount => channelCount;
104 public int SampleRate => sampleRate;
105 public int AverageBytesPerSecond => averageBytesPerSecond;
106 public int BlockAlign => blockAlign;
107 public int BitsPerSample => bitsPerSample;
108 public byte[] ExtraData => extraData;
109 public byte[] SoundData => soundData;
110 }
111}
Note: See TracBrowser for help on using the repository browser.