예제 #1
0
mad_flow MADStream::ms_error(void* user, mad_stream* stream, mad_frame* frame) {
    RW_UNUSED(user);
    RW_UNUSED(frame);

    std::cerr << "libmad error: " << mad_stream_errorstr(stream) << std::endl;
    return MAD_FLOW_BREAK;
}
예제 #2
0
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;
}
예제 #3
0
/*****************************************************************************
 * DoWork: decode an MPEG audio frame.
 *****************************************************************************/
static void DoWork( filter_t * p_filter,
                    block_t * p_in_buf, block_t * p_out_buf )
{
    filter_sys_t *p_sys = p_filter->p_sys;

    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(vlc_fixed_t) *
                               aout_FormatNbChannels( &p_filter->fmt_out.audio );

    /* Do the actual decoding now. */
    mad_stream_buffer( &p_sys->mad_stream, p_in_buf->p_buffer,
                       p_in_buf->i_buffer );
    if ( mad_frame_decode( &p_sys->mad_frame, &p_sys->mad_stream ) == -1 )
    {
        msg_Dbg( p_filter, "libmad error: %s",
                  mad_stream_errorstr( &p_sys->mad_stream ) );
        p_sys->i_reject_count = 3;
    }
    else if( p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        p_sys->i_reject_count = 3;
    }

    if( p_sys->i_reject_count > 0 )
    {
        memset( p_out_buf->p_buffer, 0, p_out_buf->i_buffer );
        p_sys->i_reject_count--;
        return;
    }


    mad_synth_frame( &p_sys->mad_synth, &p_sys->mad_frame );

    struct mad_pcm * p_pcm = &p_sys->mad_synth.pcm;
    unsigned int i_samples = p_pcm->length;
    mad_fixed_t const * p_left = p_pcm->samples[0];
    mad_fixed_t const * p_right = p_pcm->samples[1];
    mad_fixed_t * p_samples = (mad_fixed_t *)p_out_buf->p_buffer;

    assert( i_samples == p_out_buf->i_nb_samples );
    /* Interleave and keep buffers in mad_fixed_t format */
    if ( p_pcm->channels == 2 )
    {
        while ( i_samples-- )
        {
            *p_samples++ = *p_left++;
            *p_samples++ = *p_right++;
        }
    }
    else
    {
        assert( p_pcm->channels == 1 );
        memcpy( p_samples, p_left, i_samples * sizeof(mad_fixed_t) );
    }
}
예제 #4
0
파일: minimad.c 프로젝트: charlierobson/M6
static enum mad_flow error(void *data, struct mad_stream *stream, struct mad_frame *frame)
{
	struct buffer *buffer = (struct buffer *)data;

	fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n",
		stream->error, mad_stream_errorstr(stream),
		stream->this_frame - buffer->start);

	/* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */

	return MAD_FLOW_CONTINUE;
}
예제 #5
0
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;
}
예제 #6
0
파일: IoMP3Decoder.c 프로젝트: Akiyah/io
static enum mad_flow IoMP3Decoder_errorCallback(void *data,
									   struct mad_stream *stream,
									   struct mad_frame *frame)
{
	//IoMP3Decoder *self = data;

	 fprintf(stderr, "lbmad error %i (%s)\n", stream->error, mad_stream_errorstr(stream));

	 /*
	IoState_error_(IOSTATE, 0x0, "MP3Decoder %s", mad_stream_errorstr(stream));
	
	DATA(self)->isRunning = 0;
	return MAD_FLOW_BREAK;
	*/
	return MAD_FLOW_CONTINUE;
}
예제 #7
0
파일: wrapper.c 프로젝트: webcast/libmad.js
/* 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;
}
예제 #8
0
파일: mad_plugin.c 프로젝트: azuwis/mpd
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;
}
예제 #9
0
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);
		_samples += 32 * MAD_NSBSAMPLES(&_frame.header);
		break;
	}

	if (_stream.error != MAD_ERROR_NONE)
		_state = MP3_STATE_EOS;
}
예제 #10
0
/*	mp3 playback callback
 */
static WaitressCbReturn_t BarPlayerMp3Cb (void *ptr, size_t size,
		void *stream) {
	const char *data = ptr;
	struct audioPlayer *player = stream;
	size_t i;

	QUIT_PAUSE_CHECK;

	if (!BarPlayerBufferFill (player, data, size)) {
		return WAITRESS_CB_RET_ERR;
	}

	/* some "prebuffering" */
	if (player->mode < PLAYER_RECV_DATA &&
			player->bufferFilled < BAR_PLAYER_BUFSIZE / 2) {
		return WAITRESS_CB_RET_OK;
	}

	mad_stream_buffer (&player->mp3Stream, player->buffer,
			player->bufferFilled);
	player->mp3Stream.error = 0;
	do {
		/* channels * max samples, found in mad.h */
		signed short int madDecoded[2*1152], *madPtr = madDecoded;

		if (mad_frame_decode (&player->mp3Frame, &player->mp3Stream) != 0) {
			if (player->mp3Stream.error != MAD_ERROR_BUFLEN) {
				BarUiMsg (player->settings, MSG_ERR,
						"mp3 decoding error: %s\n",
						mad_stream_errorstr (&player->mp3Stream));
				return WAITRESS_CB_RET_ERR;
			} else {
				/* rebuffering required => exit loop */
				break;
			}
		}
		mad_synth_frame (&player->mp3Synth, &player->mp3Frame);
		for (i = 0; i < player->mp3Synth.pcm.length; i++) {
			/* left channel */
			*(madPtr++) = applyReplayGain (BarPlayerMadToShort (
					player->mp3Synth.pcm.samples[0][i]), player->scale);

			/* right channel */
			*(madPtr++) = applyReplayGain (BarPlayerMadToShort (
					player->mp3Synth.pcm.samples[1][i]), player->scale);
		}
		if (player->mode < PLAYER_AUDIO_INITIALIZED) {
			ao_sample_format format;
			int audioOutDriver;

			player->channels = player->mp3Synth.pcm.channels;
			player->samplerate = player->mp3Synth.pcm.samplerate;
			audioOutDriver = ao_default_driver_id();
			memset (&format, 0, sizeof (format));
			format.bits = 16;
			format.channels = player->channels;
			format.rate = player->samplerate;
			format.byte_format = AO_FMT_NATIVE;
			if ((player->audioOutDevice = ao_open_live (audioOutDriver,
					&format, NULL)) == NULL) {
				player->aoError = 1;
				BarUiMsg (player->settings, MSG_ERR,
						"Cannot open audio device\n");
				return WAITRESS_CB_RET_ERR;
			}

			/* calc song length using the framerate of the first decoded frame */
			player->songDuration = (unsigned long long int) player->waith.request.contentLength /
					((unsigned long long int) player->mp3Frame.header.bitrate /
					(unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR / 8LL);

			/* must be > PLAYER_SAMPLESIZE_INITIALIZED, otherwise time won't
			 * be visible to user (ugly, but mp3 decoding != aac decoding) */
			player->mode = PLAYER_RECV_DATA;
		}
		/* samples * length * channels */
		ao_play (player->audioOutDevice, (char *) madDecoded,
				player->mp3Synth.pcm.length * 2 * 2);

		/* avoid division by 0 */
		if (player->mode == PLAYER_RECV_DATA) {
			/* same calculation as in aac player; don't need to divide by
			 * channels, length is number of samples for _one_ channel */
			player->songPlayed += (unsigned long long int) player->mp3Synth.pcm.length *
					(unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR /
					(unsigned long long int) player->samplerate;
		}

		QUIT_PAUSE_CHECK;
	} while (player->mp3Stream.error != MAD_ERROR_BUFLEN);

	player->bufferRead += player->mp3Stream.next_frame - player->buffer;

	BarPlayerBufferMove (player);

	return WAITRESS_CB_RET_OK;
}
예제 #11
0
static gavl_source_status_t decode_frame_mad(bgav_stream_t * s)
  {
  mad_priv_t * priv;
  int i, j;
  gavl_source_status_t st;
  int got_frame;
  int flush = 0;
  
  priv = s->decoder_priv;
  
  if(priv->eof)
    return GAVL_SOURCE_EOF;

  while(1)
    {
    st = get_data(s);

    switch(st)
      {
      case GAVL_SOURCE_AGAIN:
        return st;
        break;
      case GAVL_SOURCE_EOF:
        flush = 1;
        break;
      case GAVL_SOURCE_OK:
        break;
      }
  
    got_frame = 1;
  
    mad_stream_buffer(&priv->stream, priv->buf.buffer,
                      priv->buf.size + flush * MAD_BUFFER_GUARD);

    if(priv->do_init)
      {
      get_format(s);
      priv->do_init = 0;
      }
    if(mad_frame_decode(&priv->frame, &priv->stream) == -1)
      {
      got_frame = 0;
      if(priv->stream.error != MAD_ERROR_BUFLEN)
        {
        /* This is often a spurious error, which ALWAYS occurs for ripped radio stations */
        if(priv->stream.error != MAD_ERROR_BADDATAPTR)
          bgav_log(s->opt, BGAV_LOG_ERROR, LOG_DOMAIN, "Decode failed %s\n",
                   mad_stream_errorstr(&priv->stream));
        break;
        }
      }
    else
      break;

    if(!got_frame && flush)
      return GAVL_SOURCE_EOF;
    }
  
  if(got_frame)
    {
    // fprintf(stderr, "Decodes %ld bytes\n", priv->stream.next_frame - priv->stream.buffer);
    
    mad_synth_frame(&priv->synth, &priv->frame);

    for(i = 0; i < s->data.audio.format.num_channels; i++)
      {
      for(j = 0; j < s->data.audio.format.samples_per_frame; j++)
        {
        if (priv->synth.pcm.samples[i][j] >= MAD_F_ONE)
          priv->synth.pcm.samples[i][j] = MAD_F_ONE - 1;
        else if (priv->synth.pcm.samples[i][j] < -MAD_F_ONE)
          priv->synth.pcm.samples[i][j] = -MAD_F_ONE;
      
        priv->audio_frame->channels.f[i][j] =
          (float)(priv->synth.pcm.samples[i][j]) /
          (float)MAD_F_ONE;
        }
      }
    
    priv->audio_frame->valid_samples   = s->data.audio.format.samples_per_frame;
    }
  else
    gavl_audio_frame_mute(priv->audio_frame, &s->data.audio.format);
  
  if(flush && priv->last_duration &&
     (priv->last_duration < priv->audio_frame->valid_samples))
    priv->audio_frame->valid_samples = priv->last_duration;
  
  gavl_audio_frame_copy_ptrs(&s->data.audio.format,
                             s->data.audio.frame, priv->audio_frame);
#if 0
  fprintf(stderr, "Done decode %ld %ld\n",
          priv->stream.this_frame - priv->stream.buffer,
          priv->stream.next_frame - priv->stream.this_frame);
#endif

  s->flags |= STREAM_HAVE_FRAME;
  
  bgav_bytebuffer_remove(&priv->buf,
                         priv->stream.next_frame - priv->stream.buffer);

  if(flush)
    priv->eof = 1;

  return GAVL_SOURCE_OK;
  }
예제 #12
0
/*****************************************************************************
 * DoWork: decode an MPEG audio frame.
 *****************************************************************************/
static void DoWork( filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    filter_sys_t *p_sys = p_filter->p_sys;

    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(vlc_fixed_t) *
                               aout_FormatNbChannels( &p_filter->fmt_out.audio );

    /* Do the actual decoding now. */
    mad_stream_buffer( &p_sys->mad_stream, p_in_buf->p_buffer,
                       p_in_buf->i_buffer );
    if ( mad_frame_decode( &p_sys->mad_frame, &p_sys->mad_stream ) == -1 )
    {
        msg_Dbg( p_filter, "libmad error: %s",
                  mad_stream_errorstr( &p_sys->mad_stream ) );
        p_sys->i_reject_count = 3;
    }
    else if( p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        p_sys->i_reject_count = 3;
    }

    if( p_sys->i_reject_count > 0 )
    {
        if( p_filter->fmt_out.audio.i_format == VLC_CODEC_FL32 )
        {
            int i;
            int i_size = p_out_buf->i_buffer / sizeof(float);

            float * a = (float *)p_out_buf->p_buffer;
            for ( i = 0 ; i < i_size ; i++ )
                *a++ = 0.0;
        }
        else
        {
            memset( p_out_buf->p_buffer, 0, p_out_buf->i_buffer );
        }
        p_sys->i_reject_count--;
        return;
    }


    mad_synth_frame( &p_sys->mad_synth, &p_sys->mad_frame );

    struct mad_pcm * p_pcm = &p_sys->mad_synth.pcm;
    unsigned int i_samples = p_pcm->length;
    mad_fixed_t const * p_left = p_pcm->samples[0];
    mad_fixed_t const * p_right = p_pcm->samples[1];

    assert( i_samples == p_out_buf->i_nb_samples );
    if ( p_filter->fmt_out.audio.i_format == VLC_CODEC_FI32 )
    {
        /* Interleave and keep buffers in mad_fixed_t format */
        mad_fixed_t * p_samples = (mad_fixed_t *)p_out_buf->p_buffer;

        if ( p_pcm->channels == 2 )
        {
            while ( i_samples-- )
            {
                *p_samples++ = *p_left++;
                *p_samples++ = *p_right++;
            }
        }
        else
        {
            assert( p_pcm->channels == 1 );
            vlc_memcpy( p_samples, p_left, i_samples * sizeof(mad_fixed_t) );
        }
    }
    else
    {
        /* float32 */
        float * p_samples = (float *)p_out_buf->p_buffer;
        const float f_temp = (float)FIXED32_ONE;

        if ( p_pcm->channels == 2 )
        {
            while ( i_samples-- )
            {
                *p_samples++ = (float)*p_left++ / f_temp;
                *p_samples++ = (float)*p_right++ / f_temp;
            }
        }
        else
        {
            assert( p_pcm->channels == 1 );
            while ( i_samples-- )
            {
                *p_samples++ = (float)*p_left++ / f_temp;
            }
        }
    }
}
예제 #13
0
파일: mp3_play.c 프로젝트: GCrean/wmamp
/*
 *  this is a really simple bash at an EQ graph
 *  just a quick hack 
 */
enum mad_flow
filter(void *closure, struct mad_stream const *stream,
           struct mad_frame *frame)
{
    int channel, slice, band;
    unsigned long avg = 0;
    int sample;

    /* JDH - if we're not showing the song that's playing don't show the equalizer either */
    if (np_check_state() == 0) {
        return MAD_FLOW_CONTINUE;
    }

    for (channel = 0; channel < 2; channel++) {
        for (band = 1; band < 31; band++) {
            avg = 0;
            for (slice = 0; slice < MAD_NSBSAMPLES(&frame->header); slice++) {
	            mad_fixed_t fixed = frame->sbsample[channel][slice][band];
	            avg += abs(fixed >> (MAD_F_FRACBITS-5));
	            /*avg >> 1;*/
            }
            sample = avg;

            /* Fixed point values cover the range [-8.0, 8.0).
	           Convert this to the int range [-1024, 1023]
	           meaning that [-1.0, 1.0) ==> [-128, 127].
             */
            /*int sample = fixed >> 18; */
            /*DBG_PRINTF("mp3: %3d ", sample); */

            if (sample > 50) {
                sample = 50;
            }
            sample -= 10;
            if (sample < 0) {
                sample = 0;
            }

            video_set_colour (&vid, 255, 255, 255);
            video_v_line (&vid, 250 + band * 3 + (100 * channel), vid.visy - 100, -sample);
            video_set_colour (&vid, 0, 0, 0);
            video_v_line (&vid, 250 + band * 3 + (100 * channel), vid.visy - sample - 100, -50 - sample);
            video_set_colour (&vid, 255, 255, 255);
            video_v_line (&vid, 250 + band * 3 + 1 + (100 * channel), vid.visy - 100, -sample);
            video_set_colour (&vid, 0, 0, 0);
            video_v_line (&vid, 250 + band * 3 + 1 + (100 * channel), vid.visy - sample - 100, -50 - sample);
#if 0
            avg += sample;
#endif
        }
        /*DBG_PRINTF("\n"); */

    return MAD_FLOW_CONTINUE;
}
#endif


/*
 *  error
 */
static enum mad_flow error(void *data, 
                           struct mad_stream *stream,
                           struct mad_frame *frame)
{
    DBG_PRINTF("mp3_play: decoding error 0x%04x (%s)\n", stream->error, mad_stream_errorstr(stream));

    return MAD_FLOW_CONTINUE;
}
예제 #14
0
파일: snd_mp3.c 프로젝트: dommul/super8
/* Read up to len samples from p->Synth
 * If needed, read some more MP3 data, decode them and synth them
 * Place in buf[].
 * Return number of samples read.  */
static int mp3_decode(snd_stream_t *stream, byte *buf, int len)
{
	mp3_priv_t *p = (mp3_priv_t *) stream->priv;
	int donow, i, done = 0;
	mad_fixed_t sample;
	int chan, x;

	do
	{
		x = (p->Synth.pcm.length - p->cursamp) * stream->info.channels;
		donow = min(len, x);
		i = 0;
		while (i < donow)
		{
			for (chan = 0; chan < stream->info.channels; chan++)
			{
				sample = p->Synth.pcm.samples[chan][p->cursamp];
				/* convert from fixed to short,
				 * write in host-endian format. */
				if (sample <= -MAD_F_ONE)
					sample = -0x7FFF;
				else if (sample >= MAD_F_ONE)
					sample = 0x7FFF;
				else
					sample >>= (MAD_F_FRACBITS + 1 - 16);
				if (host_bigendian)
				{
					*buf++ = (sample >> 8) & 0xFF;
					*buf++ = sample & 0xFF;
				}
				else /* assumed LITTLE_ENDIAN. */
				{
					*buf++ = sample & 0xFF;
					*buf++ = (sample >> 8) & 0xFF;
				}
				i++;
			}
			p->cursamp++;
		}

		len -= donow;
		done += donow;

		if (len == 0)
			break;

		/* check whether input buffer needs a refill */
		if (p->Stream.error == MAD_ERROR_BUFLEN)
		{
			if (mp3_inputdata(stream) == -1)
			{
				/* check feof() ?? */
				Con_DPrintf("mp3 EOF\n");
				break;
			}
		}

		if (mad_frame_decode(&p->Frame, &p->Stream))
		{
			if (MAD_RECOVERABLE(p->Stream.error))
			{
				mp3_inputtag(stream);
				continue;
			}
			else
			{
				if (p->Stream.error == MAD_ERROR_BUFLEN)
					continue;
				else
				{
					Con_Printf("MP3: unrecoverable frame level error (%s)\n",
							mad_stream_errorstr(&p->Stream));
					break;
				}
			}
		}
		p->FrameCount++;
		mad_timer_add(&p->Timer, p->Frame.header.duration);
		mad_synth_frame(&p->Synth, &p->Frame);
		p->cursamp = 0;
	} while (1);
예제 #15
0
static OMX_ERRORTYPE
decode_buffer (const void * ap_obj)
{
  mp3d_prc_t * p_obj = (mp3d_prc_t *) ap_obj;
  unsigned char * p_guardzone = NULL;
  int status = 0;

  assert (p_obj->p_outhdr_);

  /* Check if there is any remaining PCM data from a previous run of the
   * decoding loop that needs to be synthesised */
  if ((0 != p_obj->next_synth_sample_
       && p_obj->next_synth_sample_ < p_obj->synth_.pcm.length)
      && (p_obj->p_outhdr_->nFilledLen < p_obj->p_outhdr_->nAllocLen))
    {
      p_obj->next_synth_sample_
        = synthesize_samples (p_obj, p_obj->next_synth_sample_);
    }

  while (p_obj->p_outhdr_)
    {

      /* The input bucket must be filled if it becomes empty or if
       * it's the first execution of the loop.
       */

      if ((NULL == p_obj->stream_.buffer
           || MAD_ERROR_BUFLEN == p_obj->stream_.error)
          && p_obj->p_inhdr_ != NULL)
        {
          size_t read_size = 0;
          unsigned char * p_read_start = NULL;
          p_obj->remaining_ = 0;

          if (p_obj->stream_.next_frame != NULL)
            {
              p_obj->remaining_
                = p_obj->stream_.bufend - p_obj->stream_.next_frame;
              memmove (p_obj->in_buff_, p_obj->stream_.next_frame,
                       p_obj->remaining_);
              p_read_start = p_obj->in_buff_ + p_obj->remaining_;
              read_size = INPUT_BUFFER_SIZE - p_obj->remaining_;
            }
          else
            {
              read_size = INPUT_BUFFER_SIZE;
              p_read_start = p_obj->in_buff_;
              p_obj->remaining_ = 0;
            }

          /* Fill-in the buffer. If an error occurs print a message
           * and leave the decoding loop. If the end of stream is
           * reached we also leave the loop but the return status is
           * left untouched.
           */
          read_size = read_from_omx_buffer (p_obj, p_read_start, read_size,
                                            p_obj->p_inhdr_);
          if (read_size == 0)
            {
              if ((p_obj->p_inhdr_->nFlags & OMX_BUFFERFLAG_EOS) != 0)
                {
                  TIZ_TRACE (handleOf (p_obj), "end of input stream");
                  status = 2;
                }
              else
                {
                  TIZ_TRACE (handleOf (p_obj), "read_size <= 0");
                  status = 1;
                }
              break;
            }

          /* TODO */
          /*       if(BstdFileEofP (BstdFile)) */
          /*         { */
          /*           p_guardzone = p_read_start + read_size; */
          /*           memset (p_guardzone, 0, MAD_BUFFER_GUARD); */
          /*           read_size += MAD_BUFFER_GUARD; */
          /*         } */

          /* Pipe the new buffer content to libmad's stream decoder
           * facility.
           */
          mad_stream_buffer (&p_obj->stream_, p_obj->in_buff_,
                             read_size + p_obj->remaining_);
          p_obj->stream_.error = 0;
        }

      if (mad_frame_decode (&p_obj->frame_, &p_obj->stream_) == -1)
        {
          if (MAD_RECOVERABLE (p_obj->stream_.error))
            {
              if (p_obj->stream_.error != MAD_ERROR_LOSTSYNC
                  || p_obj->stream_.this_frame != p_guardzone)
                {
                  TIZ_TRACE (handleOf (p_obj),
                             "recoverable frame level error (%s)",
                             mad_stream_errorstr (&p_obj->stream_));
                }
              continue;
            }
          else
            {
              if (p_obj->stream_.error == MAD_ERROR_BUFLEN)
                {
                  if (!p_obj->p_inhdr_)
                    {
                      TIZ_TRACE (handleOf (p_obj),
                                 "p_obj->stream_.error==MAD_ERROR_BUFLEN "
                                 "p_obj->p_inhdr_=[NULL]");
                      break;
                    }
                  else
                    {
                      TIZ_TRACE (handleOf (p_obj),
                                 "p_obj->stream_.error==MAD_ERROR_BUFLEN "
                                 "p_obj->p_inhdr_=[%p] nFilledLen [%d]",
                                 p_obj->p_inhdr_, p_obj->p_inhdr_->nFilledLen);
                      continue;
                    }
                }
              else
                {
                  TIZ_TRACE (handleOf (p_obj),
                             "unrecoverable frame level error (%s).",
                             mad_stream_errorstr (&p_obj->stream_));
                  status = 2;
                  break;
                }
            }
        }

      /* The characteristics of the stream's first frame is printed The first
       * frame is representative of the entire stream.
       */
      if (0 == p_obj->frame_count_)
        {
          store_stream_metadata (p_obj, &(p_obj->frame_.header));
        }

      p_obj->frame_count_++;
      mad_timer_add (&p_obj->timer_, p_obj->frame_.header.duration);

      /* Once decoded the frame is synthesized to PCM samples. No errors
       * are reported by mad_synth_frame();
       */
      mad_synth_frame (&p_obj->synth_, &p_obj->frame_);

      p_obj->next_synth_sample_
        = synthesize_samples (p_obj, p_obj->next_synth_sample_);
    }

  (void) status;
  /* TODO */
  /*   if (p_obj->p_outhdr_ != NULL */
  /*       && p_obj->p_outhdr_->nFilledLen != 0 */
  /*       && status == 2) */
  /*     { */
  /*       const tiz_srv_t *p_parent = ap_obj; */
  /*       void *p_krn = tiz_get_krn (p_parent->p_hdl_); */

  /*       p_obj->eos_ = true; */
  /*       p_obj->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS; */
  /*       TIZ_LOG (TIZ_PRIORITY_TRACE, handleOf (p_obj), */
  /*                        "Releasing output buffer [%p] ..." */
  /*                        "nFilledLen = [%d] OMX_BUFFERFLAG_EOS", */
  /*                        p_obj->p_outhdr_, p_obj->p_outhdr_->nFilledLen); */
  /*       tiz_krn_release_buffer (tiz_get_krn (handleOf (ap_obj)), 1,
   * p_obj->p_outhdr_); */
  /*       /\* p_obj->p_outhdr_ = NULL; *\/ */
  /*     } */

  return OMX_ErrorNone;
}
예제 #16
0
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
}
예제 #17
0
/*****************************************************************************
 * DoWork: decode an MPEG audio frame.
 *****************************************************************************/
static void DoWork( filter_t * p_filter,
                    block_t * p_in_buf, block_t * p_out_buf )
{
    filter_sys_t *p_sys = p_filter->p_sys;

    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(float) *
                               aout_FormatNbChannels( &p_filter->fmt_out.audio );

    /* Do the actual decoding now. */
    mad_stream_buffer( &p_sys->mad_stream, p_in_buf->p_buffer,
                       p_in_buf->i_buffer );
    if ( mad_frame_decode( &p_sys->mad_frame, &p_sys->mad_stream ) == -1 )
    {
        msg_Err( p_filter, "libmad error: %s",
                  mad_stream_errorstr( &p_sys->mad_stream ) );
        if( !MAD_RECOVERABLE( p_sys->mad_stream.error ) )
            p_sys->i_reject_count = 3;
    }
    else if( p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        p_sys->i_reject_count = 3;
    }

    if( p_sys->i_reject_count > 0 )
    {
reject:
        memset( p_out_buf->p_buffer, 0, p_out_buf->i_buffer );
        p_sys->i_reject_count--;
        return;
    }


    mad_synth_frame( &p_sys->mad_synth, &p_sys->mad_frame );

    struct mad_pcm * p_pcm = &p_sys->mad_synth.pcm;
    unsigned int i_samples = p_pcm->length;
    mad_fixed_t const * p_left = p_pcm->samples[0];
    mad_fixed_t const * p_right = p_pcm->samples[1];
    float *p_samples = (float *)p_out_buf->p_buffer;

    if (p_pcm->channels > p_filter->fmt_out.audio.i_channels)
    {
        msg_Err( p_filter, "wrong channels count (corrupt stream?): %u > %u",
                 p_pcm->channels, p_filter->fmt_out.audio.i_channels);
        p_sys->i_reject_count = 3;
        goto reject;
    }

    if( i_samples != p_out_buf->i_nb_samples )
    {
        msg_Err( p_filter, "unexpected samples count (corrupt stream?): "
                 "%u / %u", i_samples, p_out_buf->i_nb_samples );
        p_sys->i_reject_count = 3;
        goto reject;
    }

    /* Interleave and keep buffers in mad_fixed_t format */
    if ( p_pcm->channels == 2 )
    {
        while ( i_samples-- )
        {
            //assert( *p_left < MAD_F_ONE );
            //assert( *p_left >= -MAD_F_ONE );
            //assert( *p_right < MAD_F_ONE );
            //assert( *p_right >= -MAD_F_ONE );
            *p_samples++ = (float)*p_left++ / (float)MAD_F_ONE;
            *p_samples++ = (float)*p_right++ / (float)MAD_F_ONE;
        }
    }
    else
    {
        assert( p_pcm->channels == 1 );
        while ( i_samples-- )
        {
            //assert( *p_left < MAD_F_ONE );
            //assert( *p_left >= -MAD_F_ONE );
            *p_samples++ = (float)*p_left++ / (float)MAD_F_ONE;
        }
    }
}
예제 #18
0
bool CMpegAudioDecoder::DecodeFrame(const BYTE *pData, DWORD *pDataSize, DecodeFrameInfo *pInfo)
{
	if (!m_bInitialized) {
		return false;
	}

	if (m_MadStream.buffer == nullptr || m_MadStream.error == MAD_ERROR_BUFLEN) {
		size_t ReadSize, Remain;

		if (m_MadStream.next_frame != nullptr) {
			Remain = m_MadStream.bufend - m_MadStream.next_frame;
			::MoveMemory(m_InputBuffer, m_MadStream.next_frame, Remain);
			ReadSize = INPUT_BUFFER_SIZE - Remain;
		} else {
			ReadSize = INPUT_BUFFER_SIZE;
			Remain = 0;
		}

		if (ReadSize > *pDataSize)
			ReadSize = *pDataSize;
		*pDataSize = (DWORD)ReadSize;

		::CopyMemory(&m_InputBuffer[Remain], pData, ReadSize);

		mad_stream_buffer(&m_MadStream, m_InputBuffer, (unsigned long)(ReadSize + Remain));
		m_MadStream.error = MAD_ERROR_NONE;
	} else {
		*pDataSize = 0;
	}

	if (mad_frame_decode(&m_MadFrame, &m_MadStream)) {
		pInfo->Samples = 0;

		if (m_MadStream.error == MAD_ERROR_BUFLEN)
			return true;
		if (MAD_RECOVERABLE(m_MadStream.error))
			return true;
#ifdef _DEBUG
		::OutputDebugStringA("libmad error : ");
		::OutputDebugStringA(mad_stream_errorstr(&m_MadStream));
		::OutputDebugStringA("\n");
#endif
		ResetDecoder();
		return false;
	}

	mad_synth_frame(&m_MadSynth, &m_MadFrame);

	const BYTE Channels = MAD_NCHANNELS(&m_MadFrame.header);
	short *p = m_PcmBuffer;

	if (Channels == 1) {
		for (int i = 0; i < m_MadSynth.pcm.length; i++) {
			*p++ = FixedToInt16(m_MadSynth.pcm.samples[0][i]);
		}
	} else {
		for (int i = 0; i < m_MadSynth.pcm.length; i++) {
			*p++ = FixedToInt16(m_MadSynth.pcm.samples[0][i]);
			*p++ = FixedToInt16(m_MadSynth.pcm.samples[1][i]);
		}
	}

	m_AudioInfo.Frequency = m_MadSynth.pcm.samplerate;
	m_AudioInfo.Channels = Channels;
	m_AudioInfo.OrigChannels = Channels;
	m_AudioInfo.bDualMono = false;

	pInfo->pData = (const BYTE*)m_PcmBuffer;
	pInfo->Samples = m_MadSynth.pcm.length;
	pInfo->Info = m_AudioInfo;
	pInfo->bDiscontinuity = m_bDecodeError;

	return true;
}
예제 #19
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;
}
예제 #20
0
파일: MadDecoder.cpp 프로젝트: dreieier/E3
    //
    // 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;
    }
예제 #21
0
파일: mp3.c 프로젝트: ecthiender/mocp-git
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);
}
예제 #22
0
int MAD_WRAPPER_playAudio( void *userdata, Uint8 *stream, int len )
{
    MAD_WRAPPER *mad = (MAD_WRAPPER*)userdata;

    if ( !mad->is_playing ) return -1; // pause
    
    size_t         ReadSize = 1, Remaining;
    unsigned char  *ReadStart;

    do{
        if( mad->Stream.buffer==NULL || mad->Stream.error==MAD_ERROR_BUFLEN ){
    
            if ( mad->Stream.next_frame != NULL ){
                Remaining = mad->Stream.bufend - mad->Stream.next_frame;
                memmove( mad->input_buf, mad->Stream.next_frame, Remaining);
                ReadStart = mad->input_buf + Remaining;
                ReadSize  = INPUT_BUFFER_SIZE - Remaining;
            }
            else{
                ReadSize  = INPUT_BUFFER_SIZE;
                ReadStart = mad->input_buf;
                Remaining = 0;
            }

            ReadSize = SDL_RWread( mad->src, ReadStart, 1, ReadSize );
            if ( ReadSize <= 0 ) break; // end of stream

            mad_stream_buffer( &mad->Stream, mad->input_buf, ReadSize + Remaining );
            mad->Stream.error = MAD_ERROR_NONE;
        }

        if ( mad_frame_decode( &mad->Frame,&mad->Stream ) ){
            if ( MAD_RECOVERABLE( mad->Stream.error ) ||
                 mad->Stream.error == MAD_ERROR_BUFLEN ){
                continue;
            }
            else{
                fprintf( stderr, "unrecoverable frame level error (%s).\n",
                         mad_stream_errorstr(&mad->Stream) );
                return 0; // error
            }
        }

#if defined(PDA) && !defined(PSP) && !defined(IPHONE)
        if ( mad->Frame.header.samplerate == 44100 )
            mad->Frame.options |= MAD_OPTION_HALFSAMPLERATE;
#endif
        mad_synth_frame( &mad->Synth, &mad->Frame );
    
        char *ptr = (char*)mad->output_buf + mad->output_buf_index;

        for ( int i=0 ; i<mad->Synth.pcm.length ; i++ ){
            unsigned short	Sample;

            /* Left channel */
            Sample=MadFixedToUshort( mad->Synth.pcm.samples[0][i] );
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
            *(ptr++) = Sample & 0xff;
            *(ptr++) = Sample >> 8;
#else
            *(ptr++) = Sample >> 8;
            *(ptr++) = Sample & 0xff;
#endif

            /* Right channel, if exist. */
            if ( MAD_NCHANNELS(&mad->Frame.header)==2 )
                Sample=MadFixedToUshort( mad->Synth.pcm.samples[1][i] );
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
            *(ptr++) = Sample & 0xff;
            *(ptr++) = Sample >> 8;
#else
            *(ptr++) = Sample >> 8;
            *(ptr++) = Sample&0xff;
#endif
        }
        mad->output_buf_index += mad->Synth.pcm.length * 4;
    }
    while( mad->output_buf_index < len );

    if ( ReadSize <= 0 ) return 0; // end of stream

    if ( mad->output_buf_index > len ){
        SDL_MixAudio( stream, mad->output_buf, len, mad->volume );
        memmove( mad->output_buf, mad->output_buf + len, mad->output_buf_index - len );
        mad->output_buf_index -= len;
    }
    else{
        SDL_MixAudio( stream, mad->output_buf, mad->output_buf_index, mad->volume );
        len = mad->output_buf_index;
        mad->output_buf_index = 0;
    }

    return len;
}
/* Handle first-stage decoding: extracting the MP3 frame data. */
int RageSoundReader_MP3::do_mad_frame_decode( bool headers_only )
{
	int bytes_read = 0;

	while(1)
	{
		int ret;

		/* Always actually decode the first packet, so we cleanly parse Xing tags. */
		if( headers_only && !mad->first_frame )
			ret=mad_header_decode( &mad->Frame.header,&mad->Stream );
		else
			ret=mad_frame_decode( &mad->Frame,&mad->Stream );

		if( ret == -1 && (mad->Stream.error == MAD_ERROR_BUFLEN || mad->Stream.error == MAD_ERROR_BUFPTR) )
		{
			if( bytes_read > 25000 )
			{
				/* We've read this much without actually getting a frame; error. */
				SetError( "Can't find data" );
				return -1;
			}

			ret = fill_buffer();
			if( ret <= 0 )
				return ret;
			bytes_read += ret;

			continue;
		}

		if( ret == -1 && mad->Stream.error == MAD_ERROR_LOSTSYNC )
		{
			/* This might be an ID3V2 tag. */
			const int tagsize = id3_tag_query(mad->Stream.this_frame,
				mad->Stream.bufend - mad->Stream.this_frame);

			if( tagsize )
			{
				mad_stream_skip(&mad->Stream, tagsize);

				/* Don't count the tagsize against the max-read-per-call figure. */
				bytes_read -= tagsize;

				continue;
			}
		}

		if( ret == -1 && mad->Stream.error == MAD_ERROR_BADDATAPTR )
		{
			/*
			 * Something's corrupt.  One cause of this is cutting an MP3 in the middle
			 * without reencoding; the first two frames will reference data from previous
			 * frames that have been removed.  The frame is valid--we can get a header from
			 * it, we just can't synth useful data.
			 *
			 * BASS pretends the bad frames are silent.  Emulate that, for compatibility.
			 */
			ret = 0; /* pretend success */
		}

		if( !ret )
		{
			/* OK. */
			if( mad->first_frame )
			{
				/* We're at the beginning.  Is this a Xing tag? */
				if(handle_first_frame())
				{
					/* The first frame contained a header. Continue searching. */
					continue;
				}

				/* We've decoded the first frame of data. 
				 *
				 * We want mad->Timer to represent the timestamp of the first sample of the
				 * currently decoded frame.  Don't increment mad->Timer on the first frame,
				 * or it'll be the time of the *next* frame.  (All frames have the same
				 * duration.) */
				mad->first_frame = false;
				mad->Timer = mad_timer_zero;
				mad->header_bytes = get_this_frame_byte(mad);
			}
			else
			{
				mad_timer_add( &mad->Timer,mad->Frame.header.duration );
			}

			fill_frame_index_cache( mad );

			return 1;
		}

		if( mad->Stream.error == MAD_ERROR_BADCRC )
		{
			/* XXX untested */
			mad_frame_mute(&mad->Frame);
			mad_synth_mute(&mad->Synth);

			continue;
		}

		if( !MAD_RECOVERABLE(mad->Stream.error) )
		{
			/* We've received an unrecoverable error. */
			SetError( mad_stream_errorstr(&mad->Stream) );
			return -1;
		}
	}
}
예제 #24
0
파일: k3bmaddecoder.cpp 프로젝트: KDE/k3b
bool K3bMadDecoder::seekInternal( const K3b::Msf& pos )
{
    //
    // we need to reset the complete mad stuff
    //
    if( !initDecoderInternal() )
        return false;

    //
    // search a position
    // This is all hacking, I don't really know what I am doing here... ;)
    //
    double mp3FrameSecs = static_cast<double>(d->firstHeader.duration.seconds)
                          + static_cast<double>(d->firstHeader.duration.fraction) / static_cast<double>(MAD_TIMER_RESOLUTION);

    double posSecs = static_cast<double>(pos.totalFrames()) / 75.0;

    // seekPosition to seek after frame i
    unsigned int frame = static_cast<unsigned int>( posSecs / mp3FrameSecs );

    // Rob said: 29 frames is the theoretically max frame reservoir limit (whatever that means...)
    // it seems that mad needs at most 29 frames to get ready
    unsigned int frameReservoirProtect = ( frame > 29 ? 29 : frame );

    frame -= frameReservoirProtect;

    // seek in the input file behind the already decoded data
    d->handle->inputSeek( d->seekPositions[frame] );

    qDebug() << "(K3bMadDecoder) Seeking to frame " << frame << " with "
             << frameReservoirProtect << " reservoir frames." << endl;

    // decode some frames ignoring MAD_ERROR_BADDATAPTR errors
    unsigned int i = 1;
    while( i <= frameReservoirProtect ) {
        d->handle->fillStreamBuffer();
        if( mad_frame_decode( d->handle->madFrame, d->handle->madStream ) ) {
            if( MAD_RECOVERABLE( d->handle->madStream->error ) ) {
                if( d->handle->madStream->error == MAD_ERROR_BUFLEN )
                    continue;
                else if( d->handle->madStream->error != MAD_ERROR_BADDATAPTR ) {
                    qDebug() << "(K3bMadDecoder) Seeking: recoverable mad error ("
                             << mad_stream_errorstr(d->handle->madStream) << ")" << endl;
                    continue;
                }
                else {
                    qDebug() << "(K3bMadDecoder) Seeking: ignoring ("
                             << mad_stream_errorstr(d->handle->madStream) << ")" << endl;
                }
            }
            else
                return false;
        }

        if( i == frameReservoirProtect )  // synth only the last frame (Rob said so ;)
            mad_synth_frame( d->handle->madSynth, d->handle->madFrame );

        ++i;
    }

    return true;
}
예제 #25
0
SINT SoundSourceMp3::readSampleFrames(
        SINT numberOfFrames, CSAMPLE* sampleBuffer,
        SINT sampleBufferSize, bool readStereoSamples) {
    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(getSampleBufferSize(numberOfFrames, readStereoSamples) <= sampleBufferSize);

    const SINT numberOfFramesTotal = math_min(
            numberOfFrames, getMaxFrameIndex() - m_curFrameIndex);

    CSAMPLE* pSampleBuffer = sampleBuffer;
    SINT numberOfFramesRemaining = numberOfFramesTotal;
    while (0 < numberOfFramesRemaining) {
        if (0 >= m_madSynthCount) {
            // When all decoded output data has been consumed...
            DEBUG_ASSERT(0 == m_madSynthCount);
            // ...decode the next MP3 frame
            DEBUG_ASSERT(m_madStream.buffer);
            DEBUG_ASSERT(m_madStream.this_frame);

            // WARNING: Correctly evaluating and handling the result
            // of mad_frame_decode() has proven to be extremely tricky.
            // Don't change anything at the following lines of code
            // unless you know what you are doing!!!
            unsigned char const* pMadThisFrame = m_madStream.this_frame;
            if (mad_frame_decode(&m_madFrame, &m_madStream)) {
                // Something went wrong when decoding the frame...
                if (MAD_ERROR_BUFLEN == m_madStream.error) {
                    // Abort
                    break;
                }
                if (isUnrecoverableError(m_madStream)) {
                    qWarning() << "Unrecoverable MP3 frame decoding error:"
                            << mad_stream_errorstr(&m_madStream);
                    // Abort decoding
                    break;
                }
                if (isRecoverableError(m_madStream)) {
                    if (pMadThisFrame != m_madStream.this_frame) {
                        // Ignore all recoverable errors (and especially
                        // "lost synchronization" warnings) while skipping
                        // over prefetched frames after seeking.
                        if (pSampleBuffer) {
                            qWarning() << "Recoverable MP3 frame decoding error:"
                                    << mad_stream_errorstr(&m_madStream);
                        } else {
                            // Decoded samples will simply be discarded
                            qDebug() << "Recoverable MP3 frame decoding error while skipping:"
                                << mad_stream_errorstr(&m_madStream);
                        }
                    }
                    // Continue decoding
                }
            }
            if (pMadThisFrame == m_madStream.this_frame) {
                qDebug() << "Retry decoding MP3 frame @" << m_curFrameIndex;
                // Retry decoding
                continue;
            }

            DEBUG_ASSERT(isStreamValid(m_madStream));

#ifndef QT_NO_DEBUG_OUTPUT
            const SINT madFrameChannelCount = MAD_NCHANNELS(&m_madFrame.header);
            if (madFrameChannelCount != getChannelCount()) {
                qDebug() << "MP3 frame header with mismatching number of channels"
                        << madFrameChannelCount << "<>" << getChannelCount();
            }
#endif

            // Once decoded the frame is synthesized to PCM samples
            mad_synth_frame(&m_madSynth, &m_madFrame);
#ifndef QT_NO_DEBUG_OUTPUT
            const SINT madSynthSampleRate =  m_madSynth.pcm.samplerate;
            if (madSynthSampleRate != getSamplingRate()) {
                qDebug() << "Reading MP3 data with different sampling rate"
                        << madSynthSampleRate << "<>" << getSamplingRate();
            }
#endif
            m_madSynthCount = m_madSynth.pcm.length;
            DEBUG_ASSERT(0 < m_madSynthCount);
        }

        const SINT synthReadCount = math_min(
                m_madSynthCount, numberOfFramesRemaining);
        if (pSampleBuffer) {
            DEBUG_ASSERT(m_madSynthCount <= m_madSynth.pcm.length);
            const SINT madSynthOffset =
                    m_madSynth.pcm.length - m_madSynthCount;
            DEBUG_ASSERT(madSynthOffset < m_madSynth.pcm.length);
            const SINT madSynthChannelCount = m_madSynth.pcm.channels;
            DEBUG_ASSERT(0 < madSynthChannelCount);
            DEBUG_ASSERT(madSynthChannelCount <= getChannelCount());
#ifndef QT_NO_DEBUG_OUTPUT
            if (madSynthChannelCount != getChannelCount()) {
                qDebug() << "Reading MP3 data with different number of channels"
                        << madSynthChannelCount << "<>" << getChannelCount();
            }
#endif
            if (kChannelCountMono == madSynthChannelCount) {
                // MP3 frame contains a mono signal
                if (readStereoSamples || (kChannelCountStereo == getChannelCount())) {
                    // The reader explicitly requested a stereo signal
                    // or the AudioSource itself provides a stereo signal.
                    // Mono -> Stereo: Copy 1st channel twice
                    for (SINT i = 0; i < synthReadCount; ++i) {
                        const CSAMPLE sampleValue = madScaleSampleValue(
                                m_madSynth.pcm.samples[0][madSynthOffset + i]);
                        *pSampleBuffer++ = sampleValue;
                        *pSampleBuffer++ = sampleValue;
                    }
                } else {
                    // Mono -> Mono: Copy 1st channel
                    for (SINT i = 0; i < synthReadCount; ++i) {
                        const CSAMPLE sampleValue = madScaleSampleValue(
                                m_madSynth.pcm.samples[0][madSynthOffset + i]);
                        *pSampleBuffer++ = sampleValue;
                    }
                }
            } else {
                // MP3 frame contains a stereo signal
                DEBUG_ASSERT(kChannelCountStereo == madSynthChannelCount);
                // If the MP3 frame contains a stereo signal then the whole
                // AudioSource must also provide 2 channels, because the
                // maximum channel count of all MP3 frames is used.
                DEBUG_ASSERT(kChannelCountStereo == getChannelCount());
                // Stereo -> Stereo: Copy 1st + 2nd channel
                for (SINT i = 0; i < synthReadCount; ++i) {
                    *pSampleBuffer++ = madScaleSampleValue(
                            m_madSynth.pcm.samples[0][madSynthOffset + i]);
                    *pSampleBuffer++ = madScaleSampleValue(
                            m_madSynth.pcm.samples[1][madSynthOffset + i]);
                }
            }
        }
        // consume decoded output data
        m_madSynthCount -= synthReadCount;
        m_curFrameIndex += synthReadCount;
        numberOfFramesRemaining -= synthReadCount;
    }

    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(numberOfFramesTotal >= numberOfFramesRemaining);
    return numberOfFramesTotal - numberOfFramesRemaining;
}
예제 #26
0
bool Mp3AudioFileReader::run(AudioProcessor& processor)
{
    if (file_ == nullptr) {
        return false;
    }

    enum {
        STATUS_OK,
        STATUS_INIT_ERROR,
        STATUS_READ_ERROR,
        STATUS_PROCESS_ERROR
    } status = STATUS_OK;

    unsigned char input_buffer[INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
    unsigned char* guard_ptr = nullptr;
    unsigned long frame_count = 0;

    short output_buffer[OUTPUT_BUFFER_SIZE];
    short* output_ptr = output_buffer;
    const short* const output_buffer_end = output_buffer + OUTPUT_BUFFER_SIZE;

    int channels = 0;

    // Decoding options can here be set in the options field of the stream
    // structure.

    // {1} When decoding from a file we need to know when the end of the file is
    // reached at the same time as the last bytes are read (see also the comment
    // marked {3} below). Neither the standard C fread() function nor the POSIX
    // read() system call provides this feature. We thus need to perform our
    // reads through an interface having this feature, this is implemented here
    // by the bstdfile.c module.

    BStdFile bstd_file(file_);

    // Initialize the structures used by libmad.
    MadStream stream;
    MadFrame frame;
    MadSynth synth;

    mad_timer_t timer;
    mad_timer_reset(&timer);

    // This is the decoding loop.

    for (;;) {
        // The input bucket must be filled if it becomes empty or if it's the
        // first execution of the loop.

        if (stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) {
            size_t read_size;
            size_t remaining;
            unsigned char* read_start;

            // {2} libmad may not consume all bytes of the input buffer. If the
            // last frame in the buffer is not wholly contained by it, then that
            // frame's start is pointed by the next_frame member of the stream
            // structure. This common situation occurs when mad_frame_decode()
            // fails, sets the stream error code to MAD_ERROR_BUFLEN, and sets
            // the next_frame pointer to a non-NULL value. (See also the comment
            // marked {4} below.)
            //
            // When this occurs, the remaining unused bytes must be put back at
            // the beginning of the buffer and taken in account before refilling
            // the buffer. This means that the input buffer must be large enough
            // to hold a whole frame at the highest observable bit-rate
            // (currently 448 kb/s). XXX=XXX Is 2016 bytes the size of the
            // largest frame? (448000*(1152/32000))/8

            if (stream.next_frame != nullptr) {
                remaining = stream.bufend - stream.next_frame;
                memmove(input_buffer, stream.next_frame, remaining);
                read_start = input_buffer + remaining;
                read_size  = INPUT_BUFFER_SIZE - remaining;
            }
            else {
                read_size  = INPUT_BUFFER_SIZE;
                read_start = input_buffer;
                remaining = 0;
            }

            // Fill-in the buffer. If an error occurs print a message and leave
            // the decoding loop. If the end of stream is reached we also leave
            // the loop but the return status is left untouched.

            read_size = bstd_file.read(read_start, 1, read_size);

            if (read_size <= 0) {
                if (ferror(file_)) {
                    error_stream << "\nRead error on bit-stream: "
                                 << strerror(errno) << '\n';
                    status = STATUS_READ_ERROR;
                }

                break;
            }

            // {3} When decoding the last frame of a file, it must be followed
            // by MAD_BUFFER_GUARD zero bytes if one wants to decode that last
            // frame. When the end of file is detected we append that quantity
            // of bytes at the end of the available data. Note that the buffer
            // can't overflow as the guard size was allocated but not used the
            // the buffer management code. (See also the comment marked {1}.)
            //
            // In a message to the mad-dev mailing list on May 29th, 2001, Rob
            // Leslie explains the guard zone as follows:
            //
            //    "The reason for MAD_BUFFER_GUARD has to do with the way
            //    decoding is performed. In Layer III, Huffman decoding may
            //    inadvertently read a few bytes beyond the end of the buffer in
            //    the case of certain invalid input. This is not detected until
            //    after the fact. To prevent this from causing problems, and
            //    also to ensure the next frame's main_data_begin pointer is
            //    always accessible, MAD requires MAD_BUFFER_GUARD (currently 8)
            //    bytes to be present in the buffer past the end of the current
            //    frame in order to decode the frame."

            if (bstd_file.eof()) {
                guard_ptr = read_start + read_size;
                memset(guard_ptr, 0, MAD_BUFFER_GUARD);
                read_size += MAD_BUFFER_GUARD;
            }

            // Pipe the new buffer content to libmad's stream decoder facility.
            mad_stream_buffer(&stream, input_buffer, read_size + remaining);
            stream.error = MAD_ERROR_NONE;
        }

        // Decode the next MPEG frame. The streams is read from the buffer, its
        // constituents are break down and stored the the frame structure, ready
        // for examination/alteration or PCM synthesis. Decoding options are
        // carried in the frame structure from the stream structure.
        //
        // Error handling: mad_frame_decode() returns a non zero value when an
        // error occurs. The error condition can be checked in the error member
        // of the stream structure. A mad error is recoverable or fatal, the
        // error status is checked with the MAD_RECOVERABLE macro.
        //
        // {4} When a fatal error is encountered all decoding activities shall
        // be stopped, except when a MAD_ERROR_BUFLEN is signaled. This
        // condition means that the mad_frame_decode() function needs more input
        // to complete its work. One shall refill the buffer and repeat the
        // mad_frame_decode() call. Some bytes may be left unused at the end of
        // the buffer if those bytes forms an incomplete frame. Before
        // refilling, the remaining bytes must be moved to the beginning of the
        // buffer and used for input for the next mad_frame_decode() invocation.
        // (See the comments marked {2} earlier for more details.)
        //
        // Recoverable errors are caused by malformed bit-streams, in this case
        // one can call again mad_frame_decode() in order to skip the faulty
        // part and re-sync to the next frame.

        if (mad_frame_decode(&frame, &stream)) {
            if (MAD_RECOVERABLE(stream.error)) {
                // Do not print a message if the error is a loss of
                // synchronization and this loss is due to the end of stream
                // guard bytes. (See the comment marked {3} above for more
                // information about guard bytes.)

                if (stream.error != MAD_ERROR_LOSTSYNC ||
                    stream.this_frame != guard_ptr) {

                    // For any MP3 file we typically see two errors in the
                    // first frame processed:
                    // - lost synchronization
                    // - reserved header layer value
                    // This seems to be OK, so don't print these

                    if (frame_count != 0) {
                        error_stream << "\nRecoverable frame level error: "
                                     << mad_stream_errorstr(&stream) << '\n';
                    }
                }

                continue;
            }
            else {
                if (stream.error == MAD_ERROR_BUFLEN) {
                    continue;
                }
                else {
                    error_stream << "\nUnrecoverable frame level error: "
                                 << mad_stream_errorstr(&stream) << '\n';
                    status = STATUS_READ_ERROR;
                    break;
                }
            }
        }

        // Display the characteristics of the stream's first frame. The first
        // frame is representative of the entire stream.

        if (frame_count == 0) {
            const int sample_rate = frame.header.samplerate;
            channels = MAD_NCHANNELS(&frame.header);

            dumpInfo(output_stream, frame.header);

            if (!processor.init(sample_rate, channels, OUTPUT_BUFFER_SIZE)) {
                status = STATUS_PROCESS_ERROR;
                break;
            }

            showProgress(0, file_size_);
        }

        // Accounting. The computed frame duration is in the frame header
        // structure. It is expressed as a fixed point number whole data type is
        // mad_timer_t. It is different from the samples fixed point format and
        // unlike it, it can't directly be added or subtracted. The timer module
        // provides several functions to operate on such numbers. Be careful
        // there, as some functions of libmad's timer module receive some of
        // their mad_timer_t arguments by value!

        frame_count++;
        mad_timer_add(&timer, frame.header.duration);

        // Once decoded the frame is synthesized to PCM samples. No errors are
        // reported by mad_synth_frame();

        mad_synth_frame(&synth, &frame);

        // Synthesized samples must be converted from libmad's fixed point
        // number to the consumer format. Here we use signed 16 bit integers on
        // two channels. Integer samples are temporarily stored in a buffer that
        // is flushed when full.

        for (int i = 0; i < synth.pcm.length; i++) {
            // Left channel
            short sample = MadFixedToSshort(synth.pcm.samples[0][i]);

            *output_ptr++ = sample;

            // Right channel. If the decoded stream is monophonic then the right
            // output channel is the same as the left one.

            if (MAD_NCHANNELS(&frame.header) == 2) {
                sample = MadFixedToSshort(synth.pcm.samples[1][i]);
                *output_ptr++ = sample;
            }

            // Flush the output buffer if it is full

            if (output_ptr == output_buffer_end) {
                long pos = ftell(file_);

                showProgress(pos, file_size_);

                bool success = processor.process(
                    output_buffer,
                    OUTPUT_BUFFER_SIZE / channels
                );

                if (!success) {
                    status = STATUS_PROCESS_ERROR;
                    break;
                }

                output_ptr = output_buffer;
            }
        }
    }

    // If the output buffer is not empty and no error occurred during the last
    // write, then flush it.

    if (output_ptr != output_buffer && status != STATUS_PROCESS_ERROR) {
        int buffer_size = static_cast<int>(output_ptr - output_buffer);

        bool success = processor.process(output_buffer, buffer_size / channels);

        if (!success) {
            status = STATUS_PROCESS_ERROR;
        }
    }

    // Accounting report if no error occurred.

    if (status == STATUS_OK) {
        // Report 100% done.
        showProgress(file_size_, file_size_);

        char buffer[80];

        // The duration timer is converted to a human readable string with the
        // versatile, but still constrained mad_timer_string() function, in a
        // fashion not unlike strftime(). The main difference is that the timer
        // is broken into several values according some of its arguments. The
        // units and fracunits arguments specify the intended conversion to be
        // executed.
        //
        // The conversion unit (MAD_UNIT_MINUTES in our example) also specify
        // the order and kind of conversion specifications that can be used in
        // the format string.
        //
        // It is best to examine libmad's timer.c source-code for details of the
        // available units, fraction of units, their meanings, the format
        // arguments, etc.

        mad_timer_string(timer, buffer, "%lu:%02lu.%03u",
            MAD_UNITS_MINUTES, MAD_UNITS_MILLISECONDS, 0);

        output_stream << "\nFrames decoded: " << frame_count
                      << " (" << buffer << ")\n";
    }

    processor.done();

    close();

    return status == STATUS_OK;
}
예제 #27
0
void LibMadWrapper::render(pcm_t *const bufferToFill, const uint32_t Channels, frame_t framesToRender)
{
    framesToRender = min(framesToRender, this->getFrames() - this->framesAlreadyRendered);
    int32_t *pcm = static_cast<int32_t *>(bufferToFill);

    // the outer loop, used for decoding and synthesizing MPEG frames
    while (framesToRender > 0 && !this->stopFillBuffer)
    {
        // write back tempbuffer, i.e. frames weve buffered from previous calls to libmad (necessary due to inelegant API of libmad, i.e. cant tell how many frames to render during one call)
        {
            const size_t itemsToCpy = min<size_t>(this->tempBuf.size(), framesToRender * Channels);

            memcpy(pcm, this->tempBuf.data(), itemsToCpy * sizeof(int32_t));

            this->tempBuf.erase(this->tempBuf.begin(), this->tempBuf.begin() + itemsToCpy);

            const size_t framesCpyd = itemsToCpy / Channels;
            framesToRender -= framesCpyd;
            this->framesAlreadyRendered += framesCpyd;

            // again: adjust position
            pcm += itemsToCpy;
        }

        int framesToDoNow = (framesToRender / gConfig.FramesToRender) > 0 ? gConfig.FramesToRender : framesToRender % gConfig.FramesToRender;
        if (framesToDoNow == 0)
        {
            continue;
        }

        int ret = mad_frame_decode(&this->frame.Value, this->stream);
        if (ret != 0)
        {
            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;
                }
            }

            string errstr = mad_stream_errorstr(this->stream);

            if (MAD_RECOVERABLE(this->stream->error))
            {
                errstr += " (recoverable)";
                CLOG(LogLevel_t::Info, errstr);
                continue;
            }
            else
            {
                errstr += " (not recoverable)";
                CLOG(LogLevel_t::Warning, errstr);
                break;
            }
        }

        mad_synth_frame(&this->synth.Value, &this->frame.Value);

        /* save PCM samples from synth.pcm */
        /* &synth.pcm->samplerate contains the sampling frequency */

        unsigned short nsamples = this->synth->pcm.length;
        mad_fixed_t const *left_ch = this->synth->pcm.samples[0];
        mad_fixed_t const *right_ch = this->synth->pcm.samples[1];

        unsigned int item = 0;
        /* audio normalization */
        const float absoluteGain = (numeric_limits<int32_t>::max()) / (numeric_limits<int32_t>::max() * this->gainCorrection);

        for (;
             !this->stopFillBuffer &&
             framesToDoNow > 0 && // frames left during this loop
             framesToRender > 0 && // frames left during this call
             nsamples > 0; // frames left from libmad
             framesToRender--, nsamples--, framesToDoNow--)
        {
            int32_t sample;

            /* output sample(s) in 24-bit signed little-endian PCM */

            sample = LibMadWrapper::toInt24Sample(*left_ch++);
            sample = gConfig.useAudioNormalization ? floor(sample * absoluteGain) : sample;
            pcm[item++] = sample;

            if (Channels == 2) // our buffer is for 2 channels
            {
                if (this->synth.Value.pcm.channels == 2) // ...but did mad also decoded for 2 channels?
                {
                    sample = LibMadWrapper::toInt24Sample(*right_ch++);
                    sample = gConfig.useAudioNormalization ? floor(sample * absoluteGain) : sample;
                    pcm[item++] = sample;
                }
                else
                {
                    // what? only one channel in a stereo file? well then: pseudo stereo
                    pcm[item++] = sample;

                    CLOG(LogLevel_t::Warning, "decoded only one channel, though this is a stereo file!");
                }
            }

            this->framesAlreadyRendered++;
        }
        pcm += item /* % this->count*/;

        // "bufferToFill" (i.e. "pcm") seems to be full, drain the rest pcm samples from libmad and temporarily save them
        while (!this->stopFillBuffer && nsamples > 0)
        {
            int32_t sample;

            /* output sample(s) in 24-bit signed little-endian PCM */

            sample = LibMadWrapper::toInt24Sample(*left_ch++);
            this->tempBuf.push_back(gConfig.useAudioNormalization ? floor(sample * absoluteGain) : sample);

            if (Channels == 2)
            {
                sample = LibMadWrapper::toInt24Sample(*right_ch++);
                this->tempBuf.push_back(gConfig.useAudioNormalization ? floor(sample * absoluteGain) : sample);
            }

            /* DONT do this: this->framesAlreadyRendered++; since we use framesAlreadyRendered as offset for "bufferToFill"*/
            nsamples--;
        }

        if (item > this->count)
        {
            CLOG(LogLevel_t::Error, "THIS SHOULD NEVER HAPPEN: read " << item << " items but only expected " << this->count << "\n");
            break;
        }
    }
}
예제 #28
0
static int himd_mp3stream_split_frames(struct himd_mp3stream * stream, unsigned int databytes, unsigned int firstframe, unsigned int lastframe, struct himderrinfo * status)
{
    int gotdata = 1;
    unsigned int i;
    struct mad_stream madstream;
    struct mad_header madheader;

    /* stream->frameptrs is NULL if the current frame has not been splitted yet */
    g_warn_if_fail(stream->frameptrs == NULL);

    stream->frameptrs = malloc((lastframe - firstframe + 2) * sizeof stream->frameptrs[0]);
    if(!stream->frameptrs)
    {
        set_status_printf(status, HIMD_ERROR_OUT_OF_MEMORY,
                   _("Can't allocate memory for %u frame pointers"),
                   lastframe-firstframe+2);
        return -1;
    }
    /* parse block */
    mad_stream_init(&madstream);
    mad_header_init(&madheader);

    mad_stream_buffer(&madstream, &stream->blockbuf[0x20],
                                  databytes+MAD_BUFFER_GUARD);

    /* drop unneeded frames in front */
    while(firstframe > 0)
    {
        if(mad_header_decode(&madheader, &madstream) < 0)
        {
            set_status_printf(status, HIMD_ERROR_BAD_DATA_FORMAT,
                _("Still %u frames to skip: %s"), firstframe, mad_stream_errorstr(&madstream));
            gotdata = 0;
            goto cleanup_decoder;
        }
        firstframe--;
        lastframe--;
    }
    

    /* store needed frames */
    for(i = 0;i <= lastframe;i++)
    {
        if(mad_header_decode(&madheader, &madstream) < 0 &&
            (madstream.error != MAD_ERROR_LOSTSYNC || i != lastframe))
        {
            set_status_printf(status, HIMD_ERROR_BAD_DATA_FORMAT,
                _("Frame %u of %u to store: %s"), i+1, lastframe, mad_stream_errorstr(&madstream));
            gotdata = 0;
            goto cleanup_decoder;
        }
        stream->frameptrs[i] = madstream.this_frame;
    }
    stream->frameptrs[i] = madstream.next_frame;
    stream->frames = lastframe+1;
    stream->curframe = 0;

cleanup_decoder:
    mad_header_finish(&madheader);
    mad_stream_finish(&madstream);

    if(!gotdata)
        return -1;

    return 0;
}