我正在使用 ASIO 组件(在 Delphi 7 中),当它将左/右通道解交错到 2 个独立的 ASIO 缓冲区时,该组件仅支持 16 位和 32 位输出。一些 ASIO 驱动程序仅支持 24 位输出,因此我想为此位深度添加解交错功能,但所需的按位逻辑超出了我的范围。 以下是 DeInterleave32 和 DeInterleave16 函数。 有人可以帮忙创建一个 DeInterleave24 函数吗?
PBufferInfoArray 基本上是一个指针数组。
type
TBuffer32 = array[0..0] of LongWord;
PBuffer32 = ^TBuffer32;
TBuffer16 = array[0..0] of SmallInt;
PBuffer16 = ^TBuffer16;
procedure Deinterleave32(InputBuffer : PBuffer32; OutputBuffer : PBufferInfoArray; Samples, BufferIndex : LongWord);
var
i, j : LongWord;
Dest : array[0..1] of PBuffer32;
begin
for i := 0 to 1 do // always 2 channels
Dest[i] := OutputBuffer[i].buffers[BufferIndex];
i := 0;
while i < Samples do
begin
j := i shl 1;
Dest[0][i] := InputBuffer[j];
Dest[1][i] := InputBuffer[j+1];
Inc(i);
end;
end;
procedure Deinterleave16(InputBuffer : PBuffer16; OutputBuffer : PBufferInfoArray; Samples, BufferIndex : LongWord);
var
i, j : LongWord;
Dest : array[0..1] of PBuffer16;
begin
for i := 0 to 1 do // always 2 channels
Dest[i] := OutputBuffer[i].buffers[BufferIndex];
for i := 0 to Samples - 1 do
for j := 0 to 1 do
Dest[j][i] := InputBuffer[i*2 + j];
end;
如果您能提供帮助,我们将不胜感激。
我掌握的信息很少。缺少某些类型以及有关数据布局的任何信息。因此,我给自己一些自由。
我从头开始重写了两个旧程序,这次使用指针而不是数组索引。这提高了性能,因为每次指针变量访问都是 1 次内存读取,而每次数组变量访问都是 2 次(一次用于数组变量本身,一次用于索引变量)。新程序的速度是旧程序的两倍以上(时间嵌入在源代码片段中)。
24位缓冲区需要被写入,所以我也重写了你的两个旧缓冲区结构。为了一致性、更细粒度的子元素访问和性能原因。
新的 16 位和 32 位程序具有与旧程序相同的签名。也就是说,他们仍然期望旧的缓冲区类型。请注意,这不是问题,因为新类型与旧类型具有相同的内存占用量。出于显而易见的原因,新的 24 位过程确实使用了新的 24 位类型。
所有新类型和过程都带有下划线前缀 (
_
),以将它们与旧代码区分开来。
我无法访问
PBufferInfoArray
,所以我通过分析你的旧程序收集了它的结构。这就是我得出的结论,它必须看起来像这样:
type
PBufferInfoArray = ^TBufferInfoArray;
TBufferInfoArray = array [0..1] of record
buffers: array [0..0] of Pointer;
end;
这是所有新内容:
type
_PBuffer32 = ^_TBuffer32;
_TBuffer32 = packed record // SizeOf(_TBuffer32) = 4
case Integer of
0: (d: Cardinal);
1: (w0, w1: Word);
2: (b0, b1, b2, b3: Byte);
end;
_PBuffer24 = ^_TBuffer24;
_TBuffer24 = packed record // SizeOf(_TBuffer24) = 3
case Integer of
0: (w0: Word; w1: Byte); // !
1: (b0, b1, b2: Byte);
end;
_PBuffer16 = ^_TBuffer16;
_TBuffer16 = packed record // SizeOf(_TBuffer16) = 2
case Integer of
0: (w: Word);
1: (b0, b1: Byte);
end;
// ~105.16 ms (67108864 SAMPLES)
procedure _Deinterleave32(InputBuffer: PBuffer32; OutputBuffer: PBufferInfoArray; Samples, BufferIndex: LongWord);
var
psrc, esrc: _PBuffer32;
pdst0, pdst1: _PBuffer32;
begin
psrc := Pointer(InputBuffer);
esrc := psrc;
Inc(esrc, Samples);
pdst0 := OutputBuffer[0].buffers[BufferIndex];
pdst1 := OutputBuffer[1].buffers[BufferIndex];
while (NativeInt(psrc) < NativeInt(esrc)) do
begin
pdst0.d := psrc.d;
Inc(psrc);
pdst1.d := psrc.d;
Inc(psrc);
Inc(pdst0);
Inc(pdst1);
end;
end;
// ~124.44 ms (67108864 SAMPLES)
procedure _Deinterleave24(InputBuffer: _PBuffer24; OutputBuffer: PBufferInfoArray; Samples, BufferIndex: LongWord);
var
psrc, esrc: _PBuffer24;
pdst0, pdst1: _PBuffer32;
begin
psrc := Pointer(InputBuffer);
esrc := psrc;
Inc(esrc, Samples);
pdst0 := OutputBuffer[0].buffers[BufferIndex];
pdst1 := OutputBuffer[1].buffers[BufferIndex];
while (NativeInt(psrc) < NativeInt(esrc)) do
begin
pdst0.w0 := psrc.w0;
pdst0.w1 := psrc.w1;
Inc(psrc);
pdst1.w0 := psrc.w0;
pdst1.w1 := psrc.w1;
Inc(psrc);
Inc(pdst0);
Inc(pdst1);
end;
end;
// ~91.31 ms (67108864 SAMPLES)
procedure _Deinterleave16(InputBuffer: PBuffer16; OutputBuffer: PBufferInfoArray; Samples, BufferIndex: LongWord);
var
psrc, esrc: _PBuffer16;
pdst0, pdst1: _PBuffer32;
begin
psrc := Pointer(InputBuffer);
esrc := psrc;
Inc(esrc, Samples);
pdst0 := OutputBuffer[0].buffers[BufferIndex];
pdst1 := OutputBuffer[1].buffers[BufferIndex];
while (NativeInt(psrc) < NativeInt(esrc)) do
begin
pdst0.d := psrc.w;
Inc(psrc);
pdst1.d := psrc.w;
Inc(psrc);
Inc(pdst0);
Inc(pdst1);
end;
end;
以下是您未更改的旧程序(带有时间安排):
// ~232.12 ms (67108864 SAMPLES)
procedure Deinterleave32(InputBuffer : PBuffer32; OutputBuffer : PBufferInfoArray; Samples, BufferIndex : LongWord);
var
i, j : LongWord;
Dest : array[0..1] of PBuffer32;
begin
for i := 0 to 1 do // always 2 channels
Dest[i] := OutputBuffer[i].buffers[BufferIndex];
i := 0;
while i < Samples do
begin
j := i shl 1;
Dest[0][i] := InputBuffer[j];
Dest[1][i] := InputBuffer[j+1];
Inc(i);
end;
end;
// ~264.79 ms (67108864 SAMPLES)
procedure Deinterleave16(InputBuffer : PBuffer16; OutputBuffer : PBufferInfoArray; Samples, BufferIndex : LongWord);
var
i, j : LongWord;
Dest : array[0..1] of PBuffer16;
begin
for i := 0 to 1 do // always 2 channels
Dest[i] := OutputBuffer[i].buffers[BufferIndex];
for i := 0 to Samples - 1 do
for j := 0 to 1 do
Dest[j][i] := InputBuffer[i*2 + j];
end;
奖励:这是您的旧程序,但进行了一些清理:
// ~220.23 ms (67108864 SAMPLES)
procedure Deinterleave32_clean(InputBuffer: PBuffer32; OutputBuffer: PBufferInfoArray; Samples, BufferIndex: LongWord);
var
i : LongWord;
Dest: array[0..1] of PBuffer32;
begin
Dest[0] := OutputBuffer[0].buffers[BufferIndex];
Dest[1] := OutputBuffer[1].buffers[BufferIndex];
for i := 0 to (Samples - 1) do
begin
Dest[0][i] := InputBuffer[i*2];
Dest[1][i] := InputBuffer[i*2 + 1];
end;
end;
// ~143.78 ms (67108864 SAMPLES)
procedure Deinterleave16_clean(InputBuffer: PBuffer16; OutputBuffer: PBufferInfoArray; Samples, BufferIndex: LongWord);
var
i : LongWord;
Dest: array [0..1] of PBuffer16;
begin
Dest[0] := OutputBuffer[0].buffers[BufferIndex];
Dest[1] := OutputBuffer[1].buffers[BufferIndex];
for i := 0 to (Samples - 1) do
begin
Dest[0][i] := InputBuffer[i*2];
Dest[1][i] := InputBuffer[i*2 + 1];
end;
end;