Ok, thanks, I will take a look at it.
I have now implemented your first suggestion with STREAMPROC but I can't figure out something. Almost everything works, only the conversion from 24 bit audio to 32 bit floats doesn't work.
What do I want to do. I always want the BASS_StreamCreate function to get floating point data from the STREAMPROC callback function. So in the STREAMPROC I read the raw audio after I read the W64 header in another function. The raw data that is read I will convert to 32 bit float to give it back to the BASS_ChannelGetData function. All conversions (except the 24 bit to float) are done correctly. Also the files that are created (8, 16 and 32 bit to float conversions) are correct with timing and filesize. So what am I doing wrong with the 24 to float conversion? Also the final output with the 24 to float conversion gives wrong channels in the final output. Here is some of my code:
type
rWave64 = record
HeaderSize : integer;
Bitrate : DWord;
WavType : TWavType;
SampleRate : DWORD; // default playback rate
Channels : DWORD; // channels
DataPos : Int64;
end;
T24BitSample = packed record
a0 : Byte;
a1 : Byte;
a2 : ShortInt;
end;
PByteArray = ^TByteArray;
TByteArray = array [0..255] of Byte;
PSmallIntArray = ^TSmallIntArray;
TSmallIntArray = array [0..255] of SmallInt;
PInteger24Array = ^TInteger24Array;
TInteger24Array = array[0..255] of T24BitSample;
PIntegerArray = ^TIntegerArray;
TIntegerArray = array[0..255] of integer;
PFloatArray = ^TFloatArray;
TFloatArray = array [0..255] of Single;
function Cvt24BitTo32(Sample : T24BitSample) : integer;
begin
Result := Sample.a0 + (Sample.a1 shl 8) + (Sample.a2 shl 16);
end;
function ReadWave64(handle: DWord; buffer: Pointer; length: DWORD; user: Pointer): DWORD; stdcall;
var
Buf8 : PByteArray;
Buf16 : PSmallIntArray;
Buf24 : PInteger24Array;
Buf32i : PIntegerArray;
Buf32 : PFloatArray;
c : DWORD;
i : integer;
NumSamples: integer;
begin
Buf32 := PFloatArray(Buffer);
case TBassDecoder(user).FWave64.Bitrate of
8 : begin
Buf8 := PByteArray(Buffer);
c := TBassDecoder(user).FCustomStream.read(Buf8^[0], Length); // read the file into the buffer
if c <> DWORD(-1) then // check for EOF
begin
// convert data to float!!
NumSamples := c div (TBassDecoder(user).FWave64.Bitrate div 8);
for i := NumSamples -1 downto 0 do Buf32^[i] := (integer(Buf8^[i]) - 128) / 128;
result := c * 32 div TBassDecoder(user).FWave64.Bitrate;
end
else
result := BASS_STREAMPROC_END;
end;
16 : begin
Buf16 := PSmallIntArray(Buffer);
c := TBassDecoder(user).FCustomStream.read(Buf16^[0], Length); // read the file into the buffer
if c <> DWORD(-1) then // check for EOF
begin
// convert data to float!!
NumSamples := c div (TBassDecoder(user).FWave64.Bitrate div 8);
for i := NumSamples -1 downto 0 do Buf32^[i] := Buf16^[i] / 32768;
result := c * 32 div TBassDecoder(user).FWave64.Bitrate;
end
else
result := BASS_STREAMPROC_END;
end;
24 : begin
Buf24 := PInteger24Array(Buffer);
c := TBassDecoder(user).FCustomStream.read(Buf24^[0], Length); // read the file into the buffer
if c <> DWORD(-1) then // check for EOF
begin
// convert data to float!!
NumSamples := c div (TBassDecoder(user).FWave64.Bitrate div 8);
for i := NumSamples -1 downto 0 do Buf32^[i] := Cvt24BitTo32(Buf24^[i]) / 8388608;
result := c * 32 div TBassDecoder(user).FWave64.Bitrate;
end
else
result := BASS_STREAMPROC_END;
end;
32 : begin
if TBassDecoder(user).FWave64.WavType in [wtIEEEFloat, wtExtIEEEFloat] then
begin
c := TBassDecoder(user).FCustomStream.read(Buf32^[0], Length); // read the file into the buffer
if c <> DWORD(-1) then // check for EOF
begin
result := c;
end
else
result := BASS_STREAMPROC_END;
end
else
begin
Buf32i := PIntegerArray(Buffer);
c := TBassDecoder(user).FCustomStream.read(Buf32i^[0], Length); // read the file into the buffer
if c <> DWORD(-1) then // check for EOF
begin
// convert data to float!!
NumSamples := c div (TBassDecoder(user).FWave64.Bitrate div 8);
for i := 0 to NumSamples -1 do Buf32^[i] := Buf32i^[i] / 2147483648;
result := c;
end
else
result := BASS_STREAMPROC_END;
end;
end;
end;
end;
function TBassDecoder.Load(AFileName: String): Boolean;
begin
Close;
if (FLibrary = 0) then
begin
Result := False;
Exit;
end;
FStream := BASS_StreamCreateFile(False, PWideChar(AFileName), 0, 0, BASS_STREAM_DECODE or BASS_SAMPLE_FLOAT or BASS_UNICODE);
if (FStream = 0) then
begin
// check if it is a Wave64 file and fill Fwave64 with some header properties
fIsItWave64 := IsWave64(AFileName);
if fIsItWave64 then
begin
FStream := BASS_StreamCreate(FWave64.SampleRate, FWave64.Channels, BASS_STREAM_DECODE or BASS_SAMPLE_FLOAT, @ReadWave64, Self);
if (FStream = 0) then
begin
Result := False;
Exit;
end;
end;
end;
Result := True;
end;
procedure TBassDecoder.Close;
begin
if FStream = 0
then Exit;
BASS_StreamFree(FStream);
if FIsItWave64 then
begin
FCustomStream.Free;
fWave64.HeaderSize := 0;
fWave64.Bitrate := 0;
fWave64.WavType := wtUnsupported;
fWave64.SampleRate := 0;
fWave64.Channels := 0;
fWave64.DataPos := 0;
end;
end;
function TBassDecoder.GetData(ABuffer: Pointer; ASize: Integer): integer;
begin
Result := BASS_ChannelGetData(FStream, ABuffer, ASize);
end;
And here is a screen of the input file and output file (24 bit to float conversion):
