Thanks Ian got the little-endian conversions working now.
Here is my implementation of the float to 24 bit conversion (little-endian):
procedure DSP24bitLE(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
type
T24BitSample = record
a0 : Byte;
a1 : Byte;
a2 : ShortInt;
end;
var
src : array of Single;
dst : array of T24BitSample;
i : Integer;
SaveValue : Integer;
NumSamples : integer;
begin
SetLength(src, length);
SetLength(dst, length * 24 div 32); // Size * 24 bit (output bitrate) div 32 bit (input bitrate)
move(buffer^, src[0], length);
NumSamples := Length div (32 div 8); // 32 bit float div 8
for I := 0 to NumSamples - 1 do
begin
// convert to integer
SaveValue := Trunc(src[I]*8388608);
// clip it
if (SaveValue > 8388607) then
SaveValue := 8388607
else
if (SaveValue < -8388608) then
SaveValue := -8388608;
// store it (little-endian)
dst[I].a0 := SaveValue;
dst[I].a1 := SaveValue shr 8;
dst[I].a2 := SaveValue shr 16;
end;
Form1.DSPFile.Write(dst[0], length * 24 div 32);
end;
I also have the big-endian conversion done, can you check if I did it right:
16 bit integer:
procedure DSP16bitBE(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
type
T16BitSample = record
a0 : Byte;
a1 : Byte;
end;
var
src : array of Single;
dst : array of T16BitSample;
i : Integer;
SaveValue : integer;
NumSamples : integer;
begin
SetLength(src, length);
SetLength(dst, length * 16 div 32); // Size * 16 bit (output bitrate) div 32 bit (input bitrate)
move(buffer^, src[0], length);
NumSamples := Length div (32 div 8); // 32 bit float div 8
for I := 0 to NumSamples - 1 do
begin
// convert to smallint (integer for headroom)
SaveValue := Trunc(src[I]*32768);
// clip it
if (SaveValue > 32767) then
SaveValue := 32767
else
if (SaveValue < -32768) then
SaveValue := -32768;
// store it (native endian)
dst[I].a0 := SaveValue shr 8;
dst[I].a1 := SaveValue;
end;
Form1.DSPFile.Write(dst[0], length * 16 div 32);
end;
24 bit integer:
procedure DSP24bitBE(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
type
T24BitSample = record
a0 : Byte;
a1 : Byte;
a2 : ShortInt;
end;
var
src : array of Single;
dst : array of T24BitSample;
i : Integer;
SaveValue : Integer;
NumSamples : integer;
begin
SetLength(src, length);
SetLength(dst, length * 24 div 32); // Size * 24 bit (output bitrate) div 32 bit (input bitrate)
move(buffer^, src[0], length);
NumSamples := Length div (32 div 8); // 32 bit float div 8
for I := 0 to NumSamples - 1 do
begin
// convert to integer
SaveValue := Trunc(src[I]*8388608);
// clip it
if (SaveValue > 8388607) then
SaveValue := 8388607
else
if (SaveValue < -8388608) then
SaveValue := -8388608;
// store it (big-endian)
dst[I].a0 := SaveValue shr 16;
dst[I].a1 := SaveValue shr 8;
dst[I].a2 := SaveValue;
end;
Form1.DSPFile.Write(dst[0], length * 24 div 32);
end;
32 bit integer:
procedure DSPProc32bitBE(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
type
T32BitSample = record
a0 : Byte;
a1 : Byte;
a2 : Byte;
a3 : Byte;
end;
var
src : array of Single;
dst : array of T32BitSample;
i : Integer;
SaveValue : Int64;
NumSamples : integer;
begin
SetLength(src, length);
SetLength(dst, length);
move(buffer^, src[0], length);
NumSamples := Length div (32 div 8); // 32 bit float div 8
for I := 0 to NumSamples - 1 do
begin
// convert to integer (64-bit for headroom)
SaveValue := Trunc(src[I]*2147483647);
// clip it
if (SaveValue > 2147483647) then
SaveValue := 2147483647
else
if (SaveValue < -2147483647) then
SaveValue := -2147483647;
// store it (native endian)
dst[I].a0 := SaveValue shr 24;
dst[I].a1 := SaveValue shr 16;
dst[I].a2 := SaveValue shr 8;
dst[I].a3 := SaveValue;
end;
Form1.DSPFile.Write(dst[0], length);
end;
The only thing I can't figure out is how the conversion from 32 float little-endian to 32 bit float big-endian looks like. Can you show it to me

Edit: I found the following on the web, seems to work but I don't know if it is correct:
type
//enumeration used in variant record
BytePos = (EndVal, ByteVal);
PEndianCnvRec = ^EndianCnvRec;
EndianCnvRec = packed record
case pos: BytePos of
//The value we are trying to convert
EndVal: (EndianVal: single);
//Overlapping bytes of the single
ByteVal: (Bytes: array[0..SizeOf(single)-1] of byte);
end;
//A gets B's values swapped
procedure SwapBytes( A, B: PEndianCnvRec );
var
i: integer;
begin
for i := high(A.Bytes) downto low(A.Bytes) do
A.Bytes[i] := B.Bytes[High(A.Bytes) - i];
end;
procedure DSPFloatBE(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
a,b: EndianCnvRec;
src : array of Single;
dst : array of Single;
NumSamples, I : Integer;
begin
SetLength(src, length);
SetLength(dst, length);
move(buffer^, src[0], length);
NumSamples := Length div (32 div 8); // 32 bit float div 8
for I := 0 to NumSamples - 1 do
begin
a.EndianVal := src[I];
SwapBytes(@b, @a);
dst[I] := b.EndianVal;
end;
Form1.DSPFile.Write(dst[0], length);
end;