简体   繁体   中英

How have a generic conversion from 32/24bit From Bytes To 16bit To bytes

Have been searching the solution for two days. I want to convert my wave 32 or 24 bits to a 16bit.

This my code after reading few stackoverflow topics):

byte[] data = Convert.FromBase64String("-- Wav String encoded --") (32 or 24 bits)
int  conv =  Convert.ToInt16(data);
byte[] intBytes = BitConverter.GetBytes(conv);
if (BitConverter.IsLittleEndian)
   Array.Reverse(intBytes);
 byte[] result = intBytes;

but when i writeAllbyte my result, nothing to hear...

Here is a method that cuts the least significant bits:

byte[] data = ...
var skipBytes = 0;
byte[] data16bit;
int samples;
if( /* data was 32 bit */ ) {
    skipBytes = 2;
    samples = data.Length / 4;
} else if( /* data was 24 bit */ ) {
    skipBytes = 1;
    samples = data.Length / 3;
}
data16bit = new byte[samples * 2];
int writeIndex = 0;
int readIndex = 0;
for(var i = 0; i < samples; ++i) {
    readIndex += skipBytes; //skip the least significant bytes
    //read the two most significant bytes
    data16bit[writeIndex++] = data[readIndex++];
    data16bit[writeIndex++] = data[readIndex++];
}

This assumes a little endian byte order (least significant byte is the first byte, usual for WAV RIFF). If you have big endian, you have to put the readIndex += ... after the two read lines.

You could implement your own conversion iterator for this task like so:

IEnumerable<byte> ConvertTo16Bit(byte[] data, int skipBytes)
{
    int bytesToRead = 0;
    int bytesToSkip = skipBytes;
    int readIndex = 0;
    while (readIndex < data.Length)
    {
        if (bytesToSkip > 0)
        {
            readIndex += bytesToSkip;
            bytesToSkip = 0;
            bytesToRead = 2;
            continue;
        }
        if (bytesToRead == 0)
        {
            bytesToSkip = skipBytes;
            continue;
        }
        yield return data[readIndex++];
        bytesToRead--;
    }
}

This way you don't have to create a new array if there is no need for it. And you could simply convert the data array to a new 16 bit array with the IEnumerable<T> extension methods:

var data16bit = ConvertTo16Bit(data, 1).ToArray();

Or if you don't need the array, you can iterate the data skipping the least significant bytes:

foreach (var b in ConvertTo16Bit(data, 1))
{
    Console.WriteLine(b);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM