Esempio n. 1
0
bool Mp3PspStream::seek(const Timestamp &where) {
	DEBUG_ENTER_FUNC();

	if (where == _length) {
		_state = MP3_STATE_EOS;
		return true;
	} else if (where > _length) {
		return false;
	}

	const uint32 time = where.msecs();

	mad_timer_t destination;
	mad_timer_set(&destination, time / 1000, time % 1000, 1000);

	// Important to release and re-init the ME
	releaseStreamME();
	initStreamME();

	// Check if we need to rewind
	if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0) {
		initStream();
	}

	// Skip ahead
	while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
		findValidHeader();

	return (_state != MP3_STATE_EOS);
}
Esempio n. 2
0
File: mp3.cpp Progetto: Glyth/xoreos
bool MP3Stream::rewind() {
	mad_timer_t destination;
	mad_timer_set(&destination, 0, 0, 1000);

	if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0)
		initStream();

	while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
		readHeader();

	return (_state != MP3_STATE_EOS);
}
/* Do a seek based on the bitrate. */
int RageSoundReader_MP3::SetPosition_estimate( int iFrame )
{
	/* This doesn't leave us accurate. */
	mad->timer_accurate = 0;

	mad_timer_t seekamt;
	mad_timer_set( &seekamt, 0, iFrame, mad->Frame.header.samplerate );
	{
		/* We're going to skip ahead two samples below, so seek earlier than
		 * we were asked to. */
		mad_timer_t back_len = mad->framelength;
		mad_timer_multiply(&back_len, -2);
		mad_timer_add(&seekamt, back_len);
		if( mad_timer_compare(seekamt, mad_timer_zero) < 0 )
			seekamt = mad_timer_zero;
	}

	int seekpos = mad_timer_count( seekamt, MAD_UNITS_MILLISECONDS ) * (mad->bitrate / 8 / 1000);
	seekpos += mad->header_bytes;
	seek_stream_to_byte( seekpos );

	/* We've jumped across the file, so the decoder is currently desynced. 
	 * Don't use resync(); it's slow.  Just decode a few frames. */
	for( int i = 0; i < 2; ++i )
	{
		int ret = do_mad_frame_decode();
		if( ret <= 0 )
			return ret;
	}

	/* Throw out one synth. */
	synth_output();
	mad->outleft = 0;

	/* Find out where we really seeked to. */
	int ms = (get_this_frame_byte(mad) - mad->header_bytes) / (mad->bitrate / 8 / 1000);
	mad_timer_set(&mad->Timer, 0, ms, 1000);

	return 1;
}
Esempio n. 4
0
void audio_device::sound_seek(u32 pos, u32 total)
{
    /*
        This is all very rough and does not work well on VBR's
    */
    audio_wd_num = audio_rd_num = audio_wd = audio_rd = 0;
    audio_total_done = audio_total_decoded = 0;

    double fraction = (double)  pos / total;
    u32 position = (mad_timer_count(mp3->length, MAD_UNITS_MILLISECONDS) * fraction);

	mad_timer_set(&mp3->Timer, position / 1000, position % 1000, 1000);
}
Esempio n. 5
0
AudioStream *makeMP3Stream(
	Common::SeekableReadStream *stream,
	bool disposeAfterUse,
	uint32 startTime,
	uint32 duration,
	uint numLoops) {

	mad_timer_t start;
	mad_timer_t end;

	// Both startTime and duration are given in milliseconds.
	// Calculate the appropriate mad_timer_t values from them.
	mad_timer_set(&start, startTime / 1000, startTime % 1000, 1000);
	if (duration == 0) {
		end = mad_timer_zero;
	} else {
		int endTime = startTime + duration;
		mad_timer_set(&end, endTime / 1000, endTime % 1000, 1000);
	}

	return new MP3InputStream(stream, disposeAfterUse, start, end, numLoops);
}
Esempio n. 6
0
bool MP3Stream::seek(const Timestamp &where) {
	if (where == _length) {
		_state = MP3_STATE_EOS;
		return true;
	} else if (where > _length) {
		return false;
	}

	const uint32 time = where.msecs();

	mad_timer_t destination;
	mad_timer_set(&destination, time / 1000, time % 1000, 1000);

	if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0)
		initStream();

	while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
		readHeader();

	decodeMP3Data();

	return (_state != MP3_STATE_EOS);
}
Esempio n. 7
0
/* 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);
        buf->duration = header.duration;
    }

    else
    {
        /* the durations have been added up, and the number of frames
           counted. We do nothing here. */
    }
    
    mad_header_finish(&header);
    mad_stream_finish(&stream);
}
Esempio n. 8
0
/*
 * NAME:	parse_time()
 * DESCRIPTION:	parse a time specification string
 */
static
int parse_time(mad_timer_t *timer, char const *str)
{
  mad_timer_t time, accum = mad_timer_zero;
  signed long decimal;
  unsigned long seconds, fraction, fracpart;
  int minus;

  while (isspace((unsigned char) *str))
    ++str;

  do {
    seconds = fraction = fracpart = 0;

    switch (*str) {
    case '-':
      ++str;
      minus = 1;
      break;

    case '+':
      ++str;
    default:
      minus = 0;
    }

    do {
      decimal = strtol(str, (char **) &str, 10);
      if (decimal < 0)
	return -1;

      seconds += decimal;

      if (*str == ':') {
	seconds *= 60;
	++str;
      }
    }
    while (*str >= '0' && *str <= '9');

    if (*str == '.'
# if defined(HAVE_LOCALECONV)
	|| *str == *localeconv()->decimal_point
# endif
	) {
      char const *ptr;

      decimal = strtol(++str, (char **) &ptr, 10);
      if (decimal < 0)
	return -1;

      fraction = decimal;

      for (fracpart = 1; str != ptr; ++str)
	fracpart *= 10;
    }
    else if (*str == '/') {
      ++str;

      decimal = strtol(str, (char **) &str, 10);
      if (decimal < 0)
	return -1;

      fraction = seconds;
      fracpart = decimal;

      seconds  = 0;
    }

    mad_timer_set(&time, seconds, fraction, fracpart);
    if (minus)
      mad_timer_negate(&time);

    mad_timer_add(&accum, time);
  }
  while (*str == '-' || *str == '+');

  while (isspace((unsigned char) *str))
    ++str;

  if (*str != 0)
    return -1;

  *timer = accum;

  return 0;
}
int RageSoundReader_MP3::SetPosition_hard( int iFrame )
{
	mad_timer_t desired;
	mad_timer_set( &desired, 0, iFrame, mad->Frame.header.samplerate );

	/* This seek doesn't change the accuracy of our timer. */

	/* If we're already exactly at the requested position, OK. */
	if( mad_timer_compare(mad->Timer, desired) == 0 )
		return 1;

	/* We always come in here with data synthed.  Be careful not to synth the
	 * same frame twice. */
	bool synthed=true;

	/* If we're already past the requested position, rewind. */
	if(mad_timer_compare(mad->Timer, desired) > 0)
	{
		MADLIB_rewind();
		do_mad_frame_decode();
		synthed = false;
	}

	/* Decode frames until the current frame contains the desired offset. */
	while(1)
	{
		/* If desired < next_frame_timer, this frame contains the position.  Since we've
		 * already decoded the frame, synth it, too. */
		mad_timer_t next_frame_timer = mad->Timer;
		mad_timer_add( &next_frame_timer, mad->framelength );
		
		if( mad_timer_compare(desired, next_frame_timer) < 0 )
		{
			if( !synthed )
			{
				synth_output();
			}
			else
			{
				mad->outleft += mad->outpos;
				mad->outpos = 0;
			}

			/* We just synthed data starting at mad->Timer, containing the desired offset.
			 * Skip (desired - mad->Timer) worth of frames in the output to line up. */
			mad_timer_t skip = desired;
			mad_timer_sub( &skip, mad->Timer );

			int samples = mad_timer_count( skip, (mad_units) SampleRate );

			/* Skip 'samples' samples. */
			mad->outpos = samples * this->Channels;
			mad->outleft -= samples * this->Channels;
			return 1;
		}

		/* Otherwise, if the desired time will be in the *next* decode, then synth
		 * this one, too. */
		mad_timer_t next_next_frame_timer = next_frame_timer;
		mad_timer_add( &next_next_frame_timer, mad->framelength );

		if( mad_timer_compare(desired, next_next_frame_timer) < 0 && !synthed )
		{
			synth_output();
			synthed = true;
		}

		int ret = do_mad_frame_decode();
		if( ret <= 0 )
		{
			mad->outleft = mad->outpos = 0;
			return ret; /* it set the error */
		}

		synthed = false;
	}
}
/* Returns actual position on success, 0 if past EOF, -1 on error. */
int RageSoundReader_MP3::SetPosition_toc( int iFrame, bool Xing )
{
	ASSERT( !Xing || mad->has_xing );
	ASSERT( mad->length != -1 );

	/* This leaves our timer accurate if we're using our own TOC, and inaccurate
	 * if we're using Xing. */
	mad->timer_accurate = !Xing;

	int bytepos = -1;
	if( Xing )
	{
		/* We can speed up the seek using the XING tag.  First, figure
		 * out what percentage the requested position falls in. */
		ASSERT( SampleRate != 0 );
		int ms = int( (iFrame * 1000LL) / SampleRate );
		ASSERT( mad->length != 0 );
		int percent = ms * 100 / mad->length;
		if( percent < 100 )
		{
			int jump = mad->xingtag.toc[percent];
			bytepos = mad->filesize * jump / 256;
		}
		else
			bytepos = 2000000000; /* force EOF */

		mad_timer_set( &mad->Timer, 0, percent * mad->length, 100000 );
	}
	else
	{
		mad_timer_t desired;
		mad_timer_set( &desired, 0, iFrame, SampleRate );

		if( mad->tocmap.empty() )
			return 1; /* don't have any info */

		/* Find the last entry <= iFrame that we actually have an entry for;
		 * this will get us as close as possible. */
		madlib_t::tocmap_t::iterator it = mad->tocmap.upper_bound( desired );
		if( it == mad->tocmap.begin() )
			return 1; /* don't have any info */
		--it;

		mad->Timer = it->first;
		bytepos = it->second;
	}

	if( bytepos != -1 )
	{
		/* Seek backwards up to 4k. */
		const int seekpos = max( 0, bytepos - 1024*4 );
		seek_stream_to_byte( seekpos );

		do
		{
			int ret = do_mad_frame_decode();
			if( ret <= 0 )
				return ret; /* it set the error */
		} while( get_this_frame_byte(mad) < bytepos );
		synth_output();
	}

	return 1;
}
Esempio n. 11
0
static int count_time_internal (struct mp3_data *data)
{
	struct xing xing;
	unsigned long bitrate = 0;
	int has_xing = 0;
	int is_vbr = 0;
	int num_frames = 0;
	mad_timer_t duration = mad_timer_zero;
	struct mad_header header;
	int good_header = 0; /* Have we decoded any header? */

	mad_header_init (&header);
	xing_init (&xing);

	/* 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) {
		
		/* Fill the input buffer if needed */
		if (data->stream.buffer == NULL ||
			data->stream.error == MAD_ERROR_BUFLEN) {
			if (!fill_buff(data))
				break;
		}

		if (mad_header_decode(&header, &data->stream) == -1) {
			if (MAD_RECOVERABLE(data->stream.error))
				continue;
			else if (data->stream.error == MAD_ERROR_BUFLEN)
				continue;
			else {
				debug ("Can't decode header: %s",
						mad_stream_errorstr(
							&data->stream));
				break;
			}
		}

		good_header = 1;

		/* Limit xing testing to the first frame header */
		if (!num_frames++) {
			if (xing_parse(&xing, data->stream.anc_ptr,
						data->stream.anc_bitlen)
					!= -1) {
				is_vbr = 1;

				debug ("Has XING header");
				
				if (xing.flags & XING_FRAMES) {
					has_xing = 1;
					num_frames = xing.frames;
					break;
				}
				debug ("XING header doesn't contain number of "
						"frames.");
			}
		}				

		/* Test the first n frames to see if this is a VBR file */
		if (!is_vbr && !(num_frames > 20)) {
			if (bitrate && header.bitrate != bitrate) {
				debug ("Detected VBR after %d frames",
						num_frames);
				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) {
			debug ("Fixed rate MP3");
			break;
		}
			
		mad_timer_add (&duration, header.duration);
	}

	if (!good_header)
		return -1;

	if (!is_vbr) {
		/* time in seconds */
		double time = (data->size * 8.0) / (header.bitrate);
		
		double timefrac = (double)time - ((long)(time));

		/* samples per frame */
		long nsamples = 32 * MAD_NSBSAMPLES(&header);

		/* samplerate is a constant */
		num_frames = (long) (time * header.samplerate / nsamples);

		/* the average bitrate is the constant bitrate */
		data->avg_bitrate = bitrate;

		mad_timer_set(&duration, (long)time, (long)(timefrac*100),
				100);
	}
		
	else if (has_xing) {
		mad_timer_multiply (&header.duration, num_frames);
		duration = header.duration;
	}
	else {
		/* the durations have been added up, and the number of frames
		   counted. We do nothing here. */
		debug ("Counted duration by counting frames durations in "
				"VBR file.");
	}

	if (data->avg_bitrate == -1
			&& mad_timer_count(duration, MAD_UNITS_SECONDS) > 0) {
		data->avg_bitrate = data->size 
				/ mad_timer_count(duration, MAD_UNITS_SECONDS) * 8;
	}

	mad_header_finish(&header);

	debug ("MP3 time: %ld", mad_timer_count (duration, MAD_UNITS_SECONDS));

	return mad_timer_count (duration, MAD_UNITS_SECONDS);
}
Esempio n. 12
0
/*
 * NAME:	fadein_filter()
 * DESCRIPTION:	fade-in filter
 */
enum mad_flow fadein_filter(void *data, struct mad_frame *frame)
{
  struct player *player = data;

  if (mad_timer_compare(player->stats.play_timer, player->fade_in) < 0) {
    mad_timer_t frame_start, frame_end, ratio;
    unsigned int nch, nsamples, s;
    mad_fixed_t step, scalefactor;

    /*
     * Fade-in processing may occur over the entire frame, or it may end
     * somewhere within the frame. Find out where processing should end.
     */

    nsamples = MAD_NSBSAMPLES(&frame->header);

    /* this frame has not yet been added to play_timer */

    frame_start = frame_end = player->stats.play_timer;
    mad_timer_add(&frame_end, frame->header.duration);

    if (mad_timer_compare(player->fade_in, frame_end) < 0) {
      mad_timer_t length;

      length = frame_start;

      mad_timer_negate(&length);
      mad_timer_add(&length, player->fade_in);

      mad_timer_set(&ratio, 0,
		    mad_timer_count(length, frame->header.samplerate),
		    mad_timer_count(frame->header.duration,
				    frame->header.samplerate));

      nsamples = mad_timer_fraction(ratio, nsamples);
    }

    /* determine starting scalefactor and step size */

    mad_timer_set(&ratio, 0,
		  mad_timer_count(frame_start, frame->header.samplerate),
		  mad_timer_count(player->fade_in, frame->header.samplerate));

    scalefactor = mad_timer_fraction(ratio, MAD_F_ONE);
    step = MAD_F_ONE / (mad_timer_count(player->fade_in,
					frame->header.samplerate) / 32);

    /* scale subband samples */

    nch = MAD_NCHANNELS(&frame->header);

    for (s = 0; s < nsamples; ++s) {
      unsigned int ch, sb;

      for (ch = 0; ch < nch; ++ch) {
	for (sb = 0; sb < 32; ++sb) {
	  frame->sbsample[ch][s][sb] =
	    mad_f_mul(frame->sbsample[ch][s][sb], scalefactor);
	}
      }

      scalefactor += step;
    }
  }

  return MAD_FLOW_CONTINUE;
}