从现有的ByteBuffer区域创建新的Dart ByteBuffer?

4
我正在Dart Web应用程序中加载包含压缩音频数据的二进制文件。当数据通过http请求加载时,它以ByteBuffer形式出现,我了解到这是Dart对JS ArrayBuffer的替代品。AudioContext.decodeAudioData()方法需要一个ByteBuffer,我在尝试弄清如何将已加载的ByteBuffer的相关部分传递给该方法。已加载的ByteBuffer包含与音频无关的其他数据。JS中的ArrayBuffers支持slice()方法,但在ByteBuffer类中缺少此功能,并且我无法找到任何方法可以在转换为允许范围选择的列表中返回到ByteBuffer。
我认为我可以创建一个混合解决方案来使用原生的JS,但如果可能的话,我想保持在Dart中。请提供建议!
2个回答

3
Dart的ByteBuffer没有slice方法。您可以使用Uint8List,因此不要使用buffer.slice(a, b),而是使用buffer.asUint8List().sublist(a, b).buffer。有关类型数据列表中的sublist方法返回由新缓冲区支持的相同类型的列表,并且buffer getter会返回任何类型数据列表的底层缓冲区。它不如直接在缓冲区上使用slice美观,但是如果不使用对齐问题(Int32List要求其起始偏移量为4字节对齐,因此对于任意切割,请始终使用8位清单),它可以完成工作。

谢谢!这是一种简洁的方法,选择一个1字节的列表类型也是一个好点子。 - Tyler Turner
在哪里可以找到“sublist”由一个新缓冲区支持的信息?我只能在文档中找到它返回“一个新列表”的描述。我在DartPad中尝试了一下,似乎可以工作,但我担心这可能只是一个实现细节。 - Thomas

0
我看不出在将ByteBuffer转换为任何允许范围选择的列表后返回到ByteBuffer的方法。
有几种解决方法,但是既然您不想修改原始缓冲区(我猜),那么您可以先复制一些字节。
// extract 2 ints (8 bytes) - no copying done yet
var rangeIterable = buffer.asInt32List().getRange(8, 10);

// create new typed list (copies the bytes from the iterable)
var newList = new Int32List.fromList(rangeIterable);
var newBuffer = newList.buffer;

print(buffer.lengthInBytes);
print(newBuffer.lengthInBytes);

1
非常感谢!我认为这里需要添加一个小细节,就是应该在rangeIterable上调用toList()才能与Int32List.fromList()一起使用。我甚至没有想到在创建新的Int32List时缓冲区属性会被填充。我已经习惯了它只是原始数据的引用,但当然它代表了复制的数据是有意义的。 - Tyler Turner
你真的需要添加.toList()吗?因为当我在本地尝试过它(没有强模式),它可以正常工作。 - Maximilian Riegler
1
我相信是这样的。如果没有它,当我尝试运行时会出现类型转换错误。"type 'SubListIterable<int>' is not a subtype of type 'List<int>' of 'elements'" 请注意,我是在从Intellij启动的Dartium中进行测试的,我认为这可能默认启用了Checked Mode - 这会导致这种情况吗? - Tyler Turner
非常有可能 - 我在控制台应用程序中尝试过 :) - Maximilian Riegler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接