Reading (and saving) 24-bit samples is very simple. Now, as you rightly said, the 3-byte integral type does not exist within the framework, which means that you are left with two options; either create your own type, or you can put your 24-bit samples by inserting an empty byte ( 0 ) at the beginning of your array of sample bytes, resulting in 32-bit samples (so you can use int to store / manipulate them ) A.
I will explain and demonstrate how to do this later (which is also, in my opinion, a simpler approach).
First we need to see how the 24-bit sample will be stored in int ,
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ MSB ~ ~ 2 nd MSB ~ ~ 2 nd LSB ~ ~ LSB ~ ~
24-bit sample: 11001101 01101001 01011100 00000000
32-bit sample: 11001101 01101001 01011100 00101001
MSB = Most significant byte, LSB = Lest Signal Byte.
As you can see, the LSB of the 24-bit pattern is 0 , so all you need to do is declare a byte[] with 4 elements and then read 3 bytes of the pattern into an array (starting at element 1 ) so that your array looks lower (actually a bit moves 8 places to the left),
myArray [0]: 00000000
myArray [1]: 01011100
myArray [2]: 01101001
myArray [3]: 11001101
When you have a full array of bytes, you can pass it to BitConverter.ToInt32(myArray, 0); then you will need to shift the pattern 8 places to the right to get the pattern in its correct 24-bit gateway representation (from -8388608 to 8388608 ); then divide by 8388608 to have it as a floating point value.
So, putting everything together, you should get something like this,
Notice, I wrote the following code with the intention of being βeasy to useβ, so this is not the most efficient method, for a quicker solution, see the code below this.
private List<float> Read24BitSamples(FileStream stream, int startIndex, int endIndex) { var samples = new List<float>(); var bytes = ReadChannelBytes(stream, Channels.Left, startIndex, endIndex); var temp = new List<byte>(); var paddedBytes = new byte[bytes.Length / 3 * 4];
For a faster implementation of 1, you can do the following:
private List<float> Read24BitSamples(FileStream stream, int startIndex, int endIndex) { var bytes = ReadChannelBytes(stream, Channels.Left, startIndex, endIndex); var samples = new float[bytes.Length / 3]; for (var i = 0; i < bytes.Length; i += 3) { samples[i / 3] = (bytes[i] << 8 | bytes[i + 1] << 16 | bytes[i + 2] << 24) / 2147483648f; } return samples.ToList(); }
1 After comparing the above code with the previous method, this solution is approximately 450-550% faster.