Warmice:
But I want to port mad to a simple system so there is no such complex function call available.My question is how can I write someting to replace mmap function call.
That's exactly what we just did, ran mad on a little OS-less embedded system.
To redundantly restate what Rob said: mmap() makes it *seem* as if the whole mp3 file has been read into an array.
Reading it into an array yourself will do the same thing, and that's how we first got mad running (with rather short mp3 songs to fit in our 256k of RAM :-).
Below is the main loop that we used instead of, more or less, the "decode()" routine in madplay.c. The routine that's called below, "WOSFS_Read()" is a simple file-read call.
(But it sounds like the current version of mad will do this for you already...)
-- David Van Brink
/* * * nios_mp3_getNextFrame() fills up the nios_mp3.synth * with one frame's worth of data, or returns an error. */
int nios_mp3_getNextFrame(nios_mp3 *nm) { int result = 0;
result = mad_frame_decode(&nm->frame,&nm->stream); // // the decode may fail due to a lack of source data, // in which case we'll read some and try again // if(result == -1 && (nm->stream.error == MAD_ERR_BUFLEN || nm->stream.error == MAD_ERR_BUFPTR)) { long tailSave; // how much is still good in the buffer long size = kFileBufferSize; // amount we'll try to have on-hand
if(nm->currentFilePosition >= nm->fileLength) { result = -1; goto goHome; }
tailSave = nm->stream.bufend - nm->stream.next_frame; size -= tailSave; #if NIOS_MP3_DEBUG printf("nios_mp3_getNextFrame: size = %d, tailSave = %d\n",size,tailSave); #endif
// Copy the tail to the head // memmove(nm->fileBuffer,nm->fileBuffer + nm->currentBufferSize - tailSave,tailSave);
// Clamp size to fileLength // if(nm->currentFilePosition + size > nm->fileLength) size = nm->fileLength - nm->currentFilePosition;
// Read in the new bytes //
WOSFS_Read(nm->fileNumber,nm->currentFilePosition,size,nm->fileBuffer + tailSave); nm->currentBufferSize = size + tailSave; nm->currentFilePosition += size;
// Give new buffer to the stream // mad_stream_buffer(&nm->stream, nm->fileBuffer, nm->currentBufferSize);
// And try that frame decode again (but no more after this!) // result = mad_frame_decode(&nm->frame,&nm->stream); }
if(result && nm->stream.error != 1) // "error" 1 is normal file-end printf("nios_mp3_getNextFrame: mad_frame_decode returned %d/%d\n", result,nm->stream.error);
if(result == -1) goto goHome;
nm->framesDecoded++; mad_synth_frame(&nm->synth,&nm->frame); nm->samplesGenerated += nm->synth.pcmlen;
goHome: return result; }
-----Original Message----- From: Rob Leslie [mailto:rob@mars.org] Sent: Sunday, October 01, 2000 9:00 AM To: warmice Cc: mad-dev@lists.mars.org Subject: Re: [mad-dev] question about mmap
The function mmap(....) appears several times in madplay.c and
minimad.c
.I don't know what the function will exactly do ,bu I think it's related with paging ?
The function maps the file into the memory address space of the process. The file can then be accessed directly with memory references rather than by calling read(). This is helpful because it enables random access without worries about buffering, as this is done in the kernel -- the file is paged into memory only as needed. It also eliminates copying data from the kernel's buffer into user space.
But I want to port mad to a simple system so there is no such complex function call available.My question is how can I write someting to replace mmap function call.
I don't know if Windows provides a similar capability. However, `madplay' has been written to work without it. Just don't define HAVE_MMAP.
Can I just allocate a mem buffer and read the file to the buffer and using the pointer to buffer as void * fdm in the main()? I try it but it seems
to
cause some error.When I decode to the almost end of a mp3 file ,it will sometimes report 0x0101 error.
/* fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0);*/ fdm = malloc(stat.st_size); inputstream = fdopen(STDIN_FILENO,"r"); fread(fdm,sizeof(char),stat.st_size,inputstream);
This will probably work, although it is perhaps a bit greedy to read the entire file into memory at once. You might prefer to read the file in chunks, as `madplay' will do when HAVE_MMAP is not defined.
The 0x0101 error means MAD lost synchronization with the bitstream. I have found this to be common if the file contains an ID3v1 tag at the end of the file; the tag is apparently not always located at a frame boundary. I will try to work around this, but for now you can ignore the error.