本文整理汇总了C++中MAD_RECOVERABLE函数的典型用法代码示例。如果您正苦于以下问题:C++ MAD_RECOVERABLE函数的具体用法?C++ MAD_RECOVERABLE怎么用?C++ MAD_RECOVERABLE使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了MAD_RECOVERABLE函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: mp3_decode_frame
static int mp3_decode_frame (mp3_s *mp3)
{
if (mp3->stream.buffer == NULL || mp3->stream.error == MAD_ERROR_BUFLEN) {
if (mp3_fill_input (mp3) < 0) {
return DECODE_BREAK;
}
}
if (mad_frame_decode (&mp3->frame, &mp3->stream)) {
if (MAD_RECOVERABLE (mp3->stream.error)) {
return DECODE_CONT;
} else {
if (mp3->stream.error == MAD_ERROR_BUFLEN) {
return DECODE_CONT;
} else {
printf ("Unrecoverable frame error: \'%s\'\n", mad_stream_errorstr (&mp3->stream));
mp3->status = 1;
return DECODE_BREAK;
}
}
}
mp3->frame_count++;
return DECODE_OK;
}
示例2: getNumChannels
//
// Read up samples from madSynth_
// If needed, read some more MP3 data, decode them and synth them
// Place in audioBuffer_.
// Return number of samples read.
//
size_t MadDecoder::decode(size_t numPendingTotal, AudioBuffer* buffer)
{
size_t numProcessedTotal = 0;
int numChannels = getNumChannels();
mad_fixed_t sample;
do {
size_t numPendingFrame = (madSynth_.pcm.length - currentFrame_) * numChannels;
numPendingFrame = std::min(numPendingTotal, numPendingFrame);
size_t numProcessedFrame = 0;
while (numProcessedFrame < numPendingFrame)
{
for (int channel = 0; channel < numChannels; channel++)
{
sample = madSynth_.pcm.samples[channel][currentFrame_];
if (sample < -MAD_F_ONE)
sample = -MAD_F_ONE;
else if (sample >= MAD_F_ONE)
sample = MAD_F_ONE - 1;
float fSample = (float)(sample / (float)(1L << MAD_F_FRACBITS));
float* pos = buffer->getHead() + numProcessedTotal;
*pos = fSample;
numProcessedFrame++;
numProcessedTotal++;
}
currentFrame_++;
}
numPendingTotal -= numProcessedFrame;
if (numPendingTotal == 0)
break;
if (madStream_.error == MAD_ERROR_BUFLEN) { // check whether input buffer needs a refill
if (readMpgFile() == false) // eof
break;
}
if (mad_frame_decode(&madFrame_, &madStream_))
{
if (MAD_RECOVERABLE(madStream_.error)) {
consumeId3Tag();
continue;
}
else {
if (madStream_.error == MAD_ERROR_BUFLEN)
continue;
else
THROW(std::exception, "unrecoverable frame level error (%s).", mad_stream_errorstr(&madStream_));
}
}
mad_timer_add(&madTimer_, madFrame_.header.duration);
mad_synth_frame(&madSynth_, &madFrame_);
currentFrame_ = 0;
numMpegFrames_++;
} while (true);
return numProcessedTotal;
}
示例3: file
int TrackDuration::duration(const QFileInfo &fileinfo)
{
QString fn = fileinfo.absoluteFilePath();
if (fn.isEmpty())
return 0;
QFile file(fn);
if (!file.open(QFile::ReadOnly))
return 0;
mad_stream infostream;
mad_header infoheader;
mad_timer_t infotimer;
mad_stream_init(&infostream);
mad_header_init(&infoheader);
mad_timer_reset(&infotimer);
qint64 r;
qint64 l = 0;
unsigned char* buf = new unsigned char[INPUT_BUFFER_SIZE];
while (!file.atEnd()) {
if (l < INPUT_BUFFER_SIZE) {
r = file.read(reinterpret_cast<char*>(buf) + l, INPUT_BUFFER_SIZE - l);
l += r;
}
mad_stream_buffer(&infostream, buf, l);
for (;;) {
if (mad_header_decode(&infoheader, &infostream)) {
if (!MAD_RECOVERABLE(infostream.error))
break;
if (infostream.error == MAD_ERROR_LOSTSYNC) {
TagLib::ID3v2::Header header;
uint size = (uint)(infostream.bufend - infostream.this_frame);
if (size >= header.size()) {
header.setData(TagLib::ByteVector(reinterpret_cast<const char*>(infostream.this_frame), size));
uint tagsize = header.tagSize();
if (tagsize > 0) {
mad_stream_skip(&infostream, qMin(tagsize, size));
continue;
}
}
}
qDebug() << "header decode error while getting file info" << infostream.error;
continue;
}
mad_timer_add(&infotimer, infoheader.duration);
}
if (infostream.error != MAD_ERROR_BUFLEN && infostream.error != MAD_ERROR_BUFPTR)
break;
memmove(buf, infostream.next_frame, &(buf[l]) - infostream.next_frame);
l -= (infostream.next_frame - buf);
}
mad_stream_finish(&infostream);
mad_header_finish(&infoheader);
delete[] buf;
return timerToMs(&infotimer);
}
示例4: readMP3Data
void MP3Stream::readHeader() {
if (_state != MP3_STATE_READY)
return;
// If necessary, load more data into the stream decoder
if (_stream.error == MAD_ERROR_BUFLEN)
readMP3Data();
while (_state != MP3_STATE_EOS) {
_stream.error = MAD_ERROR_NONE;
// Decode the next header. Note: mad_frame_decode would do this for us, too.
// However, for seeking we don't want to decode the full frame (else it would
// be far too slow). Hence we perform this explicitly in a separate step.
if (mad_header_decode(&_frame.header, &_stream) == -1) {
if (_stream.error == MAD_ERROR_BUFLEN) {
readMP3Data(); // Read more data
continue;
} else if (MAD_RECOVERABLE(_stream.error)) {
//status("MP3Stream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
continue;
} else {
warning("MP3Stream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
break;
}
}
// Sum up the total playback time so far
mad_timer_add(&_totalTime, _frame.header.duration);
break;
}
if (_stream.error != MAD_ERROR_NONE)
_state = MP3_STATE_EOS;
}
示例5: DEBUG_ENTER_FUNC
// Seek in the stream, finding the next valid header
void Mp3PspStream::findValidHeader() {
DEBUG_ENTER_FUNC();
if (_state != MP3_STATE_READY)
return;
// If necessary, load more data into the stream decoder
if (_stream.error == MAD_ERROR_BUFLEN)
readMP3DataIntoBuffer();
while (_state != MP3_STATE_EOS) {
_stream.error = MAD_ERROR_NONE;
// Decode the next header.
if (mad_header_decode(&_header, &_stream) == -1) {
if (_stream.error == MAD_ERROR_BUFLEN) {
readMP3DataIntoBuffer(); // Read more data
continue;
} else if (MAD_RECOVERABLE(_stream.error)) {
debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
continue;
} else {
warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
break;
}
}
// Sum up the total playback time so far
mad_timer_add(&_totalTime, _header.duration);
break;
}
if (_stream.error != MAD_ERROR_NONE)
_state = MP3_STATE_EOS;
}
示例6: decode_next_frame_header
static enum mp3_action
decode_next_frame_header(struct mp3_data *data, G_GNUC_UNUSED struct tag **tag)
{
enum mad_layer layer;
if ((data->stream).buffer == NULL
|| (data->stream).error == MAD_ERROR_BUFLEN) {
if (!mp3_fill_buffer(data))
return DECODE_BREAK;
}
if (mad_header_decode(&data->frame.header, &data->stream)) {
if ((data->stream).error == MAD_ERROR_LOSTSYNC &&
(data->stream).this_frame) {
signed long tagsize = id3_tag_query((data->stream).
this_frame,
(data->stream).
bufend -
(data->stream).
this_frame);
if (tagsize > 0) {
if (tag && !(*tag)) {
mp3_parse_id3(data, (size_t)tagsize,
tag);
} else {
mad_stream_skip(&(data->stream),
tagsize);
}
return DECODE_CONT;
}
}
if (MAD_RECOVERABLE((data->stream).error)) {
return DECODE_SKIP;
} else {
if ((data->stream).error == MAD_ERROR_BUFLEN)
return DECODE_CONT;
else {
g_warning("unrecoverable frame level error "
"(%s).\n",
mad_stream_errorstr(&data->stream));
return DECODE_BREAK;
}
}
}
layer = data->frame.header.layer;
if (!data->layer) {
if (layer != MAD_LAYER_II && layer != MAD_LAYER_III) {
/* Only layer 2 and 3 have been tested to work */
return DECODE_SKIP;
}
data->layer = layer;
} else if (layer != data->layer) {
/* Don't decode frames with a different layer than the first */
return DECODE_SKIP;
}
return DECODE_OK;
}
示例7: scan_file
static void
scan_file (FILE * fd, int *length, int *bitrate)
{
struct mad_stream stream;
struct mad_header header;
mad_timer_t timer;
unsigned char buffer[8192];
unsigned int buflen = 0;
mad_stream_init (&stream);
mad_header_init (&header);
timer = mad_timer_zero;
while (1)
{
if (buflen < 8192)
{
int bytes = 0;
bytes = fread (buffer + buflen, 1, 8192 - buflen, fd);
if (bytes <= 0)
break;
buflen += bytes;
}
mad_stream_buffer (&stream, buffer, buflen);
while (1)
{
if (mad_header_decode (&header, &stream) == -1)
{
if (!MAD_RECOVERABLE (stream.error))
break;
continue;
}
if (length)
mad_timer_add (&timer, header.duration);
}
if (stream.error != MAD_ERROR_BUFLEN)
break;
memmove (buffer, stream.next_frame, &buffer[buflen] - stream.next_frame);
buflen -= stream.next_frame - &buffer[0];
SDL_Delay(1);
}
mad_header_finish (&header);
mad_stream_finish (&stream);
if (length)
*length = mad_timer_count (timer, MAD_UNITS_MILLISECONDS);
}
示例8: mad_stream_buffer
static const void *mp_registersong (music_player_t *music, const void *data, unsigned len)
{
mp_player_t *mp = (mp_player_t*)music;
int i;
int maxtry;
int success = 0;
// the MP3 standard doesn't include any global file header. the only way to tell filetype
// is to start decoding stuff. you can't be too strict however because MP3 is resilient to
// crap in the stream.
// this routine is a bit slower than it could be, but apparently there are lots of files out
// there with some dodgy stuff at the beginning.
// if the stream begins with an ID3v2 magic, search hard and long for our first valid header
if (memcmp (data, "ID3", 3) == 0)
maxtry = 100;
// otherwise, search for not so long
else
maxtry = 20;
mad_stream_buffer (&mp->Stream, data, len);
for (i = 0; i < maxtry; i++)
{
if (mad_header_decode (&mp->Header, &mp->Stream) != 0)
{
if (!MAD_RECOVERABLE (mp->Stream.error))
{
lprintf (LO_WARN, "mad_registersong failed: %s\n", mad_stream_errorstr (&mp->Stream));
return NULL;
}
}
else
{
success++;
}
}
// 80% to pass
if (success < maxtry * 8 / 10)
{
lprintf (LO_WARN, "mad_registersong failed\n");
return NULL;
}
lprintf (LO_INFO, "mad_registersong succeed. bitrate %lu samplerate %d\n", mp->Header.bitrate, mp->Header.samplerate);
mp->mp_data = data;
mp->mp_len = len;
// handle not used
return data;
}
示例9: mad_js_decode_frame
/* Returns 1 if a recoverable error occured, 0 else. */
int mad_js_decode_frame(madfile_t *mf)
{
int dec;
dec = mad_frame_decode(&mf->frame, &mf->stream);
if (dec) {
if (MAD_RECOVERABLE(mf->stream.error)
|| mf->stream.error == MAD_ERROR_BUFLEN) {
return 1;
} else {
_mad_js_raise(mad_stream_errorstr(&mf->stream));
}
}
mad_synth_frame(&mf->synth, &mf->frame);
return 0;
}
示例10: while
int LibMadWrapper::findValidHeader(struct mad_header &header)
{
int ret;
while ((ret = mad_header_decode(&header, this->stream)) != 0 && MAD_RECOVERABLE(this->stream->error))
{
if (this->stream->error == MAD_ERROR_LOSTSYNC)
{
long tagsize = id3_tag_query(this->stream->this_frame, this->stream->bufend - this->stream->this_frame);
if (tagsize > 0)
{
mad_stream_skip(this->stream, tagsize);
continue;
}
}
}
return ret;
}
示例11: decodeNextFrame
static enum mp3_action
decodeNextFrame(struct mp3_data *data)
{
if ((data->stream).buffer == NULL
|| (data->stream).error == MAD_ERROR_BUFLEN) {
if (!mp3_fill_buffer(data))
return DECODE_BREAK;
}
if (mad_frame_decode(&data->frame, &data->stream)) {
#ifdef HAVE_ID3TAG
if ((data->stream).error == MAD_ERROR_LOSTSYNC) {
signed long tagsize = id3_tag_query((data->stream).
this_frame,
(data->stream).
bufend -
(data->stream).
this_frame);
if (tagsize > 0) {
mad_stream_skip(&(data->stream), tagsize);
return DECODE_CONT;
}
}
#endif
if (MAD_RECOVERABLE((data->stream).error)) {
return DECODE_SKIP;
} else {
if ((data->stream).error == MAD_ERROR_BUFLEN)
return DECODE_CONT;
else {
g_warning("unrecoverable frame level error "
"(%s).\n",
mad_stream_errorstr(&data->stream));
return DECODE_BREAK;
}
}
}
return DECODE_OK;
}
示例12: xmms_mad_init
static gboolean
xmms_mad_init (xmms_xform_t *xform)
{
struct mad_frame frame;
struct mad_stream stream;
xmms_error_t err;
guchar buf[40960];
xmms_mad_data_t *data;
int len;
const gchar *metakey;
g_return_val_if_fail (xform, FALSE);
data = g_new0 (xmms_mad_data_t, 1);
mad_stream_init (&data->stream);
mad_frame_init (&data->frame);
mad_synth_init (&data->synth);
xmms_xform_private_data_set (xform, data);
data->buffer_length = 0;
data->synthpos = 0x7fffffff;
mad_stream_init (&stream);
mad_frame_init (&frame);
len = xmms_xform_peek (xform, buf, 40960, &err);
mad_stream_buffer (&stream, buf, len);
while (mad_frame_decode (&frame, &stream) == -1) {
if (!MAD_RECOVERABLE (stream.error)) {
XMMS_DBG ("couldn't decode %02x %02x %02x %02x",buf[0],buf[1],buf[2],buf[3]);
mad_frame_finish (&frame);
mad_stream_finish (&stream);
return FALSE;
}
}
data->channels = frame.header.mode == MAD_MODE_SINGLE_CHANNEL ? 1 : 2;
data->samplerate = frame.header.samplerate;
if (frame.header.flags & MAD_FLAG_PROTECTION) {
XMMS_DBG ("Frame has protection enabled");
if (stream.anc_ptr.byte > stream.buffer + 2) {
stream.anc_ptr.byte = stream.anc_ptr.byte - 2;
}
}
data->samples_to_play = -1;
data->xing = xmms_xing_parse (stream.anc_ptr);
if (data->xing) {
xmms_xing_lame_t *lame;
XMMS_DBG ("File with Xing header!");
metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_IS_VBR;
xmms_xform_metadata_set_int (xform, metakey, 1);
if (xmms_xing_has_flag (data->xing, XMMS_XING_FRAMES)) {
guint duration;
mad_timer_t timer;
timer = frame.header.duration;
mad_timer_multiply (&timer, xmms_xing_get_frames (data->xing));
duration = mad_timer_count (timer, MAD_UNITS_MILLISECONDS);
XMMS_DBG ("XING duration %d", duration);
metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION;
xmms_xform_metadata_set_int (xform, metakey, duration);
if (xmms_xing_has_flag (data->xing, XMMS_XING_BYTES) && duration) {
guint tmp;
tmp = xmms_xing_get_bytes (data->xing) * ((guint64)8000) / duration;
XMMS_DBG ("XING bitrate %d", tmp);
metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE;
xmms_xform_metadata_set_int (xform, metakey, tmp);
}
}
lame = xmms_xing_get_lame (data->xing);
if (lame) {
/* FIXME: add a check for ignore_lame_headers from the medialib */
data->frames_to_skip = 1;
data->samples_to_skip = lame->start_delay;
data->samples_to_play = ((guint64) xmms_xing_get_frames (data->xing) * 1152ULL) -
lame->start_delay - lame->end_padding;
XMMS_DBG ("Samples to skip in the beginning: %d, total: %" G_GINT64_FORMAT,
data->samples_to_skip, data->samples_to_play);
/*
metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_ALBUM;
xmms_xform_metadata_set_int (xform, metakey, lame->audiophile_gain);
metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PEAK_TRACK;
xmms_xform_metadata_set_int (xform, metakey, lame->peak_amplitude);
//.........这里部分代码省略.........
示例13: mp_render_ex
static void mp_render_ex (void *dest, unsigned nsamp)
{
short *sout = (short *) dest;
int localerrors = 0;
if (!mp_playing || mp_paused)
{
memset (dest, 0, nsamp * 4);
return;
}
while (1)
{
// write any leftover data from last MP3 frame
while (mp_leftoversamps > 0 && nsamp > 0)
{
short s = mp_fixtoshort (Synth.pcm.samples[0][mp_leftoversamppos]);
*sout++ = s;
if (Synth.pcm.channels == 2)
s = mp_fixtoshort (Synth.pcm.samples[1][mp_leftoversamppos]);
// if mono, just duplicate the first channel again
*sout++ = s;
mp_leftoversamps -= 1;
mp_leftoversamppos += 1;
nsamp -= 1;
}
if (nsamp == 0)
return; // done
// decode next valid MP3 frame
while (mad_frame_decode (&Frame, &Stream) != 0)
{
if (MAD_RECOVERABLE (Stream.error))
{ // unspecified problem with one frame.
// try the next frame, but bail if we get a bunch of crap in a row;
// likely indicates a larger problem (and if we don't bail, we could
// spend arbitrarily long amounts of time looking for the next good
// packet)
localerrors++;
if (localerrors == 10)
{
lprintf (LO_WARN, "mad_frame_decode: Lots of errors. Most recent %s\n", mad_stream_errorstr (&Stream));
mp_playing = 0;
memset (sout, 0, nsamp * 4);
return;
}
}
else if (Stream.error == MAD_ERROR_BUFLEN)
{ // EOF
// FIXME: in order to not drop the last frame, there must be at least MAD_BUFFER_GUARD
// of extra bytes (with value 0) at the end of the file. current implementation
// drops last frame
if (mp_looping)
{ // rewind, then go again
mad_stream_buffer (&Stream, mp_data, mp_len);
continue;
}
else
{ // stop
mp_playing = 0;
memset (sout, 0, nsamp * 4);
return;
}
}
else
{ // oh well.
lprintf (LO_WARN, "mad_frame_decode: Unrecoverable error %s\n", mad_stream_errorstr (&Stream));
mp_playing = 0;
memset (sout, 0, nsamp * 4);
return;
}
}
// got a good frame, so synth it and dispatch it.
mad_synth_frame (&Synth, &Frame);
mp_leftoversamps = Synth.pcm.length;
mp_leftoversamppos = 0;
}
// NOT REACHED
}
示例14: read_next_frame
/* Reads the next frame from the file. Returns true on success or
false on failure. */
static int
read_next_frame(mad_data *mp3_mad) {
if (mp3_mad->stream.buffer == NULL ||
mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
size_t read_size;
size_t remaining;
unsigned char *read_start;
/* There might be some bytes in the buffer left over from last
time. If so, move them down and read more bytes following
them. */
if (mp3_mad->stream.next_frame != NULL) {
remaining = mp3_mad->stream.bufend - mp3_mad->stream.next_frame;
memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
read_start = mp3_mad->input_buffer + remaining;
read_size = MAD_INPUT_BUFFER_SIZE - remaining;
} else {
read_size = MAD_INPUT_BUFFER_SIZE;
read_start = mp3_mad->input_buffer;
remaining = 0;
}
/* Now read additional bytes from the input file. */
read_size = SDL_RWread(mp3_mad->src, read_start, 1, read_size);
if (read_size <= 0) {
if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
if (read_size == 0) {
mp3_mad->status |= MS_input_eof;
} else {
mp3_mad->status |= MS_input_error;
}
/* At the end of the file, we must stuff MAD_BUFFER_GUARD
number of 0 bytes. */
SDL_memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
read_size += MAD_BUFFER_GUARD;
}
}
/* Now feed those bytes into the libmad stream. */
mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
read_size + remaining);
mp3_mad->stream.error = MAD_ERROR_NONE;
}
/* Now ask libmad to extract a frame from the data we just put in
its buffer. */
if (mad_frame_decode(&mp3_mad->frame, &mp3_mad->stream)) {
if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
return 0;
} else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
return 0;
} else {
mp3_mad->status |= MS_decode_error;
return 0;
}
}
mp3_mad->frames_read++;
mad_timer_add(&mp3_mad->next_frame_start, mp3_mad->frame.header.duration);
return 1;
}
示例15: scan
/* Following two functions are adapted from mad_timer, from the
libmad distribution */
void scan(void const *ptr, ssize_t len, buffer *buf)
{
struct mad_stream stream;
struct mad_header header;
struct xing xing;
unsigned long bitrate = 0;
int has_xing = 0;
int is_vbr = 0;
mad_stream_init(&stream);
mad_header_init(&header);
mad_stream_buffer(&stream, ptr, len);
buf->num_frames = 0;
/* There are three ways of calculating the length of an mp3:
1) Constant bitrate: One frame can provide the information
needed: # of frames and duration. Just see how long it
is and do the division.
2) Variable bitrate: Xing tag. It provides the number of
frames. Each frame has the same number of samples, so
just use that.
3) All: Count up the frames and duration of each frames
by decoding each one. We do this if we've no other
choice, i.e. if it's a VBR file with no Xing tag.
*/
while (1)
{
if (mad_header_decode(&header, &stream) == -1)
{
if (MAD_RECOVERABLE(stream.error))
continue;
else
break;
}
/* Limit xing testing to the first frame header */
if (!buf->num_frames++)
{
if(parse_xing(&xing, stream.anc_ptr, stream.anc_bitlen))
{
is_vbr = 1;
if (xing.flags & XING_FRAMES)
{
/* We use the Xing tag only for frames. If it doesn't have that
information, it's useless to us and we have to treat it as a
normal VBR file */
has_xing = 1;
buf->num_frames = xing.frames;
break;
}
}
}
/* Test the first n frames to see if this is a VBR file */
if (!is_vbr && !(buf->num_frames > 20))
{
if (bitrate && header.bitrate != bitrate)
{
is_vbr = 1;
}
else
{
bitrate = header.bitrate;
}
}
/* We have to assume it's not a VBR file if it hasn't already been
marked as one and we've checked n frames for different bitrates */
else if (!is_vbr)
{
break;
}
mad_timer_add(&buf->duration, header.duration);
}
if (!is_vbr)
{
double time = (len * 8.0) / (header.bitrate); /* time in seconds */
double timefrac = (double)time - ((long)(time));
long nsamples = 32 * MAD_NSBSAMPLES(&header); /* samples per frame */
/* samplerate is a constant */
buf->num_frames = (long) (time * header.samplerate / nsamples);
mad_timer_set(&buf->duration, (long)time, (long)(timefrac*100), 100);
}
else if (has_xing)
{
/* modify header.duration since we don't need it anymore */
mad_timer_multiply(&header.duration, buf->num_frames);
//.........这里部分代码省略.........