Пример #1
0
Mp3PspStream::Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
	_inStream(inStream),
	_disposeAfterUse(dispose),
	_pcmLength(0),
	_posInFrame(0),
	_state(MP3_STATE_INIT),
	_length(0, 1000),
	_sampleRate(0),
	_totalTime(mad_timer_zero) {

	DEBUG_ENTER_FUNC();

	assert(_decoderInit);	// must be initialized by now

	// let's leave the buffer guard -- who knows, it may be good?
	memset(_buf, 0, sizeof(_buf));
	memset(_codecInBuffer, 0, sizeof(_codecInBuffer));

	initStream();	// init needed stuff for the stream

	findValidHeader();	// get a first header so we can read basic stuff

	_sampleRate = _header.samplerate;	// copy it before it gets destroyed
	_stereo = (MAD_NCHANNELS(&_header) == 2);

	while (_state != MP3_STATE_EOS)
		findValidHeader();	// get a first header so we can read basic stuff

	_length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate());

	deinitStream();

	_state = MP3_STATE_INIT;
}
Пример #2
0
static int mp3_read (song_s *song, char *buffer)
{
  static int i;
  static int ret;
  static struct audio_dither dither;
  static char buffer2[BUF_SIZE];
  static char *out_ptr = buffer2;
  static char *out_buf_end = buffer2 + BUF_SIZE;
  mp3_s *mp3 = song->songlib->mp3;

  mad_timer_add (&mp3->timer, mp3->frame.header.duration);
  mad_synth_frame (&mp3->synth, &mp3->frame);
  mp3->elapsed_time = ((float)mad_timer_count (mp3->timer, MAD_UNITS_MILLISECONDS))/1000.0;
  
  for (i = 0; i < mp3->synth.pcm.length; i++) {
    signed int sample;
    sample = (signed int)audio_linear_dither (16, mp3->synth.pcm.samples[0][i], &dither);
   
    *(out_ptr++) = sample & 0xff;
    *(out_ptr++) = sample >> 8;

    if (MAD_NCHANNELS (&(mp3->frame).header) == 2) {
      sample = (signed int) audio_linear_dither (16, mp3->synth.pcm.samples[1][i], &dither);

      *(out_ptr++) = sample & 0xff;
      *(out_ptr++) = sample >> 8;
    }

    if (out_ptr == out_buf_end) {
      memcpy (buffer, buffer2, BUF_SIZE);
      bossao_play_chunk (song, buffer, BUF_SIZE);
      out_ptr = buffer2;
    }
  }
void fill_frame_index_cache( madlib_t *mad )
{
	int ms, percent, pos;

	/* Only update the frame cache if our timer is consistent. */
	if(!mad->timer_accurate) return;

	/* ms of the frame we just decoded: */
	ms = mad_timer_count(mad->Timer, MAD_UNITS_MILLISECONDS);
	percent = ms * 100 / mad->length;
	pos = get_this_frame_byte(mad);

	/* Fill in the TOC percent. */
	if( !mad->tocmap.empty() )
	{
		/* Don't add an entry if one already exists near this time. */
		madlib_t::tocmap_t::iterator it = mad->tocmap.upper_bound( mad->Timer );
		if( it != mad->tocmap.begin() )
		{
			--it;
			int iDiffSeconds = mad->Timer.seconds - it->first.seconds;
			if( iDiffSeconds < 5 )
				return;
		}
	}

	mad->tocmap[mad->Timer] = pos;
}
Пример #4
0
static void
mp3_update_timer_next_frame(struct mp3_data *data)
{
	if (data->current_frame >= data->highest_frame) {
		/* record this frame's properties in
		   data->frame_offsets (for seeking) and
		   data->times */
		data->bit_rate = (data->frame).header.bitrate;

		if (data->current_frame >= data->max_frames)
			/* cap data->current_frame */
			data->current_frame = data->max_frames - 1;
		else
			data->highest_frame++;

		data->frame_offsets[data->current_frame] =
			mp3_this_frame_offset(data);

		mad_timer_add(&data->timer, (data->frame).header.duration);
		data->times[data->current_frame] = data->timer;
	} else
		/* get the new timer value from data->times */
		data->timer = data->times[data->current_frame];

	data->current_frame++;
	data->elapsed_time =
		mad_timer_count(data->timer, MAD_UNITS_MILLISECONDS) / 1000.0;
}
Пример #5
0
static enum mad_flow mad_header_cb(void *blob, const mad_header_t *header) {
    state_t *data = (state_t *)blob;

    data->sample_rate = header->samplerate;
    data->output_channels = MAD_NCHANNELS(header);
    data->output_size += mad_timer_count(header->duration, header->samplerate);
    return MAD_FLOW_IGNORE;
}
Пример #6
0
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);
}
Пример #7
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);
}
Пример #8
0
/*
 * NAME:	timer->count()
 * DESCRIPTION:	return timer value in selected units
 */
s32 mad_timer_count(mad_timer_t timer, enum mad_units units)
{
  switch (units) {
  case MAD_UNITS_HOURS:
    return timer.seconds / 60 / 60;

  case MAD_UNITS_MINUTES:
    return timer.seconds / 60;

  case MAD_UNITS_SECONDS:
    return timer.seconds;

  case MAD_UNITS_DECISECONDS:
  case MAD_UNITS_CENTISECONDS:
  case MAD_UNITS_MILLISECONDS:

  case MAD_UNITS_8000_HZ:
  case MAD_UNITS_11025_HZ:
  case MAD_UNITS_12000_HZ:
  case MAD_UNITS_16000_HZ:
  case MAD_UNITS_22050_HZ:
  case MAD_UNITS_24000_HZ:
  case MAD_UNITS_32000_HZ:
  case MAD_UNITS_44100_HZ:
  case MAD_UNITS_48000_HZ:

  case MAD_UNITS_24_FPS:
  case MAD_UNITS_25_FPS:
  case MAD_UNITS_30_FPS:
  case MAD_UNITS_48_FPS:
  case MAD_UNITS_50_FPS:
  case MAD_UNITS_60_FPS:
  case MAD_UNITS_75_FPS:
    return timer.seconds * (s32) units +
      (s32) scale_rational(timer.fraction, MAD_TIMER_RESOLUTION,
				   units);

  case MAD_UNITS_23_976_FPS:
  case MAD_UNITS_24_975_FPS:
  case MAD_UNITS_29_97_FPS:
  case MAD_UNITS_47_952_FPS:
  case MAD_UNITS_49_95_FPS:
  case MAD_UNITS_59_94_FPS:
    return (mad_timer_count(timer, -units) + 1) * 1000 / 1001;
  }

  /* unsupported units */
  return 0;
}
Пример #9
0
static long
mp3_time_to_frame(const struct mp3_data *data, double t)
{
	unsigned long i;

	for (i = 0; i < data->highest_frame; ++i) {
		double frame_time =
			mad_timer_count(data->times[i],
					MAD_UNITS_MILLISECONDS) / 1000.;
		if (frame_time >= t)
			break;
	}

	return i;
}
int RageSoundReader_MP3::GetLengthInternal( bool fast )
{
	if( mad->has_xing && mad->length != -1 )
		return mad->length; /* should be accurate */

	/* Check to see if a frame in the middle of the file is the same
	 * bitrate as the first frame.  If it is, assume the file is really CBR. */
	seek_stream_to_byte( mad->filesize / 2 );

	/* XXX use mad_header_decode and check more than one frame */
	if(mad->length != -1 &&
	   do_mad_frame_decode() &&
	   mad->bitrate == (int) mad->Frame.header.bitrate)
	{
		return mad->length;
	}

	if( !MADLIB_rewind() )
		return 0;

	/* Worst-case: vbr && !xing.  We've made a guess at the length, but let's actually
	 * scan the size, since the guess is probably wrong. */
	if( fast )
	{
		SetError("Can't estimate file length");
		return -1;
	}

	MADLIB_rewind();
	while(1)
	{
		int ret = do_mad_frame_decode( true );
		if( ret == -1 )
			return -1; /* it set the error */
		if( ret == 0 ) /* EOF */
			break;
	}

	/* mad->Timer is the timestamp of the current frame; find the timestamp of
	 * the very end. */
	mad_timer_t end = mad->Timer;
	mad_timer_add( &end, mad->framelength );

	/* Count milliseconds. */
	return mad_timer_count( end, MAD_UNITS_MILLISECONDS );
}
/* Called on the first frame decoded.  Returns true if this frame
 * should be ignored. */
bool RageSoundReader_MP3::handle_first_frame()
{
	bool ret = false;

	/* Check for a XING tag. */
	xing_init( &mad->xingtag );
	if( xing_parse(&mad->xingtag, mad->Stream.anc_ptr, mad->Stream.anc_bitlen) == 0 )
	{
		/*
		 * "Info" tags are written by some tools.  They're just Xing tags, but for
		 * CBR files.
		 * 
		 * However, DWI's decoder, BASS, doesn't understand this, and treats it as a
		 * corrupt frame, outputting a frame of silence.  Let's ignore the tag, so
		 * it'll be treated as an invalid frame, so we match DWI sync.
		 *
		 * The information in it isn't very useful to us.  The TOC is less accurate
		 * then computing it ourself (low resolution).  The file length computation
		 * might be wrong, if the tag is incorrect, and we can compute that accurately
		 * ourself for CBR files.
		 */
		if( mad->xingtag.type == xing::INFO )
			return false;

		mad->header_bytes = max( mad->header_bytes, get_this_frame_byte(mad) );

		mad->has_xing = true;

		mad_timer_t tm = mad->Frame.header.duration;
		/* XXX: does this include the Xing header itself? */
		mad_timer_multiply( &tm, mad->xingtag.frames );
		mad->length = mad_timer_count( tm, MAD_UNITS_MILLISECONDS );

		/* XXX: an id3v2 footer tag would throw this off a little. This also assumes
		 * the Xing tag is the last header; it always is, I think. */
		int bytes = mad->filesize - mad->header_bytes;
		mad->bitrate = (int)(bytes * 8 / (mad->length/1000.f));

		if( mad->xingtag.type == xing::XING )
			ret = 1;
	}

	/* If there's no Xing tag, mad->length will be filled in by _open. */

	return ret;
}
/* 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;
}
Пример #13
0
int
mp3_get_tag (Private * h, char *path, struct SongDBEntry *e)
{ 
    
    FILE *fd;
    mp3Private *mp3_priv = (mp3Private *) h;
    int length = 0;
    long size = 0;

    char *empty = strdup ("");
    char *title = NULL, *artist = NULL, *album = NULL;
    char *comment = NULL, *year = NULL, *genre = NULL;

    if( h == NULL ||  path == NULL ||  e ==NULL)
        return ERROR_INVALID_ARG;
  

    {
	struct id3_file *id3file;
	struct id3_tag *id3tag;
	id3_ucs4_t *ucs4;
	id3_latin1_t *latin1;
	struct id3_frame *frame;

	id3file = id3_file_open ( path, ID3_FILE_MODE_READONLY);
	if (id3file == NULL)
	{
            ERROR("get_tag: Error opening file: %s", strerror (errno));
            return -1;
	}

	id3tag = id3_file_tag (id3file);

	frame = id3_tag_findframe (id3tag, ID3_FRAME_TITLE, 0);
	if (frame != NULL)
	{
            ucs4 =
		(id3_ucs4_t *) id3_field_getstrings ((union id3_field const *)
                                                     &frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    title = strdup (latin1);
		}
            }
	}

	frame = id3_tag_findframe (id3tag, ID3_FRAME_ARTIST, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    artist = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_ALBUM, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    album = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_COMMENT,
                               0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    comment = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_YEAR, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		latin1 = id3_ucs4_latin1duplicate (ucs4);
		if (latin1 != NULL)
		{
                    year = strdup (latin1);
		}
            }
	}

	frame =
            id3_tag_findframe ((struct id3_tag const *) id3tag, ID3_FRAME_GENRE, 0);
	if (frame != NULL)
	{
            ucs4 = (id3_ucs4_t *) id3_field_getstrings (&frame->fields[1], 0);
            if (ucs4 != NULL)
            {
		ucs4 = (id3_ucs4_t *) id3_genre_name (ucs4);
		if (ucs4 != NULL)
		{
                    latin1 = id3_ucs4_latin1duplicate (ucs4);
                    if (latin1 != NULL)
                    {
			genre = strdup (latin1);
                    }
		}
            }
	}


	id3_file_close (id3file);
    }



     e->title   = title;
     e->artist  = artist;
     e->album   = album;
     e->comment = comment;
     e->year    = year;
     e->genre   = genre;


/* length calculation stuff */
    {
	struct mad_header header;
	struct xing xing;

	if(  e->AddInfo == NULL )
	{
             e->AddInfo = malloc( sizeof(struct SongAddInfo) );
            if( e->AddInfo == NULL)
                return ERROR_NO_MEMORY;
            memset(  e->AddInfo, 0, sizeof( struct SongAddInfo ));
	}

	fd = fopen ( path, "rb");
	if (fd == NULL)
	{
            ERROR("get_tag: Error opening file %s:%s",  path, strerror (errno));
            return ERROR_OPEN_ERROR;
	}

        fseek(fd,0,SEEK_END);
        size=ftell(fd);
        fseek(fd,0,SEEK_SET);
	 e->filesize = size;
        
	if (scan_header (fd, &header, &xing) == -1)
	{
            fclose (fd);

//            printf ("get_tag: Error Reading File\n");
            return ERROR_READ_SEEK_ERROR;
	}

	switch( header.layer )
	{
        case MAD_LAYER_I:  e->AddInfo->type = str_mpeg1_l1; break;
        case MAD_LAYER_II:  e->AddInfo->type = str_mpeg1_l2; break;
        case MAD_LAYER_III:
            if( header.flags & MAD_FLAG_MPEG_2_5_EXT )
                e->AddInfo->type = str_mpeg25_l3;
            else 
                 e->AddInfo->type = str_mpeg1_l3;
            break;
        default:  e->AddInfo->type = NULL; break;
	}
	 e->AddInfo->n_ch = MAD_NCHANNELS(&header);
	 e->AddInfo->SampleRate = header.samplerate;
	 e->AddInfo->bitrate = header.bitrate;

	 e->AddInfo->err_protection = ((header.flags & MAD_FLAG_PROTECTION) >0);
	 e->AddInfo->copyright = ((header.flags & MAD_FLAG_COPYRIGHT) >0);
	 e->AddInfo->original = ((header.flags & MAD_FLAG_ORIGINAL) >0);

	fseek (fd, 0, SEEK_SET);

//	   bitrate = 0;

	if (xing.flags & XING_FRAMES)
	{
            mad_timer_t timer;

            timer = header.duration;
            mad_timer_multiply (&timer, xing.frames);

            length = mad_timer_count (timer, MAD_UNITS_MILLISECONDS);
/*
  if (xing.flags & XING_BYTES)
  bitrate = xing.bytes * 8 / length;
*/
//				printf ("XING header w/ XING_FRAMES found. length = %d\n", length);

	}
	else
	{
            if (!cfg->lengthcalc)
		length = (size * 8 / (header.bitrate / 1000)); /* est. */
            else
            {
		fseek (fd, 0, SEEK_SET);
		scan_file (fd, &length, NULL);
            }
	}

	 e->time   = length;
        mp3_priv->length = length;
    }

    fclose (fd);
    mp3_priv->size = size;
    mp3_priv->position = 0;
 
    return 1;

}
Пример #14
0
//Get info on file:
//Uso LibMad per calcolare la durata del pezzo perché
//altrimenti dovrei gestire il buffer anche nella seekNextFrame (senza è troppo lenta).
//E' una porcheria ma è più semplice. :)
int MP3MEgetInfo(){
	unsigned long FrameCount = 0;
    int fd = -1;
    int bufferSize = 1024*496;
    u8 *localBuffer;
    long singleDataRed = 0;
	struct mad_stream stream;
	struct mad_header header;
    int timeFromID3 = 0;
    float mediumBitrate = 0.0f;
    int has_xing = 0;
    struct xing xing;
	memset(&xing, 0, sizeof(xing));

    if (!MP3ME_tagRead)
        getMP3METagInfo(MP3ME_fileName, &MP3ME_info);

	mad_stream_init (&stream);
	mad_header_init (&header);

    fd = sceIoOpen(MP3ME_fileName, PSP_O_RDONLY, 0777);
    if (fd < 0)
        return -1;

	long size = sceIoLseek(fd, 0, PSP_SEEK_END);
    sceIoLseek(fd, 0, PSP_SEEK_SET);

    MP3ME_tagsize = ID3v2TagSize(MP3ME_fileName);
	double startPos = MP3ME_tagsize;
	sceIoLseek32(fd, startPos, PSP_SEEK_SET);

    //Check for xing frame:
	unsigned char *xing_buffer;
	xing_buffer = (unsigned char *)malloc(XING_BUFFER_SIZE);
	if (xing_buffer != NULL)
	{
        sceIoRead(fd, xing_buffer, XING_BUFFER_SIZE);
        if(parse_xing(xing_buffer, 0, &xing))
        {
            if (xing.flags & XING_FRAMES && xing.frames){
                has_xing = 1;
                bufferSize = 50 * 1024;
            }
        }
        free(xing_buffer);
        xing_buffer = NULL;
    }

    size -= startPos;

    if (size < bufferSize * 3)
        bufferSize = size;
    localBuffer = (unsigned char *) malloc(sizeof(unsigned char)  * bufferSize);
    unsigned char *buff = localBuffer;

    MP3ME_info.fileType = MP3_TYPE;
    MP3ME_info.defaultCPUClock = MP3ME_defaultCPUClock;
    MP3ME_info.needsME = 1;
	MP3ME_info.fileSize = size;
	MP3ME_filesize = size;
    MP3ME_info.framesDecoded = 0;

    double totalBitrate = 0;
    int i = 0;

	for (i=0; i<3; i++){
        memset(localBuffer, 0, bufferSize);
        singleDataRed = sceIoRead(fd, localBuffer, bufferSize);
    	mad_stream_buffer (&stream, localBuffer, singleDataRed);

        while (1){
    		if (mad_header_decode (&header, &stream) == -1){
                if (stream.buffer == NULL || stream.error == MAD_ERROR_BUFLEN)
                    break;
    			else if (MAD_RECOVERABLE(stream.error)){
    				continue;
    			}else{
    				break;
    			}
    		}
    		//Informazioni solo dal primo frame:
    	    if (FrameCount++ == 0){
    			switch (header.layer) {
    			case MAD_LAYER_I:
    				strcpy(MP3ME_info.layer,"I");
    				break;
    			case MAD_LAYER_II:
    				strcpy(MP3ME_info.layer,"II");
    				break;
    			case MAD_LAYER_III:
    				strcpy(MP3ME_info.layer,"III");
    				break;
    			default:
    				strcpy(MP3ME_info.layer,"unknown");
    				break;
    			}

    			MP3ME_info.kbit = header.bitrate / 1000;
    			MP3ME_info.instantBitrate = header.bitrate;
    			MP3ME_info.hz = header.samplerate;
    			switch (header.mode) {
    			case MAD_MODE_SINGLE_CHANNEL:
    				strcpy(MP3ME_info.mode, "single channel");
    				break;
    			case MAD_MODE_DUAL_CHANNEL:
    				strcpy(MP3ME_info.mode, "dual channel");
    				break;
    			case MAD_MODE_JOINT_STEREO:
    				strcpy(MP3ME_info.mode, "joint (MS/intensity) stereo");
    				break;
    			case MAD_MODE_STEREO:
    				strcpy(MP3ME_info.mode, "normal LR stereo");
    				break;
    			default:
    				strcpy(MP3ME_info.mode, "unknown");
    				break;
    			}

    			switch (header.emphasis) {
    			case MAD_EMPHASIS_NONE:
    				strcpy(MP3ME_info.emphasis,"no");
    				break;
    			case MAD_EMPHASIS_50_15_US:
    				strcpy(MP3ME_info.emphasis,"50/15 us");
    				break;
    			case MAD_EMPHASIS_CCITT_J_17:
    				strcpy(MP3ME_info.emphasis,"CCITT J.17");
    				break;
    			case MAD_EMPHASIS_RESERVED:
    				strcpy(MP3ME_info.emphasis,"reserved(!)");
    				break;
    			default:
    				strcpy(MP3ME_info.emphasis,"unknown");
    				break;
    			}

    			//Check if lenght found in tag info:
                if (MP3ME_info.length > 0){
                    timeFromID3 = 1;
                    break;
                }
                if (has_xing)
                    break;
            }

            totalBitrate += header.bitrate;
		}
        if (size == bufferSize)
            break;
        else if (i==0)
            sceIoLseek(fd, startPos + size/3, PSP_SEEK_SET);
        else if (i==1)
            sceIoLseek(fd, startPos + 2 * size/3, PSP_SEEK_SET);

        if (timeFromID3 || has_xing)
            break;
	}
	mad_header_finish (&header);
	mad_stream_finish (&stream);
    if (buff){
    	free(buff);
        buff = NULL;
    }
    sceIoClose(fd);

    int secs = 0;
    if (has_xing)
    {
        /* modify header.duration since we don't need it anymore */
        mad_timer_multiply(&header.duration, xing.frames);
        secs = mad_timer_count(header.duration, MAD_UNITS_SECONDS);
		MP3ME_info.length = secs;
	}
    else if (!MP3ME_info.length){
		mediumBitrate = totalBitrate / (float)FrameCount;
		secs = size * 8 / mediumBitrate;
        MP3ME_info.length = secs;
    }else{
        secs = MP3ME_info.length;
    }

	//Formatto in stringa la durata totale:
	int h = secs / 3600;
	int m = (secs - h * 3600) / 60;
	int s = secs - h * 3600 - m * 60;
	snprintf(MP3ME_info.strLength, sizeof(MP3ME_info.strLength), "%2.2i:%2.2i:%2.2i", h, m, s);

    return 0;
}
Пример #15
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);
}
int RageSoundReader_MP3::GetNextSourceFrame() const
{
	int iFrame = mad_timer_count( mad->Timer, mad_units(mad->Frame.header.samplerate) );
	iFrame += mad->outpos / this->Channels;
	return iFrame;
}
Пример #17
0
    int64 MadDecoder::getDurationMs(unsigned char* buffer, size_t bufferSize)
    {
        struct mad_stream madStream;
        struct mad_frame  madFrame;
        struct mad_header madHeader;
        mad_timer_t  time = mad_timer_zero;

        bool depadded = false;
        bool vbr = false;
        size_t tagsize = 0;
        size_t consumed = 0;
        size_t numFrames = 0;
        size_t initialBitrate = 0;


        mad_stream_init(&madStream);
        mad_header_init(&madHeader);
        mad_frame_init(&madFrame);

        do  // Read data from the MP3 file 
        {
            int padding = 0;
            size_t leftover = madStream.bufend - madStream.next_frame;
            memcpy(buffer, madStream.this_frame, leftover);

            int bytesRead = fread(buffer + leftover, (size_t)1, bufferSize - leftover, handle_);
            if (bytesRead <= 0) {
                break;
            }
            for (; !depadded && padding < bytesRead && !buffer[padding]; ++padding);
            depadded = true;
            mad_stream_buffer(&madStream, buffer + padding, leftover + bytesRead - padding);

            while (true)   // decode frame headers 
            {
                madStream.error = MAD_ERROR_NONE;
                if (mad_header_decode(&madHeader, &madStream) == -1)
                {
                    if (madStream.error == MAD_ERROR_BUFLEN)     // Normal behaviour; get some more data from the file
                        break;
                    if (MAD_RECOVERABLE(madStream.error) == 0)
                        break;
                    if (madStream.error == MAD_ERROR_LOSTSYNC)
                    {
                        unsigned available = (madStream.bufend - madStream.this_frame);
                        tagsize = getId3TagSize(madStream.this_frame, (size_t)available);

                        if (tagsize)    // It's some ID3 tags, so just skip 
                        {
                            if (tagsize >= available) {
                                _fseeki64(handle_, (int64)(tagsize - available), SEEK_CUR);
                                depadded = false;
                            }
                            mad_stream_skip(&madStream, std::min(tagsize, available));
                        }
                    }
                    continue; // not an audio frame
                }

                mad_timer_add(&time, madHeader.duration);
                consumed += madStream.next_frame - madStream.this_frame;

                if (numFrames == 0) {
                    initialBitrate = madHeader.bitrate;

                    // Get the precise frame count from the XING header if present 
                    madFrame.header = madHeader;
                    if (mad_frame_decode(&madFrame, &madStream) == -1)
                    {
                        if (MAD_RECOVERABLE(madStream.error) == 0) {
                            break;
                        }
                    }
                    if ((numFrames = xingFrames(madStream.anc_ptr, madStream.anc_bitlen)))
                    {
                        mad_timer_multiply(&time, (signed long)numFrames);
                        break;
                    }
                }
                else {
                    vbr |= madHeader.bitrate != initialBitrate;
                }

                // If not VBR, we can time just a few frames then extrapolate (not exact!)
                if (++numFrames == 25 && !vbr)
                {
                    struct stat st;
                    fstat(fileno(handle_), &st);
                    timerMultiply(&time, (double)(st.st_size - tagsize) / consumed);
                    break;
                }
            }   // while(true)
        } while (madStream.error == MAD_ERROR_BUFLEN);

        mad_frame_finish(&madFrame);
        mad_header_finish(&madHeader);
        mad_stream_finish(&madStream);
        rewind(handle_);

        return mad_timer_count(time, MAD_UNITS_MILLISECONDS);
    }
Пример #18
0
enum mad_flow read_header(void *data, struct mad_header const * header)
{
    char long_currenttime_str[14]; /* this *will* fill if you're using 100000+ minute mp3s */
    char long_remaintime_str[14];
    static int frames_played = 0;
    
    buffer *playbuf = (buffer *)data;
    mad_timer_t time_remaining;
    char *ao_time;

    if (stop_playing_file)
    {
        stop_playing_file = 0;
        status = MPG321_STOPPED;
        return MAD_FLOW_STOP;
    }
    
    if(options.opt & MPG321_REMOTE_PLAY)
    {
        enum mad_flow mf;

        /* We might have to stop if the user inputs something */
        if ((mf = remote_get_input_nowait(playbuf)))
            return mf;
    }

    /* Stop playing if -n is used, and we're at the frame specified. */
    if ((playbuf->max_frames != -1) && (frames_played++ > playbuf->max_frames))
    {
        frames_played = 0;
        status = MPG321_STOPPED;
	if(options.opt & MPG321_ENABLE_BUFFER) Decoded_Frames->done = 1;
	//fprintf(stderr,"Total D: %d\n",Decoded_Frames->total_decoded_frames);
        return MAD_FLOW_STOP;
    }

    current_frame++;

    mad_timer_add(&current_time, header->duration);

    if(options.opt & MPG321_USE_SCROBBLER && scrobbler_time > 0 && scrobbler_time < current_time.seconds)
    {
	    scrobbler_time = -1;
	    scrobbler_report();
    }

    if(options.opt & (MPG321_VERBOSE_PLAY | MPG321_REMOTE_PLAY))
    {
        mad_timer_string(current_time, long_currenttime_str, "%.2u:%.2u.%.2u", MAD_UNITS_MINUTES,
                            MAD_UNITS_CENTISECONDS, 0);

        if (mad_timer_compare(playbuf->duration, mad_timer_zero) == 0)
            time_remaining = current_time;
        else
            time_remaining = playbuf->duration;


        mad_timer_negate(&current_time);

        mad_timer_add(&time_remaining, current_time);
        mad_timer_negate(&current_time);

        mad_timer_string(time_remaining, long_remaintime_str, "%.2u:%.2u.%.2u", MAD_UNITS_MINUTES,
                            MAD_UNITS_CENTISECONDS, 0);
    }
                        
    /* update cached table of frames & times */
    if (current_frame <= playbuf->num_frames) /* we only allocate enough for our estimate. */
    {
        playbuf->frames[current_frame] = playbuf->frames[current_frame-1] + (header->bitrate / 8 / 1000)
            * mad_timer_count(header->duration, MAD_UNITS_MILLISECONDS);
        playbuf->times[current_frame] = current_time;
    }
    
    if (file_change)
    {
        file_change = 0;
        if (options.opt & MPG321_REMOTE_PLAY)
        {
            printf("@S %s %d %d %s %d %ld %d %d %d %d %ld %d\n",versionstring(header->flags), header->layer, header->samplerate,
                modestringucase(header->mode), header->mode_extension, 
                (header->bitrate / 8 / 100) * mad_timer_count(header->duration, MAD_UNITS_CENTISECONDS),
                MAD_NCHANNELS(header), header->flags & MAD_FLAG_COPYRIGHT ? 1 : 0, 
                header->flags & MAD_FLAG_PROTECTION ? 1 : 0, header->emphasis,
                header->bitrate/1000, header->mode_extension);
        }    

        else if (options.opt & MPG321_VERBOSE_PLAY)/*zip it good*/
        {
            fprintf(stderr, "MPEG %s, Layer: %s, Freq: %d, mode: %s, modext: %d, BPF : %ld\n"
                    "Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n"
                    "Bitrate: %ld Kbits/s, Extension value: %d\n"
                    "Audio: 1:1 conversion, rate: %d, encoding: signed 16 bit, channels: %d\n",
                    versionstring(header->flags),layerstring(header->layer), header->samplerate, modestringucase(header->mode), header->mode_extension, 
                    (header->bitrate / 100) * mad_timer_count(header->duration, MAD_UNITS_CENTISECONDS),
                    MAD_NCHANNELS(header), header->flags & MAD_FLAG_COPYRIGHT ? "Yes" : "No",
                    header->flags & MAD_FLAG_ORIGINAL ? "Yes" : "No", header->flags & MAD_FLAG_PROTECTION ? "Yes" : "No",
                    header->emphasis, header->bitrate/1000, header->mode_extension,
                    header->samplerate, MAD_NCHANNELS(header));
        }

        else if (!(options.opt & MPG321_QUIET_PLAY))/*I love Joey*/
        {
            fprintf(stderr, "MPEG %s layer %s, %ld kbit/s, %d Hz %s\n",
                versionstring(header->flags),layerstring(header->layer), header->bitrate/1000, header->samplerate, modestring(header->mode));
        }
    }
    
    if (status == MPG321_SEEKING && options.seek)
    {
        if (!--options.seek)
            status = MPG321_PLAYING;

        return MAD_FLOW_IGNORE;
    }
    else
    {
        status = MPG321_PLAYING;
    }

    if(!(options.opt & MPG321_ENABLE_BUFFER))
    {
	    if(count > 0)
	    {
		    count++;
		    if(count > 40)
		    {
			    if(!(options.opt & MPG321_VERBOSE_PLAY))
				    fprintf(stderr,"                \r");
			    count = -1;
			    fflush(stderr);
		    }
	    }
    }

    if(options.opt & MPG321_ENABLE_BUFFER)
    {
	    ao_time = (Output_Queue+mad_decoder_position)->time;
	    (Output_Queue+mad_decoder_position)->num_frames = playbuf->num_frames - current_frame;
	    if(Decoded_Frames->is_file) (Output_Queue+mad_decoder_position)->seconds = time_remaining.seconds;
    }

    if (options.opt & MPG321_VERBOSE_PLAY)
    {
        if (!options.skip_printing_frames 
            || (options.skip_printing_frames && !(current_frame % options.skip_printing_frames)))
   
	      	if(count > 0)
		{
/*			if(options.opt & MPG321_ENABLE_BUFFER)
			{	
				sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s], \r", current_frame,
					playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str);
				//sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s], \r", current_frame,
				//	playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str);
				//sprintf(ao_time, "Volume: %d%%  Frame# %5lu [%5lu], Time: %s [%s], \r",volume, current_frame,
				//	playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str);
			}else*/
			{
				fprintf(stderr, "Volume: %d%%  Frame# %5lu [%5lu], Time: %s [%s], \r",volume, current_frame,
					playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str);
			}
		}
		else if(count < 0)
		{
			if(options.opt & MPG321_ENABLE_BUFFER)
			{
//				sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s],                     \r", current_frame,
				sprintf(ao_time, "Frame# %5lu [%5lu], Time: %s [%s],                 \r", current_frame,
					playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str);
			}
			else
			{
				
				fprintf(stderr, "Frame# %5lu [%5lu], Time: %s [%s],                      \r", current_frame,
					playbuf->num_frames > 0 ? playbuf->num_frames - current_frame : 0, long_currenttime_str, long_remaintime_str);
			}
		}
    }
    else if (options.opt & MPG321_REMOTE_PLAY)
    {
    
	    if (!options.skip_printing_frames 
            || (options.skip_printing_frames && !(current_frame % options.skip_printing_frames)))
	    {
		    if(options.opt & MPG321_ENABLE_BUFFER)
		    {
			    sprintf(ao_time,"@F %ld %ld %.2f %.2f\n", current_frame, playbuf->num_frames - current_frame,
				    	    ((double)mad_timer_count(current_time, MAD_UNITS_CENTISECONDS)/100.0),
			    		    ((double)mad_timer_count(time_remaining, MAD_UNITS_CENTISECONDS)/100.0));
		    }
		    else
		    {

			    fprintf(stderr,"@F %ld %ld %.2f %.2f\n", current_frame, playbuf->num_frames - current_frame,
				    	    ((double)mad_timer_count(current_time, MAD_UNITS_CENTISECONDS)/100.0),
			    		    ((double)mad_timer_count(time_remaining, MAD_UNITS_CENTISECONDS)/100.0));
		    }
	    }
    }
    return MAD_FLOW_CONTINUE;
}        
Пример #19
0
static inline float
mp3_frame_duration(const struct mad_frame *frame)
{
	return mad_timer_count(frame->header.duration,
			       MAD_UNITS_MILLISECONDS) / 1000.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;
	}
}
Пример #21
0
static bool
mp3_decode_first_frame(struct mp3_data *data, struct tag **tag,
		       struct replay_gain_info **replay_gain_info_r)
{
	struct xing xing;
	struct lame lame;
	struct mad_bitptr ptr;
	int bitlen;
	enum mp3_action ret;

	/* stfu gcc */
	memset(&xing, 0, sizeof(struct xing));
	xing.flags = 0;

	while (true) {
		do {
			ret = decode_next_frame_header(data, tag,
						       replay_gain_info_r);
		} while (ret == DECODE_CONT);
		if (ret == DECODE_BREAK)
			return false;
		if (ret == DECODE_SKIP) continue;

		do {
			ret = decodeNextFrame(data);
		} while (ret == DECODE_CONT);
		if (ret == DECODE_BREAK)
			return false;
		if (ret == DECODE_OK) break;
	}

	ptr = data->stream.anc_ptr;
	bitlen = data->stream.anc_bitlen;

	mp3_filesize_to_song_length(data);

	/*
	 * if an xing tag exists, use that!
	 */
	if (parse_xing(&xing, &ptr, &bitlen)) {
		data->found_xing = true;
		data->mute_frame = MUTEFRAME_SKIP;

		if ((xing.flags & XING_FRAMES) && xing.frames) {
			mad_timer_t duration = data->frame.header.duration;
			mad_timer_multiply(&duration, xing.frames);
			data->total_time = ((float)mad_timer_count(duration, MAD_UNITS_MILLISECONDS)) / 1000;
			data->max_frames = xing.frames;
		}

		if (parse_lame(&lame, &ptr, &bitlen)) {
			if (gapless_playback &&
			    data->input_stream->seekable) {
				data->drop_start_samples = lame.encoder_delay +
				                           DECODERDELAY;
				data->drop_end_samples = lame.encoder_padding;
			}

			/* Album gain isn't currently used.  See comment in
			 * parse_lame() for details. -- jat */
			if (replay_gain_info_r && !*replay_gain_info_r &&
			    lame.track_gain) {
				*replay_gain_info_r = replay_gain_info_new();
				(*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
				(*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
			}
		}
	} 

	if (!data->max_frames)
		return false;

	if (data->max_frames > 8 * 1024 * 1024) {
		g_warning("mp3 file header indicates too many frames: %lu\n",
			  data->max_frames);
		return false;
	}

	data->frame_offsets = g_malloc(sizeof(long) * data->max_frames);
	data->times = g_malloc(sizeof(mad_timer_t) * data->max_frames);

	return true;
}
Пример #22
0
const int mpgDecoder::getTime( )
{
#ifdef HAVE_MAD
    return mad_timer_count( *endPositionTimer, MAD_UNITS_SECONDS);
#endif
}
Пример #23
0
const float mpgDecoder::getPosition_Samples( )
{
#ifdef HAVE_MAD
    return getTime()-mad_timer_count( *currentPositionTimer, (mad_units)sampleRate);
#endif
}
Пример #24
0
const float mpgDecoder::getTotal_Samples( )
{
#ifdef HAVE_MAD
    return mad_timer_count( *endPositionTimer, (mad_units)sampleRate);
#endif
}
Пример #25
0
SoundSource::OpenResult SoundSourceMp3::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) {
    DEBUG_ASSERT(!hasValidChannelCount());
    DEBUG_ASSERT(!hasValidSamplingRate());

    DEBUG_ASSERT(!m_file.isOpen());
    if (!m_file.open(QIODevice::ReadOnly)) {
        qWarning() << "Failed to open file:" << m_file.fileName();
        return OpenResult::FAILED;
    }

    // Get a pointer to the file using memory mapped IO
    m_fileSize = m_file.size();
    m_pFileData = m_file.map(0, m_fileSize);
    // NOTE(uklotzde): If the file disappears unexpectedly while mapped
    // a SIGBUS error might occur that is not handled and will terminate
    // Mixxx immediately. This behavior is documented in the manpage of
    // mmap(). It has already appeared due to hardware errors and is
    // described in the following bug report:
    // https://bugs.launchpad.net/mixxx/+bug/1452005

    // Transfer it to the mad stream-buffer:
    mad_stream_options(&m_madStream, MAD_OPTION_IGNORECRC);
    mad_stream_buffer(&m_madStream, m_pFileData, m_fileSize);
    DEBUG_ASSERT(m_pFileData == m_madStream.this_frame);

    DEBUG_ASSERT(m_seekFrameList.empty());
    m_avgSeekFrameCount = 0;
    m_curFrameIndex = getMinFrameIndex();
    int headerPerSamplingRate[kSamplingRateCount];
    for (int i = 0; i < kSamplingRateCount; ++i) {
        headerPerSamplingRate[i] = 0;
    }

    // Decode all the headers and calculate audio properties

    unsigned long sumBitrate = 0;

    mad_header madHeader;
    mad_header_init(&madHeader);

    SINT maxChannelCount = getChannelCount();
    do {
        if (!decodeFrameHeader(&madHeader, &m_madStream, true)) {
            if (isStreamValid(m_madStream)) {
                // Skip frame
                continue;
            } else {
                // Abort decoding
                break;
            }
        }

        // Grab data from madHeader
        const unsigned int madSampleRate = madHeader.samplerate;

        // TODO(XXX): Replace DEBUG_ASSERT with static_assert
        // MAD must not change its enum values!
        DEBUG_ASSERT(MAD_UNITS_8000_HZ == 8000);
        const mad_units madUnits = static_cast<mad_units>(madSampleRate);

        const long madFrameLength = mad_timer_count(madHeader.duration, madUnits);
        if (0 >= madFrameLength) {
            qWarning() << "Skipping MP3 frame with invalid length"
                    << madFrameLength
                    << "in:" << m_file.fileName();
            // Skip frame
            continue;
        }

        const SINT madChannelCount = MAD_NCHANNELS(&madHeader);
        if (isValidChannelCount(maxChannelCount) && (madChannelCount != maxChannelCount)) {
            qWarning() << "Differing number of channels"
                    << madChannelCount << "<>" << maxChannelCount
                    << "in some MP3 frame headers:"
                    << m_file.fileName();
        }
        maxChannelCount = math_max(madChannelCount, maxChannelCount);

        const int samplingRateIndex = getIndexBySamplingRate(madSampleRate);
        if (samplingRateIndex >= kSamplingRateCount) {
            qWarning() << "Invalid sample rate:" << m_file.fileName()
                    << madSampleRate;
            // Abort
            mad_header_finish(&madHeader);
            return OpenResult::FAILED;
        }
        // Count valid frames separated by its sampling rate
        headerPerSamplingRate[samplingRateIndex]++;

        addSeekFrame(m_curFrameIndex, m_madStream.this_frame);

        // Accumulate data from the header
        sumBitrate += madHeader.bitrate;

        // Update current stream position
        m_curFrameIndex += madFrameLength;

        DEBUG_ASSERT(m_madStream.this_frame);
        DEBUG_ASSERT(0 <= (m_madStream.this_frame - m_pFileData));
    } while (quint64(m_madStream.this_frame - m_pFileData) < m_fileSize);

    mad_header_finish(&madHeader);

    if (MAD_ERROR_NONE != m_madStream.error) {
        // Unreachable code for recoverable errors
        DEBUG_ASSERT(!MAD_RECOVERABLE(m_madStream.error));
        if (MAD_ERROR_BUFLEN != m_madStream.error) {
            qWarning() << "Unrecoverable MP3 header error:"
                    << mad_stream_errorstr(&m_madStream);
            // Abort
            return OpenResult::FAILED;
        }
    }

    if (m_seekFrameList.empty()) {
        // This is not a working MP3 file.
        qWarning() << "SSMP3: This is not a working MP3 file:"
                << m_file.fileName();
        // Abort
        return OpenResult::FAILED;
    }

    int mostCommonSamplingRateIndex = kSamplingRateCount; // invalid
    int mostCommonSamplingRateCount = 0;
    int differentRates = 0;
    for (int i = 0; i < kSamplingRateCount; ++i) {
        // Find most common sampling rate
        if (mostCommonSamplingRateCount < headerPerSamplingRate[i]) {
            mostCommonSamplingRateCount = headerPerSamplingRate[i];
            mostCommonSamplingRateIndex = i;
            differentRates++;
        }
    }

    if (differentRates > 1) {
        qWarning() << "Differing sampling rate in some headers:"
                   << m_file.fileName();
        for (int i = 0; i < kSamplingRateCount; ++i) {
            if (0 < headerPerSamplingRate[i]) {
                qWarning() << headerPerSamplingRate[i] << "MP3 headers with sampling rate" << getSamplingRateByIndex(i);
            }
        }

        qWarning() << "MP3 files with varying sample rate are not supported!";
        qWarning() << "Since this happens most likely due to a corrupt file";
        qWarning() << "Mixxx tries to plays it with the most common sample rate for this file";
    }

    if (mostCommonSamplingRateIndex < kSamplingRateCount) {
        setSamplingRate(getSamplingRateByIndex(mostCommonSamplingRateIndex));
    } else {
        qWarning() << "No single valid sampling rate in header";
        // Abort
        return OpenResult::FAILED;
    }

    // Initialize the AudioSource
    setChannelCount(maxChannelCount);
    setFrameCount(m_curFrameIndex);

    // Calculate average values
    m_avgSeekFrameCount = getFrameCount() / m_seekFrameList.size();
    const unsigned long avgBitrate = sumBitrate / m_seekFrameList.size();
    setBitrate(avgBitrate / 1000);

    // Terminate m_seekFrameList
    addSeekFrame(m_curFrameIndex, 0);

    // Reset positions
    m_curFrameIndex = getMinFrameIndex();

    // Restart decoding at the beginning of the audio stream
    m_curFrameIndex = restartDecoding(m_seekFrameList.front());
    if (m_curFrameIndex != m_seekFrameList.front().frameIndex) {
        qWarning() << "Failed to start decoding:" << m_file.fileName();
        // Abort
        return OpenResult::FAILED;
    }

    return OpenResult::SUCCEEDED;
}
Пример #26
0
const float mpgDecoder::getTotalFrames( )
{
#ifdef HAVE_MAD
    return mad_timer_count( *endPositionTimer, MAD_UNITS_25_FPS);
#endif
}
Пример #27
0
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);

			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK;
			xmms_xform_metadata_set_int (xform, metakey, lame->radio_gain);
			*/
		}

	} else {
		gint filesize;

		metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE;
		xmms_xform_metadata_set_int (xform, metakey, frame.header.bitrate);

		metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION;
		if (!xmms_xform_metadata_get_int (xform, metakey, &filesize)) {
			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE;

			if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) {
				gint32 val;

				val = (gint32) (filesize * (gdouble) 8000.0 / frame.header.bitrate);

				metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION;
				xmms_xform_metadata_set_int (xform, metakey, val);
			}
		}
	}

	/* seeking needs bitrate */
	data->bitrate = frame.header.bitrate;

	if (xmms_id3v1_get_tags (xform) < 0) {
		mad_stream_finish (&data->stream);
		mad_frame_finish (&data->frame);
		mad_synth_finish (&data->synth);
		if (data->xing) {
			xmms_xing_free (data->xing);
		}
		return FALSE;
	}

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_S16,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->samplerate,
	                             XMMS_STREAM_TYPE_END);

	mad_frame_finish (&frame);
	mad_stream_finish (&stream);

	return TRUE;
}
Пример #28
0
const float mpgDecoder::getPlayedFrames( )
{
#ifdef HAVE_MAD
    return mad_timer_count( *currentPositionTimer, MAD_UNITS_25_FPS);
#endif
}
Пример #29
0
/*
 * NAME:	timer->string()
 * DESCRIPTION:	write a string representation of a timer using a template
 */
void mad_timer_string(mad_timer_t timer,
		      char *dest, char const *format, enum mad_units units,
		      enum mad_units fracunits, u32 subparts)
{
  u32 hours, minutes, seconds, sub;
  u32 frac;

  timer = mad_timer_abs(timer);

  seconds = timer.seconds;
  frac = sub = 0;

  switch (fracunits) {
  case MAD_UNITS_HOURS:
  case MAD_UNITS_MINUTES:
  case MAD_UNITS_SECONDS:
    break;

  case MAD_UNITS_DECISECONDS:
  case MAD_UNITS_CENTISECONDS:
  case MAD_UNITS_MILLISECONDS:

  case MAD_UNITS_8000_HZ:
  case MAD_UNITS_11025_HZ:
  case MAD_UNITS_12000_HZ:
  case MAD_UNITS_16000_HZ:
  case MAD_UNITS_22050_HZ:
  case MAD_UNITS_24000_HZ:
  case MAD_UNITS_32000_HZ:
  case MAD_UNITS_44100_HZ:
  case MAD_UNITS_48000_HZ:

  case MAD_UNITS_24_FPS:
  case MAD_UNITS_25_FPS:
  case MAD_UNITS_30_FPS:
  case MAD_UNITS_48_FPS:
  case MAD_UNITS_50_FPS:
  case MAD_UNITS_60_FPS:
  case MAD_UNITS_75_FPS:
    {
      u32 denom;

      denom = MAD_TIMER_RESOLUTION / fracunits;

      frac = timer.fraction / denom;
      sub  = scale_rational(timer.fraction % denom, denom, subparts);
    }
    break;

  case MAD_UNITS_23_976_FPS:
  case MAD_UNITS_24_975_FPS:
  case MAD_UNITS_29_97_FPS:
  case MAD_UNITS_47_952_FPS:
  case MAD_UNITS_49_95_FPS:
  case MAD_UNITS_59_94_FPS:
    /* drop-frame encoding */
    /* N.B. this is only well-defined for MAD_UNITS_29_97_FPS */
    {
      u32 frame, cycle, d, m;

      frame = mad_timer_count(timer, fracunits);

      cycle = -fracunits * 60 * 10 - (10 - 1) * 2;

      d = frame / cycle;
      m = frame % cycle;
      frame += (10 - 1) * 2 * d;
      if (m > 2)
	frame += 2 * ((m - 2) / (cycle / 10));

      frac    = frame % -fracunits;
      seconds = frame / -fracunits;
    }
    break;
  }

  switch (units) {
  case MAD_UNITS_HOURS:
    minutes = seconds / 60;
    hours   = minutes / 60;

    sprintf(dest, format,
	    hours,
	    (u32) (minutes % 60),
	    (u32) (seconds % 60),
	    frac, sub);
    break;

  case MAD_UNITS_MINUTES:
    minutes = seconds / 60;

    sprintf(dest, format,
	    minutes,
	    (u32) (seconds % 60),
	    frac, sub);
    break;

  case MAD_UNITS_SECONDS:
    sprintf(dest, format,
	    seconds,
	    frac, sub);
    break;

  case MAD_UNITS_23_976_FPS:
  case MAD_UNITS_24_975_FPS:
  case MAD_UNITS_29_97_FPS:
  case MAD_UNITS_47_952_FPS:
  case MAD_UNITS_49_95_FPS:
  case MAD_UNITS_59_94_FPS:
    if (fracunits < 0) {
      /* not yet implemented */
      sub = 0;
    }

    /* fall through */

  case MAD_UNITS_DECISECONDS:
  case MAD_UNITS_CENTISECONDS:
  case MAD_UNITS_MILLISECONDS:

  case MAD_UNITS_8000_HZ:
  case MAD_UNITS_11025_HZ:
  case MAD_UNITS_12000_HZ:
  case MAD_UNITS_16000_HZ:
  case MAD_UNITS_22050_HZ:
  case MAD_UNITS_24000_HZ:
  case MAD_UNITS_32000_HZ:
  case MAD_UNITS_44100_HZ:
  case MAD_UNITS_48000_HZ:

  case MAD_UNITS_24_FPS:
  case MAD_UNITS_25_FPS:
  case MAD_UNITS_30_FPS:
  case MAD_UNITS_48_FPS:
  case MAD_UNITS_50_FPS:
  case MAD_UNITS_60_FPS:
  case MAD_UNITS_75_FPS:
    sprintf(dest, format, mad_timer_count(timer, units), sub);
    break;
  }
}
Пример #30
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;
}