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(a)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.
--
Rob Leslie
rob(a)mars.org