尝试将音频样本写入文件。我有16位整数列表
UInt16List _samples = new UInt16List(0);
当样本进入时,我将元素添加到此列表中。然后我可以像这样写入IOSink:
IOSink _ios = ...
List<int> _toWrite;
_toWrite.addAll(_samples);
_ios.add(_toWrite);
要么
_ios.add(_samples);
只是工作,没有类型的问题,尽管签名添加服用List<int>
而不是UInt16List
。
正如我读到的,在Dart中'int'类型是64位。两个写入都是相同的吗?他们是否在此文件中生成了16位整数?
一个Uint16List
是一个List<int>
。它是一个整数列表,它将写入截断为16位,并始终读出16位整数,但它是一个整数列表。
如果将这些整数复制到普通的可增长的List<int>
,它将包含相同的整数值。
因此,做ios.add(_sample)
会像ios.add(_toWrite)
一样,很可能也不会做你想要的。
IOSink
的add
方法需要一个字节列表。因此,它将采用整数列表并假设它们是字节。这意味着它只会使用每个整数的低8位,如果您尝试将其作为16位音频样本播放,则可能听起来很糟糕。
如果要存储所有16位,则需要弄清楚如何以两个字节存储每个16位值。简单的选择是假设平台字节顺序很好,并做ios.add(_samples.buffer.asUint8List(_samples.offsetInBytes, _samples.lengthInBytes))
。这将使16位数据的视图为两倍的字节,然后写入这些字节。
这些字节的字节序(首先是高字节或最后字节)取决于平台,因此如果您想要安全,可以先将字节转换为固定的字节顺序:
if (Endian.host == Endian.little) {
ios.add(
_samples.buffer.asUint8List(_samples.offsetInBytes, _samples.lengthInBytes);
} else {
var byteData = ByteData(_samples.length * 2);
for (int i = 0; i < _samples.length; i++) {
byteData.setUint16(i * 2, _samples[i], Endian.little);
}
var littleEndianData = byteData.buffer.asUint8List(0, _samples.length * 2);
ios.add(littleEndianData);
}