AllegroMP3 == chaos in my mind.
Albin Engström

I have never seen something more confusing than the AllegroMP3 example file.. yes, i don't have enough knowledge but still, an example file should only include the things necessary and related to the subject, in this case to play an mp3 file.
And it should be commented.

This might sound a little lazy but.. could someone please post a piece of code of AllegroMP3 that only includes the very minimum required code to play an mp3 file?.

thanks!

Kibiz0r

It's been a long time since I used it, but I thought it was something like ALMP3_load(), ALMP3_play()... I'll go check it out, though.

Heh, okay... maybe not.

Quote:

Server not found

:-/

CGamesPlay

You have to open a file, seek to the end of it, find the offset of that position, seek to the beginning, create a buffer of the same size as the file, read the file into the buffer, than pass that to AlMP3, IIRC.

Archon
Quote:

create a buffer of the same size as the file

Does 'seeking' actually give you purely PCM data (as it has VBR and probably metadata in each frame)?

OP: Basically, MP3 and all other codecs should decode to a common format (like .wav files - which is why they're so big), but each codec does it differently.

Unless you want to stream it, you'll need to create a normal SAMPLE and then uncompress the PCM data of the MP3 file into the data attribute, as well as give it the metadata (bits[rate], stereo, freq[uency], len[gth]) so the SAMPLE knows how much data data describes. Then you should be able to just play it like you play a normal .wav file.

CGamesPlay
Quote:

Unless you want to stream it, you'll need to create a normal SAMPLE and then uncompress the PCM data of the MP3 file into the data attribute, as well as give it the metadata (bits[rate], stereo, freq[uency], len[gth]) so the SAMPLE knows how much data data describes. Then you should be able to just play it like you play a normal .wav file.

And why would anyone use AlMP3 if they had to do this? :P

Quote:

Does 'seeking' actually give you purely PCM data (as it has VBR and probably metadata in each frame)?

No, it gives you the size of the MP3 file. AlMP3 doesn't know how to read files, so you can for instance pass in an MP3 stored in a datafile.

Albin Engström

OK.. maybe all that 'crap' wasn't unnecessary.. thanks for your help!!
Unfortunately i have to spend some time with my friends watching "eurovision song contest" or whatever, then i'll be able to get down to work.

If you have a more detailed version on how to make it work then don't hesitate to post it.

I thank thee!

Archon
Quote:

And why would anyone use AlMP3 if they had to do this? :P

I don't know! I can't think straight (it was 2:10am) :P

I'm just recalling what I'm trying to do with libvorbisfile and libFLAC for OpenAL... Not so fun if I can't test it in the middle of programming it.

Kibiz0r

Wow, how is ALMP3 a billion times more complicated than I remember it?

I was able to use it while I was still working on my first game, which was pure C with ridiculously awful practices and an endearingly noob-ish lack of skill/knowledge... I got through by the skin of my teeth. I wonder how I was able to contend with ALMP3.

Thomas Fjellstrom

You can't stream the mp3s directly of the disk by just sending chunks of data instead of it all? Loading up a 3-5MB mp3 just to send to almp3 seems a bit silly when libmad lets you load and decode on the fly.

Albin Engström
Thomas Fjellstrom said:

You can't stream the mp3s directly of the disk by just sending chunks of data instead of it all? Loading up a 3-5MB mp3 just to send to almp3 seems a bit silly when libmad lets you load and decode on the fly.

I think you can.
ALMP3_MP3 *s; to create a non-stream type.
ALMP3_MP3STREAM *s; to create a stream type.

Anyway: i'm accepting the AllegroMP3 challenge and now i'm facing my first opponent. PACKFILES! i'm having a huge problem understanding these fellas.
First of: how do i create a packfile? is there a tool?

Thomas Fjellstrom

A normal allegro packfile is just a regular file that can optionally be moderately compressed. pack_fopen pack_fread pack_fclose etc. The api is very similar to the libc standard file io routines.

Now if you mean datafiles, theres dat.exe and grabber.exe

Albin Engström

nono! not datafiles, i have those under control.. :).
so how would i go about to create a packfile with for example a mp3file?
would i create a new program and use pack routines with fstream? or something..

gah, something like this would have made my day:

packfile.write("iman.mp3");

- -.

Thomas Fjellstrom

Ah, the packfile stuff is very similar to "stdio".

PACKFILE *pf = pack_fopen("w", "filename");
pack_fwrite(data, sizeof_data, pf);
pack_fclose(pf);

Albin Engström

"PACKFILE *pf = pack_fopen("w", "filename");"
This loads a packfile right?

pack_fwrite(data, sizeof_data, pf);
Is this where you write to the opened datafile?
so whats data representing? or rather how would i load this data and to use with this function? and how would i get sizeof_data?

Thomas Fjellstrom
Quote:

This loads a packfile right?

It just opens it, for "w"riting in this case.

Quote:

Is this where you write to the opened datafile?

Packfile, and yes.

char data[256];
PACKFILE *pf = pack_fopen("r", "filename");
pack_fread(data, 256, pf);
pack_fclose(pf);

And that will read the first 256 bytes of whatever is in "filename", and place it in data.

CGamesPlay
Quote:

You can't stream the mp3s directly of the disk by just sending chunks of data instead of it all?

No, you can. That's why AlMP3 doesn't provide filename-based functions and lets you do the dirty work. If it did, it would cut out a lot of the features.

Albin Engström
char data[256];
PACKFILE *pf = pack_fopen("r", "filename");
pack_fread(data, 256, pf);
pack_fclose(pf);

ok, so thats how i read..

to write however:

pack_fwrite(data, sizeof_data, pf);

manual said:

from memory location pointed to by `p'.

memory means? can i replace data with the path to the mp3? (hopes for an easy solution)..

why: char data[256]??
why does it read the first 256bytes? can't i have more than one information in one packfile? can i nest packfiles?

Thomas Fjellstrom
Quote:

memory means?

Any memory address. like a pointer to something. Generally an array of some kind is used (since using it without the []s it acts like a pointer, and thus works in functions like these).
Everything in a running program is stored in memory. variables, functions, etc. You can also get a "pointer" to them as well, and use that pointer in functions that take one.

Quote:

can i replace data with the path to the mp3? (hopes for an easy solution)..

If you want to read the mp3, you just place the filename in the "filename" bit in pack_fopen, and then use pack_fread to read it in.

Quote:

why: char data[256]??

Because. No reason, just some random number I picked.

Quote:

why does it read the first 256bytes?

Because a file "read" position starts at 0 by default, and I put "256" in the size bit in pack_fread, its also the size of the array (you never want to read more data than can fit in your memory variable).

Quote:

can't i have more than one information in one packfile?

IIRC its limited to about 2-4GB

Quote:

can i nest packfiles?

Yes. Though thats a little more complex than just normal packfiles.

Albin Engström
Quote:

Though thats a little more complex than just normal packfiles.

Aka nothing i should bother with..

Well, below is my pathetic attempt to make a simple function to load and play mp3 files.. this didn't work, it doesn't crash either, which should have been preferred..

1#define DATASZ (1<<15)
2#define BUFSZ (1<<16)
3 
4void *open_mp3_file(char *filename)
5{
6 using namespace sfx::music;
7
8 PACKFILE *mp3file = NULL;
9 ALMP3_MP3STREAM *mp3 = NULL;
10 char data[DATASZ];
11 int len;
12
13 mp3file = pack_fopen(filename, F_READ);
14 len = pack_fread(data, DATASZ, mp3file);
15
16 if (len < DATASZ) {
17 mp3 = almp3_create_mp3stream(data, len, TRUE);
18 }
19 else
20 {
21 mp3 = almp3_create_mp3stream(data, DATASZ, FALSE);
22 }
23
24 almp3_play_mp3stream(mp3, DATASZ, 255, 128);
25
26}

:-/

Thomas Fjellstrom

DATAZ is only 256kb in size, with a 128kb/s mp3, thats about 2 seconds of mp3 data.

Also, I think the MP3STREAM/mp3stream stuff is for streaming off the disk, so you read X bytes every so often and send into the stream, where as it looks like you want to just load it all and send, in which case, you need to dynamically allocate "data" with "malloc" or "new" the size of the file, and then send it using the non stream functions.

CGamesPlay
Quote:

DATAZ is only 256kb in size, with a 128kb/s mp3, thats about 2 seconds of mp3 data.

No, it's 32 KB.

Thomas Fjellstrom

Yeah, somehow I got the math wrong, its 1024kb, which is 8 seconds of playtime with a 128kb/s mp3.

CGamesPlay
Quote:

#define DATASZ (1<<15)

It's 32,768 bytes long. 32 kilobytes.

Thomas Fjellstrom

OOps, I'm really fuzzy this morning. I was right to begin with. I'm talking BITS here not bytes. To match with the way mp3s are labeled (in kbits/s).

32KB * 8bits is a whole 256kbits.

Do you see now what I'm talking about?

Albin Engström

I think my muscles was just replaced by lead.. ???.. sight..
I feel like i'm in a deadlock, to learn this, i need to learn that, but too learn that, i need to learn this. Anyway, just working my ass of usually shows results so here's some more questions(my definition of working my ass of 8-)):

Ok, the goal is to load and play a mp3 non-streamed..

trying to get a grip on >what i have to do to get it to work< is important.
see comments for comments:

1//the ultimate lazy-man project function:
2void whatever()
3{
4 PACKFILE *mp3file = NULL;// is a pack file really requiered and what is a
5 //packfile??
6
7 ALMP3_MP3 *mp3 = NULL;//how is this data type built up? and what is the idea of
8 //having this thing?
9
10 char data[x];//ok? what the hell is this?
11 //why is the "data" stored as an char array?
12
13 int len;//what is this?...
14
15 len = pack_fread(data, x, mp3file);//see above..
16 
17 mp3file = pack_fopen(filename, F_READ);//this is obviously something packfile
18 //related.. what should filename be? the path in char data type? ex: "muu.mp3".??
19
20 //following(copying the example) this section makes less sense after
21 //pathetically converting it for non streamed type.
22 if (len < x) //ok..
23 {
24 mp3 = almp3_create_mp3(data, len);
25 }
26 else
27 {
28 mp3 = almp3_create_mp3(data, x);
29 }
30 //ok.. so use the lowest value when creating the mp3.. why??
31 //is this because of the streaming thingie?
32
33 almp3_play_mp3stream(mp3, x, 255, 128);//trying to play it..
34 //mp3 = the mp3.. x = size of what? how do i allcolate the space required?
35 // 255 volume or pitch of something i don't need to focus on right now.
36
37}

It's not easy being a newbie, :).
Thanks a lot for eventual answers! really! :P

Thomas Fjellstrom
Quote:

is a pack file really requiered and what is a packfile??

Yes, and its just a file handle. You use it to read and/or write to files.

Quote:

how is this data type built up? and what is the idea of having this thing

Almp3 provides the type and builds it for you with 'almp3_create_mp3'.

char data[x];//ok? what the hell is this?
//why is the "data" stored as an char array?

What type does almp3_create_mp3 take? char*? or void*? use which ever it happens to take, then follow the "len" directions.

int len;//what is this?...Its the length of the mp3 data in bytes.

Something like this should work:

unsigned int len = file_size_ex("filename.ext");
void *data = malloc(len);
if(data == NULL) { DIE A HORRIBLE DEATH! }

len = pack_fread(data, x, mp3file);//see above..
Should change that to:
len = pack_fread(data, len, mp3file);pack_fread returns the actual number of bytes read, so if it didn't read all of "len" you only have that many...

  mp3file = pack_fopen(filename, F_READ);//this is obviously something packfile    
  //related.. what should filename be? the path in char data type? ex: "muu.mp3".??

This really needs to go above the pack_fread. really. And the filename can be "whatever.mp3" or any C string.

almp3_play_mp3stream(mp3, x, 255, 128);//trying to play it..
Almost:
almp3_play_mp3stream(mp3, len, 255, 128);You have to tell it how much data there is to decode.

hth.

Albin Engström

Another attempt... i'm really grateful for the help, and i'm sorry i'm learning this so slowly - -.

1void muu(char filename)
2{
3 using namespace sfx::music;
4
5 mp3file = NULL;
6 mp3 = NULL;
7
8 mp3file = pack_fopen(filename, F_READ);//opens a file?
9
10 unsigned int len;//unsigned?
11 len = file_size_ex(filename);//gets the size of file?
12
13 char *data = (char *) malloc (len);//malloc? googled it but didn't find any
14 //explanations i could understand..
15 
16 if(data == NULL) {allegro_message("MOOO");};
17
18 len = pack_fread(data, len, mp3file);//i don't really understand whats going on
19 //here, first len got the value of "file size" and now what?
20
21 mp3 = almp3_create_mp3(data, len);
22
23 almp3_play_mp3(mp3, len, 255, 128);//mp3 = what to "decode" len = how much to
24 //"decode"?
25}

Quote:

int almp3_poll_mp3(ALMP3_MP3 *mp3);
This functions needs to be called in order to keep the ALMP3_MP3
playing properly, since the mp3s need to be decoded at real time
(either that, or to a huge memory buffer).

I got the impression this was only used for streaming?

This didn't work, it didn't crash, i just didn't play. It's funny how you sometimes want it to crash... at least that gives you a clue about whats wrong.

Help appreciated!

off-topic: how come pixels colored "0,0,1" display the underlying active mediaplayer window... in windowed mode. i use vlc mediaplayer.

Thomas Fjellstrom
1void muu(char filename)
2{
3 using namespace sfx::music;
4
5 mp3file = NULL;
6 mp3 = NULL;
7
8 mp3file = pack_fopen(filename, F_READ);//opens a file?
9 //> Yup.
10
11 unsigned int len;//unsigned?
12 //> A "signed" integer uses one bit for the "sign" (if its negative or positive) meaning you only have 31 bits of space, or a number up to 2billion instead of 4billion (2GB versus 4GB).
13 
14 len = file_size_ex(filename);//gets the size of file?
15 //> Yup.
16
17 char *data = (char *) malloc (len);//malloc? googled it but didn't find any
18 //explanations i could understand..
19 //> Ok, all computers have some ammount of "RAM", this is where programs are executed, and where programs store in use data, like loaded bitmaps, etc.
20 //> malloc lets you get a "len" sized chunk of it to use however you want.
21 
22 if(data == NULL) {allegro_message("MOOO");};
23 //> This is really a fatal error, using data after this check will cause memory corruption and a crash, or just a crash.
24
25 len = pack_fread(data, len, mp3file);//i don't really understand whats going on
26 //here, first len got the value of "file size" and now what?
27 //> Now that you have the "len" from file_size_ex, you pass it into fread so it attempts to read "len" bytes of data from the file (hopefully all of it).
28 //> If fread _can't_ read "len" bytes, it returns the number of bytes it did read, or -1 on error. Which makes me think it should actually be this instead:
29 long newlen = pack_fread(data, len, mp3file);
30 if(newlen == -1) {
31 // ERROR!
32 }
33 else if(newlen == 0) {
34 // Probably an error as well.
35 }
36 
37 len = newlen; //> save the new length.
38 
39 mp3 = almp3_create_mp3(data, len);
40
41 almp3_play_mp3(mp3, len, 255, 128);//mp3 = what to "decode" len = how much to
42 //"decode"?
43 //> Yup.
44}

Quote:

I got the impression this was only used for streaming?

What I and the others mean by streaming is incrementally loading the data of the disk and passing it into the decoder.

I suppose you could call what almp3 does with non mp3stream's streaming, but best not, otherwise it can get confusing.

almp3_poll_mp3 is used to tell almp3 to send some more data to the soundcard, a bit at a time, since you can't actually fit 40MB (decoded size of mp3 data) of sound data in most sound cards ;)

If almp3_poll_mp3 didn't poll in this fashion you'd need to decode all of the mp3 data into ram, and then place it into a SAMPLE, and play that. But that can eat up a lot of memory. So instead, it holds just the mp3 data, and when you poll, it decodes enough information to fill the buffer, and then queues it to play with allegro's sound system.

Albin Engström

Finally it worked!!.

You're my hero Thomas!! ;D.

thanks to all the other nice people too!!
WOOOHOOO!!!!

but i still have questions ^^:
1: what is the sign used for? (unsigned signed stuff).

2: malloc lets me use the memory however i want eh,
so examples of not using how i want would be: int, char and stuff?
i kinda get it but at the same time not.. no, i don't think i get it at all..

Thomas Fjellstrom
Quote:

1: what is the sign used for? (unsigned signed stuff).

If an integer is unsigned, its range is from 0 through 2^32
If an integer is signed (which all are by default), the range is -2^31 through 2^31.

Quote:

2: malloc lets me use the memory however i want eh,

It lets you get an arbitryily sized chunk of memory to use for just about anything. Dynamically allocating variables (int, char, arrays, structs, etc). Or whatever.

Thread #591367. Printed from Allegro.cc