使用场景:使用AudioRecord获取short格式的音频流数据,在经过处理后需要写入WAV文件中,但WAV文件使用的是二进制文件,因此需要将short转换为byte格式,而且是little-endian。
little-endian:中文被翻译为小端格式,意为将低序字节存储在起始地址(低位编址)即:
1.地址低位存储值的低位
2.地址高位存储值的高位
little-endian是最符合人的思维的字节序,是因为从人的第一观感来说低位值小,就应该放在内存地址小的地方,也即内存地址低位,反之,高位值就应该放在内存地址大的地方,也即内存地址高位(来源)。
网上对于short或者int转byte的说法各种各样,实在是混乱,记录一下目前我找到可以用的转换格式。
首先简单说一下原理,无论short、int,又或者是byte,都是以二进制的方式进行存储的,那么由此可知,short是2字节(1个字节8位)存储,byte是1字节存储,所以如果进行转换的话,byte的长度是short的两倍。
sample & 0xff
是掩码运算,相当于生成一个由sample的最低有效字节组成的值,其他的字节就被置为0。
sample >>8
是移位运算,相当于将该值移位至高字节。
/**/
注释部分是用于测试生成的字节是否正确,可以打印到后台方便查看。
private byte[] get16BitPcm(short[] data) {
byte[] resultData = new byte[2 * data.length];int iter = 0;String TAG = "get16BitPcm";for (short sample : data) {
resultData[iter++] = (byte)( sample & 0xff); //低位存储,0xff是掩码操作resultData[iter++] = (byte)((sample >>8) & 0xff); //高位存储/*测试生成的字节是否正确//ByteBuffer bb = ByteBuffer.allocate(2);//bb.order(ByteOrder.LITTLE_ENDIAN);//bb.put((byte)(sample & 0xff));//bb.put((byte)((sample >>8) & 0xff));//short shortVal = bb.getShort(0);//Log.d(TAG,"iter is:"+iter+"\tshortVal is: "+ shortVal);//Log.d(TAG,"==========================");*/}return resultData;}
参考资料:
byte转short:https://stackoverflow.com/questions/736815/2-bytes-to-short-java/38228146
https://blog.csdn.net/wuqingsen1/article/details/107235798
打印byte数组:https://stackoverflow.com/questions/6463580/how-to-print-the-data-in-byte-array-as-characters/6463665
short转byte:https://stackoverflow.com/questions/10549997/java-from-short-to-byte2-using-little-endian