May 23, 2019, 06:56:41 am

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


One more Problem using Bass library

Started by pistol350, July 13, 2008, 09:28:06 am

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

pistol350

Just a question about Bass library.
Maybe Krypt could help as he's spent so much time struggling with the conversion of the header. ;)

Before version 2.4.1 of the library, this line of code worked properly :

Code Select

BASS_ChannelSetAttributes(myMusicHandle, -1, MaxMusicVol, -101);


The function imported had that syntax :

Code Select
Declare Import, BASS_ChannelSetAttributes(UNSIGNED INT handle, INT freq, INT volume, INT pan),INT;

But since the latest version, many changes have been made to the library and even though i used their documentation,
i still can't get what expected from the sounds i play.

Here is the syntax of the new function in the bass.inc file. We no longer have 4 but 3 parameters plus a slight change.

Code Select
Declare Import, BASS_ChannelSetAttribute(UNSIGNED INT handle, UNSIGNED INT attrib, FLOAT *value),INT;

I expected the code below to work, but it does not.

Code Select
#define BASS_ATTRIB_VOL 2  // this is what we find in the original bass.h header
but i had no sound so i changed the value to any but 2 and the sound played  ??? ???

Code Select

BASS_ChannelSetAttribute(myMusicHandle, BASS_ATTRIB_VOL, MaxMusicVol);

My problem now is that i can no longer control the volume of the sounds i play.
In the declaration, we have a typed pointer "Float *value".
So i guess i have to access the data in the memory....
Frow now on i really need help as i tried so many things and ended up by making the program crash all the time.

Any suggestions please.
Regards,

Peter B.

Ionic Wind Support Team

You would need to use a FLOAT variable.  Does the documentation mention the accepted ranges?

Ionic Wind Support Team

ExMember001

July 13, 2008, 05:21:54 pm #2 Last Edit: July 13, 2008, 05:24:24 pm by KrYpT
since 2.4 volume value is a float, 0 = no sound, 1 =  Max volume
try using a value between like 0.50 or 0.75

Looks like i forgot to add the channel attributes constants to my Bass.inc
thanks for pointing out :)

pistol350

Quote from: Paul Turley on July 13, 2008, 12:37:33 pm
You would need to use a FLOAT variable.  Does the documentation mention the accepted ranges?




I used a float.I think the problem is indeed due to ranges.

Quote from: KrYpT on July 13, 2008, 05:21:54 pm
since 2.4 volume value is a float, 0 = no sound, 1 =  Max volume
try using a value between like 0.50 or 0.75

Looks like i forgot to add the channel attributes constants to my Bass.inc
thanks for pointing out :)


You're surely right Krypt, i totally ignored the fact that i used a float and no longer an integer so i used the former ranges values (0-100).
I'm not at home now so i'll give it a try tomorrow and let you guys know.
Thanks again.
Regards,

Peter B.

pistol350

I still can't get my problem fixed.
I know what i am doing wrong :
Code Select
Float MusicVol; Should be
Code Select
Float*MusicVol;
But when i define my variable as a float type pointer i don't access the datas properly which causes the program to crash.

Any help please ?

Code Select

#autodefine "OFF"
#include "bass.inc"

#define BASS_ATTRIB_VOL -1
HSTREAM myMusicHandler;
Float MusicVol;
Int run=1;
MusicVol=.5;
Global sub main()
{
//Init BASS and Audio Device
if(BASS_Init( -1,44100,0,0,null) = False)
{
messagebox(0, "Problem with Audio Device", "Warning");
goto end;
}

//load music
myMusicHandler = BASS_StreamCreateFile(false, getstartpath()+ "drumK.mp3", 0, 0, BASS_SAMPLE_LOOP);
//Start playing music
BASS_ChannelPlay(myMusicHandler,true);
Do
{
locate(10,10);
print("MusicVolume: ");
locate(10,23);
print(NumToStr(MusicVol));
VolumeControl();
}until GetKeyState(0x1b);
//Free Audio device
BASS_Free();
label end;
return 0;
}

/********************************************************************************************/

sub VolumeControl()
{
//set music volume
BASS_ChannelSetAttribute(myMusicHandler, BASS_ATTRIB_VOL, MusicVol);

if(GetKeyState(0x6b) and MusicVol <1) //add key
{
MusicVol=MusicVol+0.1f;  //Music volume 0.0 silent to 1.0
}
if(GetKeyState(0x6d) and MusicVol >0) //subtract key
{
MusicVol=MusicVol-0.1f;  //Music volume 0.0 silent to 1.0

}
}


attached is the sample code above + Bass.inc + Bass.DLL + a short mp3 sample.

Regards,

Peter B.

LarryMc

This is from the EBasic Help file about pointers.
Maybe this will help:
QuoteA pointer is a special type of variable that can reference, or point to, another variable. The pointer when initialized is said to reference another variable, or to contain a memory location. To understand pointers fully you need to remember some key concepts.

1) A variable is really a memory address,

2) The memory address is where the data is stored.

So when we assign a variable a value there are really two values involved. The first is the value we want to store, and the second is the starting address of the memory we want to store it in. That address is a value in and of itself. On 32 bit processors you can think of a memory address as a UINT type.

A = 1

Seems simple enough. Internally the compiler tells the linker that we want to move the number 1 into the address that A represents. That address is picked by the linker when your program is compiled and can be any where in your programs address space.

A pointer then is a variable that has an address, and in that address we store another address.


A = 1 : 'Store the number 1 in the address that A represents
DEF p as POINTER
p = A : 'Store the address of A into p

Retrieving the value that is contained in the address, that is stored in the pointer is called dereferencing.  In some texts you may see it referred to as indirection. The EBASIC compiler supports two general dereferencing operators, the # symbol and a 'C' style dereference operator, the '*'. The hash dereference '#' operator is unique to the EBASIC language and is suitable for most basic pointer needs.


PRINT #<INT>p

The above statement may look a bit strange. Lets break it down by what it does.

# - We want to perform a dereferencing operation

p - The pointer that contains the address of a variable

<INT> - The value stored in the address of the variable is of type INT

When we combine the two examples the dereferencing operation returns the number 1. The type between the < > is called type casting. The compiler must know what type is stored in the address being dereferenced. If the pointer was assigned directly as above you can omit the type cast and simplify the statement to:


PRINT #p

This only works if the pointer was assigned an actual variable and you haven't crossed a subroutine boundary with the pointer. The compiler will generate an error message of "Type cast must be specified" if it cannot automatically determine the type of the value an address contains. For pointers to a UDT variable (user data type) a typecast must always be specified.

You can determine the type that a pointer is currently referencing by using the TYPEOF function. If a pointer has never been assigned an address then TYPEOF will return -1.

Dereferencing operations can appear on both the left hand and right hand side of an assignment operation. In this way you can indirectly change the contents of a variable by using the pointer. Continuing with the statements from above:


#<INT>p = 2

Stores the value of 2 into the address of the variable pointed to by p and that variable is of type INT.

It is important to note that if a pointer is a NULL pointer then any dereferencing operation will result in an access violation crash. A NULL pointer is a pointer that hasn't been initialized, or assigned an address yet. This is the most common reason that programs fail. If your unsure what a pointer will contain, such as a pointer passed to a subroutine, then always test your pointers for NULL before performing a dereference operation.


IF p <> NULL
    #<INT>p = 2
ENDIF



Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

You don't use a float pointer.  The parameter is a pointer to a floating point variable, which is different.  The way you have it written looks correct as long as the documentation for the DLL is correct.

Strictly speaking you would have:

float MusicVolume
.....the rest of your code
BASS_ChannelSetAttribute(myMusicHandler, BASS_ATTRIB_VOL, &MusicVol);

The '&' is optional as Aurora automatically takes the address of the variable when passed to a pointer. 

If I were to hazard a guess, without trying out your code since I am in Linux right now, is it probably is a double and not a float.

double MusicVolume
.....the rest of your code
BASS_ChannelSetAttribute(myMusicHandler, BASS_ATTRIB_VOL, &MusicVol);

I won't get into the history of C, needles to say just about every C compiler type promotes floats to doubles internally when passing them to functions.  Just something to try as I am assuming BASS was written with a C/C++ compiler, perhaps even GCC.

Paul.

Ionic Wind Support Team

José Roca

Quote
Declare Import, BASS_ChannelSetAttribute(UNSIGNED INT handle, UNSIGNED INT attrib, FLOAT *value),INT;


The value parameter is not a pointer to a float, but a float passed by value.

The original C declare is as follows:

Code Select

BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value);


FLOAT *value is correct for BASS_ChannelGetAttribute, not for ChannelSetAttribute.

Code Select

BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value);


pistol350

Quote from: JosÃÆ'Ã,© Roca on July 18, 2008, 12:42:50 am
Quote
Declare Import, BASS_ChannelSetAttribute(UNSIGNED INT handle, UNSIGNED INT attrib, FLOAT *value),INT;


The value parameter is not a pointer to a float, but a float passed by value.

The original C declare is as follows:

Code Select

BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value);

Actu
FLOAT *value is correct for BASS_ChannelGetAttribute, not for ChannelSetAttribute.

Code Select

BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value);




Oh my oh my, i've just realized that i partially fixed the problem and now i cause myself more pain in the a**.  :-\
Actually, I noticed that too, but in the original bass.inc converted by Krypt, there was this mistake above,
which i corrected in the bass.inc i provide in the zip attached. this file is the one in the folder i compiled the program and i forgot to update the header in my INCLUDE folder too.
BTW, at first i found it odd that one parameter was different for both BASS_ChannelSetAttribute() and BASS_ChannelGetAttribute().
I now understand a little more the reason why.


@Paul,
I'll try what you said taking into account that i'm not using a float pointer nor a pointer to a floating point variable.
Pointers really are another philosophy  ;D

@Larry,
Thank you Larry.
I've read alot about pointers, reference, dereferencing operations..... But it seems that i've not learned a lot.
I'll go back to reading. ;)

Thank you all.

Regards,

Peter B.

pistol350

Ok, now that we know that we don't have a pointer to a float but just a float passed by value.

Float MusicVol=.5 should work but although initialised to .5, when the value is displayed only a "0" appears and when i press "+" or "-" value rather jumps to "1" or (oddly) to "-0"  ???
It should increase or decrease by .1 as stated.

I'm am obviously doing something wrong.
Any idea please ?
Regards,

Peter B.

ExMember001

Here's a quick fix using double as Paul said.

Code Select

#autodefine "OFF"
#include "bass.inc"

#define BASS_ATTRIB_VOL 2
HSTREAM myMusicHandler;
double MusicVol = 0.5;


Global sub main()
{
//Init BASS and Audio Device
if(BASS_Init( -1,44100,0,0,null) = False)
{
messagebox(0, "Problem with Audio Device", "Warning");
goto end;
}

//load music
myMusicHandler = BASS_StreamCreateFile(false, getstartpath()+ "drumK.mp3", 0, 0, BASS_SAMPLE_LOOP);

//set music volume
BASS_ChannelSetAttribute(myMusicHandler, BASS_ATTRIB_VOL, MusicVol);

//Start playing music
BASS_ChannelPlay(myMusicHandler,true);

Do
{
locate(10,10);
print(USING("MusicVolume: %d#.##",MusicVol));
VolumeControl();
}until GetKeyState(0x1b);
//Free Audio device
BASS_Free();
label end;
return 0;
}

/********************************************************************************************/

sub VolumeControl()
{

//set music volume
BASS_ChannelSetAttribute(myMusicHandler, BASS_ATTRIB_VOL, MusicVol);

if(GetKeyState(0x6b) & MusicVol < 0.9) //add key
{
MusicVol += 0.1;  //Music volume 0.0 silent to 1.0
}
if(GetKeyState(0x6d) & MusicVol > 0.1) //subtract key
{
MusicVol -= 0.1;  //Music volume 0.0 silent to 1.0
}

}

pistol350

July 20, 2008, 11:51:50 am #11 Last Edit: July 21, 2008, 04:32:31 pm by pistol350
Thanks Krypt!
I'll give it a try tomorrow.

EDIT : It works fine now   8)
Thank you so much!

Regards,

Peter B.