通过IOSink.Add编写UInt16List,结果如何?

问题描述 投票:0回答:1

尝试将音频样本写入文件。我有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位整数?

dart
1个回答
1
投票

一个Uint16List是一个List<int>。它是一个整数列表,它将写入截断为16位,并始终读出16位整数,但它是一个整数列表。

如果将这些整数复制到普通的可增长的List<int>,它将包含相同的整数值。

因此,做ios.add(_sample)会像ios.add(_toWrite)一样,很可能也不会做你想要的。

IOSinkadd方法需要一个字节列表。因此,它将采用整数列表并假设它们是字节。这意味着它只会使用每个整数的低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);
}
© www.soinside.com 2019 - 2024. All rights reserved.