Author Topic: range check error with bass_channelgetdata  (Read 138 times)

mikeanders

  • Guest
Delphi.

Code: [Select]
r := BASS_ChannelGetData(BStream, @Bdata[0], Sizeof(BData));
I am using decode flag. When the file is a loop, bass_channelgetdata will wrap around and begin at the loop start point - meaning an exit is never reached (if r <= 0), which is probably the correct behaviour? However, with no loop, I get a range check error on the line above, which is incorrect behaviour. Hopefully this time it isn't me being a dork.  But I don't think so.

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #1 on: 7 Aug '17 - 01:23 »
The range check error happens when BASS_ChannelGetData tries to copy data from past the end of BStream.  But my understanding is that this should fail silently and R should equal the number of bytes that were actually copied.

Ian @ un4seen

  • Administrator
  • Posts: 20210
Re: range check error with bass_channelgetdata
« Reply #2 on: 7 Aug '17 - 17:34 »
I'm not a Delphi user myself, so I'm not sure, but looking at the LIVESPEC.DPR example from the BASS package, I notice it doesn't have the "[0]" bit in its BASS_ChannelGetData call. Are you sure that's needed in your case? Also, what type are using for the "r" variable? It should be "DWORD" or perhaps "LongInt" (not "Integer"); if you have a "if r <= 0" line then it should probably be "LongInt".

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #3 on: 7 Aug '17 - 18:24 »
The normal convention for delphi when sending an array address to something is to include the
  • . That makes it point to the first item in the array. From what I've always seen, that's always been recommended and I am sure I've had crashes in certain projects when not using it. The range error happens even when I don't use it.


I am using "LongInt" for R, which is the Delphi standard for a 32 bit signed integer value (since R can be -1). There should definitely be 

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #4 on: 7 Aug '17 - 18:25 »
is to include the
Code: [Select]
[0] that should have read.


The normal convention for delphi when sending an array address to something is to include the
Code: [Select]
[0]That makes it point to the first item in the array. From what I've always seen, that's always been recommended and I am sure I've had crashes in certain projects when not using it. The range error happens even when I don't use it.

I am using "LongInt" for R, which is the Delphi standard for a 32 bit signed integer value (since R can be -1).

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #5 on: 7 Aug '17 - 18:45 »
Someone else online mentions

Quote
@array is NOT SAME as @array[0] or @array[0, 0], it is simply not, just like string[0] is something else, for arrays you need to point your pointer AT THE DATA, NOT at the variable itself, the structure of the variable is not guaranteed to be same on all compilers, but the DATA is, so point at the data and not at the variable, because variable may contain internal structures to represent and hold the actual data.

3delite

  • Posts: 890
Re: range check error with bass_channelgetdata
« Reply #6 on: 7 Aug '17 - 20:20 »
There are 2 scenarios, either Bdata is a dynamic or a static array. If it's a dynamic, you have to include the [ 0 ]. If it's a static array or a pointer, you don't (but can).

The r should be declared as DWord and test for -1 with:

Code: [Select]
    if r = DW_ERROR then...

Hope it helps!

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #7 on: 7 Aug '17 - 20:37 »
Changing to Dword won't change a thing. And it doesn't - since that isn't the cause of the range error.

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #8 on: 7 Aug '17 - 20:44 »
Although the r = DW_ERROR  might.

But why would that make a difference?  R is meant to be assigned -1 - which would work as well with LongInt as it would with DWord.  So that would still be rather poor.

3delite

  • Posts: 890
Re: range check error with bass_channelgetdata
« Reply #9 on: 7 Aug '17 - 21:26 »
I just wrote how it should be done correctly, you can go your own route if you think it would be better.

You didn't tell how is Bdata declared.

EDIT: Sizeof(BData) is wrong, If the array is of Single it should be:

Code: [Select]
    Length(BData) * 4

BASS_ChannelGetData() returns a DWord. And you are limiting the value to a signed type. Probably this is the reason you get the range check error.
« Last Edit: 7 Aug '17 - 21:38 by 3delite »

Chris

  • Posts: 1804
Re: range check error with bass_channelgetdata
« Reply #10 on: 7 Aug '17 - 21:42 »
Code: [Select]
var
fft        : array[0..1023] of Single;

if BASS_ChannelGetData(Channel, @fft, BASS_DATA_FFT2048)<> DW_ERROR then
begin
 // do some with the fft
end;

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #11 on: 7 Aug '17 - 22:35 »
Sizeof(BData)

Will return the correct size on its own.  Try it in Delphi.  An array [0..4] of single will return 5 * 4 (20).

Quote
BASS_ChannelGetData() returns a DWord

Dword is an unsigned integer (it's the exact same as Delphi's LongWord). The bass documentation says that BASS_ChannelGetData can return -1. So either it's a signed integer or the bass documentation is wrong. http://www.bass.radio42.com/help/html/a13cfef0-1056-bb94-81c4-a4fdf21bd463.htm

I am thinking it's the latter.  if so, that needs to be corrected, as it leads to a lot of confusion.  When I check to see what value is assigned to the error.

Code: [Select]
if BASS_ChannelGetData(Channel, @fft, BASS_DATA_FFT2048)<> DW_ERROR then
begin

Can't do that, since R is needed for other calculations - and I don't use fft calcs anyway.  But the DW_Error usage that 3delite wrote does seem to work. But there is an issue here somewhere - and it's probably the bass documentation.


mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #12 on: 7 Aug '17 - 22:39 »
Or Bass returns -1 despite normally returning a DWORD value... which seems to me to be a very strange way of doing things.

Chris

  • Posts: 1804
Re: range check error with bass_channelgetdata
« Reply #13 on: 7 Aug '17 - 23:05 »
The Return of DW_Error(-1)  is in Delphi 4294967295
another possible way can be

Code: [Select]
var
r:DWORD;
begin
  r:= BASS_ChannelGetData(Channel, nil, BASS_DATA_AVAILABLE);
 if r <> DW_Error then
begin
  r:= BASS_ChannelGetData(Channel, @fft, BASS_DATA_FFT2048)............
end;
« Last Edit: 7 Aug '17 - 23:10 by Chris »

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #14 on: 7 Aug '17 - 23:59 »
The Return of DW_Error(-1)  is in Delphi 4294967295

Which is a valid Dword value FF FF FF FF.... so that seems totally crazy to me to ever use that value as an error with an unsigned integer (It's not good practice).  4294967295 is -1 with a signed integer.  So what is going on here?  Is bass outputting FF FF FF FF as an unsigned int... or as signed? They are the same thing as a raw hex value. 

I'm using if r <> DW_Error then exit, as it's part of a loop that must exit the function when broken. That works fine.

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #15 on: 8 Aug '17 - 01:01 »
It's made clear in bass.pas

 DW_ERROR = LongWord(-1); // -1 (DWORD)

This is a very very strange way of doing things.  I've never seen this before. All that this is really doing is assigning FF FF FF FF to DW_Error. DW_Error isn't even needed...  basically, bass is using 0xFFFFFFFF as the error code and NOT -1. You cannot have "-1" with a longword as LongWord is unsigned (it's the exact same as Dword).  So, either the author of bass has made some sort of mistake, or this is just sloppy code.

In either case, the documentation should not be saying that -1 is the return error.  It isn't.  The return error is (2^32) -1 or 0xFFFFFFFF.  Personally, as I say, I have never seen this done before.  Usually -1 is an error code with a LongInt or Int64 type.  If the maximum data size allowed to be returned is an unsigned 32 bit value, then strictly speaking, Int64 should be used so that -1 can be the error.  If a 32 bit signed value is the maximum, then LongInt should be the type with -1 being the error. 

The bass documentation needs amending whatever the case. And the DW_Error is really just a constant value of FF FF FF FF - so should just be a const with the following code

Code: [Select]
DW_Error = LongWord ($FFFFFFFF); 

mikeanders

  • Guest
Re: range check error with bass_channelgetdata
« Reply #16 on: 8 Aug '17 - 01:12 »
I suppose the idea is that a file size of 2 ^ 32 -1 isn't possible or allowed, in which case an error being $FFFFFFFF is perfectly fine.  But the documentation does need altering to notify people that the returned value is a. an unsigned 32 bit value and b. that the error code is 0xFFFFFFFF (4294967295).  That would have saved us this entire thread :P