Exemple #1
0
    //
    // 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;
    }
Exemple #2
0
static int mp3_decode_frame (mp3_s *mp3)
{
  if (mp3->stream.buffer == NULL || mp3->stream.error == MAD_ERROR_BUFLEN) {
    if (mp3_fill_input (mp3) < 0) {
      return DECODE_BREAK;
    }
  }

  if (mad_frame_decode (&mp3->frame, &mp3->stream)) {
    if (MAD_RECOVERABLE (mp3->stream.error)) {
      return DECODE_CONT;
    } else {
      if (mp3->stream.error == MAD_ERROR_BUFLEN) {
	return DECODE_CONT;
      } else {
	printf ("Unrecoverable frame error: \'%s\'\n", mad_stream_errorstr (&mp3->stream));
	mp3->status = 1;
	return DECODE_BREAK;
      }
    }
  }

  mp3->frame_count++;

  return DECODE_OK;
}
void decode() { 
	// While we need to fill the buffer... 
	while ( 
	(mad_frame_decode(&frame, &stream) == -1) && 
	((stream.error == MAD_ERROR_BUFLEN) || (stream.error == MAD_ERROR_BUFPTR)) 
	) 
	{ 
		// Fill up the remainder of the file buffer. 
		int tmp;
		tmp = fillFileBuffer(); 
		if (tmp==2) {
            endofstream = 1;
			//MusicPlayerNextSong();
			/*!
			*
			*	Put here the function that does something when the file has ended.
			*
			*/
		}

		// Give new buffer to the stream. 
		mad_stream_buffer(&stream, fileBuffer, sizeof(fileBuffer)); 
	}
    // Add to the timer the stream duration
    mad_timer_add(&timer, frame.header.duration);
	// Synth the frame. 
	mad_synth_frame(&synth, &frame); 
} 
Exemple #4
0
static int read_frame(sh_audio_t *sh){
  mad_decoder_t *this = sh->context;
  int len;

while((len=demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],
          sh->a_in_buffer_size-sh->a_in_buffer_len))>0){
  sh->a_in_buffer_len+=len;
  while(1){
    int ret;
    mad_stream_buffer (&this->stream, sh->a_in_buffer, sh->a_in_buffer_len);
    ret=mad_frame_decode (&this->frame, &this->stream);
    if (this->stream.next_frame) {
	int num_bytes =
	    (char*)sh->a_in_buffer+sh->a_in_buffer_len - (char*)this->stream.next_frame;
	memmove(sh->a_in_buffer, this->stream.next_frame, num_bytes);
	mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"libmad: %d bytes processed\n",sh->a_in_buffer_len-num_bytes);
	sh->a_in_buffer_len = num_bytes;
    }
    if (ret == 0) return 1; // OK!!!
    // error! try to resync!
    if(this->stream.error==MAD_ERROR_BUFLEN) break;
  }
}
mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Cannot sync MAD frame\n");
return 0;
}
Exemple #5
0
    size_t MadDecoder::start(FILE* handle)
    {
        handle_ = handle;

        decodeBuffer_.resize(bufferSize_, false);
        ASSERT(decodeBuffer_.size() == bufferSize_);
        unsigned char* buffer = decodeBuffer_.getHead();

        int64 durationMsec = getDurationMs(buffer, bufferSize_);

        mad_stream_init(&madStream_);
        mad_frame_init(&madFrame_);
        mad_synth_init(&madSynth_);
        mad_timer_reset(&madTimer_);

        // Decode at least one valid frame to find out the input format.
        // The decoded frame will be saved off so that it can be processed later.
        //
        size_t bytesRead = fread(buffer, (size_t)1, bufferSize_, handle_);
        if (bytesRead != bufferSize_ && ferror(handle_))
            THROW(std::exception, "%s", strerror(errno));
        mad_stream_buffer(&madStream_, buffer, bytesRead);

        // Find a valid frame before starting up.
        // This make sure that we have a valid MP3 
        // and also skips past ID3v2 tags at the beginning of the audio file.
        //
        madStream_.error = MAD_ERROR_NONE;
        while (mad_frame_decode(&madFrame_, &madStream_))
        {
            // check whether input buffer needs a refill 
            if (madStream_.error == MAD_ERROR_BUFLEN) {

                if (readMpgFile() == false) break;              // eof
                else continue;
            }
            consumeId3Tag();    // consume any ID3 tags

            // FIXME: We should probably detect when we've read
            // a bunch of non-ID3 data and still haven't found a
            // frame.  In that case we can abort early without
            // scanning the whole file.
            //
            madStream_.error = MAD_ERROR_NONE;
        }

        if (madStream_.error) {
            THROW(std::exception, "No valid MP3 frame found");
        }

        mad_timer_add(&madTimer_, madFrame_.header.duration);
        mad_synth_frame(&madSynth_, &madFrame_);

        //unsigned int precision_ = 16;
        currentFrame_ = 0;
        numMpegFrames_ = 0;
        initialized_ = true;

        return (size_t)(durationMsec * .001 * getSampleRate() + .5);  // number of sample frames
    }
Exemple #6
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) );
    }
}
Exemple #7
0
/* 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;
}
Exemple #8
0
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;
}
Exemple #9
0
  bool madaudiofile::getNextAudioFrame() {
#ifdef HAVE_MAD_H
#ifdef MADAUDIO_PRINT_DEBUG
    printf("Now in getNextAudioFrame()\n");
#endif      
    u_int8_t *OutputPtr = OutputBuffer;
    u_int8_t *GuardPtr = NULL;

    while(OutputPtr < OutputBufferEnd) {
      /* The input bucket must be filled if it becomes empty or if
       * it's the first execution of the loop.
       */
      if(Stream->buffer==NULL || Stream->error==MAD_ERROR_BUFLEN || 
	 frame_count == 0) {
	size_t ReadSize,Remaining;
	unsigned char *ReadStart;
          
	/* {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} bellow.)
	 *
	 * 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!=NULL) {
	  Remaining=Stream->bufend-Stream->next_frame;
	  memmove(InputBuffer,Stream->next_frame,Remaining);
	  ReadStart=InputBuffer+Remaining;
	  ReadSize=INPUT_BUFFER_SIZE-Remaining;
	}
	else
	  ReadSize=INPUT_BUFFER_SIZE,
	    ReadStart=InputBuffer,
	    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.
	 */
	ReadSize=readData(ReadStart,1,ReadSize,file);
	if(ReadSize<=0) {
	  break; // probably end of file reached and nothing was read
	}
          
	/* {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(reachedEOF) {
	  GuardPtr=ReadStart+ReadSize;
	  memset(GuardPtr,0,MAD_BUFFER_GUARD);
	  ReadSize+=MAD_BUFFER_GUARD;
	}
          
	/* Pipe the new buffer content to libmad's stream decoder
	 * facility.
	 */
	mad_stream_buffer(Stream,InputBuffer,ReadSize+Remaining);
	Stream->error=(mad_error)0;
      }
        
      /* 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 comments marked {3}
	   * supra for more informations about guard bytes.)
	   */
	  if(Stream->error!=MAD_ERROR_LOSTSYNC ||
	     Stream->this_frame!=GuardPtr) {
	  }
	  continue;
	}
	else
	  if(Stream->error==MAD_ERROR_BUFLEN)
	    continue; // end of buffer reached --> read more from the file
	  else {
	    fprintf(stderr,
		    "madaudiofile: unrecoverable frame level error (%i).\n",
		    Stream->error);
	    break;
	  }
      }

        
      if(frame_count == 0) {
	samplerate = Frame->header.samplerate;
#ifdef MADAUDIO_PRINT_DEBUG
	printf("Initially setting samplerate to %i\n",samplerate);
#endif
      }
#ifdef MADAUDIO_PRINT_DEBUG
      if(Frame->header.samplerate != samplerate)
	printf("Obs: samplerate changed to %i!\n",Frame->header.samplerate);
#endif        
      /* 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 unsigned
       * 16 bit big endian integers on two channels. Integer samples
       * are temporarily stored in a buffer that is flushed when
       * full.
       */
      int unsigned sr = 0;
      for(int i=0;i<Synth->pcm.length;i++) {
	signed short    Sample;

	u_int8_t left[2];
	u_int8_t right[2];
	/* Left channel */
	Sample=MadFixedToSshort(Synth->pcm.samples[0][i]);
	left[0]=Sample>>8;
	left[1]=Sample&0xff;
            
	/* 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]);
	right[0]=Sample>>8;
	right[1]=Sample&0xff;

	while(sr < samplerate) {
	  /* Left channel */
	  *(OutputPtr++)=left[1];
	  *(OutputPtr++)=left[0];
            
	  /* Right channel. If the decoded stream is monophonic then
	   * the right output channel is the same as the left one.
	   */
	  *(OutputPtr++)=right[1];
	  *(OutputPtr++)=right[0];

	  sr += Synth->pcm.samplerate;
	}
	sr -= samplerate;
      }
        
      if (OutputPtr>=OutputBufferEnd+OUTPUT_BUFFER_SAFETY) {
	char cstr[200];
	sprintf(cstr,"getNextAudioFrame() writing outside of OutputBuffer:"
		" %p >= %p VERY BAD!!!\n", OutputPtr,
		OutputBufferEnd+OUTPUT_BUFFER_SAFETY);
	throw(string(cstr));
      }
        
    } // while(OutputPtr < OutputBufferEnd)
    outputLength = OutputPtr-OutputBuffer;
    outputPosition = 0;

    if (outputLength == 0)
      reachedEOF = true;

    // If we have breaked out of the loop, but it wasn't because of EOF,
    // return false.
    if (OutputPtr < OutputBufferEnd && !reachedEOF) 
      return false;

    return true;
#else
    cerr << "libmad not available" << endl;
    return false;
#endif // HAVE_MAD_H
  }
Exemple #10
0
static gint
xmms_mad_read (xmms_xform_t *xform, gpointer buf, gint len, xmms_error_t *err)
{
	xmms_mad_data_t *data;
	xmms_samples16_t *out = (xmms_samples16_t *)buf;
	gint ret;
	gint j;
	gint read = 0;

	data = xmms_xform_private_data_get (xform);

	j = 0;

	while (read < len) {

		/* use already synthetized frame first */
		if (data->synthpos < data->synth.pcm.length) {
			out[j++] = scale_linear (data->synth.pcm.samples[0][data->synthpos]);
			if (data->channels == 2) {
				out[j++] = scale_linear (data->synth.pcm.samples[1][data->synthpos]);
				read += 2 * xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16);
			} else {
				read += xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16);
			}
			data->synthpos++;
			continue;
		}

		/* then try to decode another frame */
		if (mad_frame_decode (&data->frame, &data->stream) != -1) {

			/* mad_synthpop_frame - go Depeche! */
			mad_synth_frame (&data->synth, &data->frame);

			if (data->frames_to_skip) {
				data->frames_to_skip--;
				data->synthpos = 0x7fffffff;
			} else if (data->samples_to_skip) {
				if (data->samples_to_skip > data->synth.pcm.length) {
					data->synthpos = 0x7fffffff;
					data->samples_to_skip -= data->synth.pcm.length;
				} else {
					data->synthpos = data->samples_to_skip;
					data->samples_to_skip = 0;
				}
			} else {
				if (data->samples_to_play == 0) {
					return read;
				} else if (data->samples_to_play > 0) {
					if (data->synth.pcm.length > data->samples_to_play) {
						data->synth.pcm.length = data->samples_to_play;
					}
					data->samples_to_play -= data->synth.pcm.length;
				}
				data->synthpos = 0;
			}
			continue;
		}


		/* if there is no frame to decode stream more data */
		if (data->stream.next_frame) {
			guchar *buffer = data->buffer;
			const guchar *nf = data->stream.next_frame;
			memmove (data->buffer, data->stream.next_frame,
			         data->buffer_length = (&buffer[data->buffer_length] - nf));
		}

		ret = xmms_xform_read (xform,
		                       (gchar *)data->buffer + data->buffer_length,
		                       4096 - data->buffer_length,
		                       err);

		if (ret <= 0) {
			return ret;
		}

		data->buffer_length += ret;
		mad_stream_buffer (&data->stream, data->buffer, data->buffer_length);
	}

	return read;
}
Exemple #11
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
}
Exemple #12
0
// MP3 decode player
void MP3Player(void)
{
    FRESULT res;
    uint8_t *ReadStart;
    uint8_t *GuardPtr;
    volatile uint8_t u8PCMBufferTargetIdx = 0;
    volatile uint32_t pcmbuf_idx, i;
    volatile unsigned int Mp3FileOffset=0;
    uint16_t sampleL, sampleR;

    pcmbuf_idx = 0;
    memset((void *)&audioInfo, 0, sizeof(audioInfo));

    /* Parse MP3 header */
    MP3_ParseHeaderInfo(MP3_FILE);

    /* First the structures used by libmad must be initialized. */
    mad_stream_init(&Stream);
    mad_frame_init(&Frame);
    mad_synth_init(&Synth);

    /* Open MP3 file */
    res = f_open(&mp3FileObject, MP3_FILE, FA_OPEN_EXISTING | FA_READ);
    if (res != FR_OK) {
        printf("Open file error \r\n");
        return;
    }

    /* Open I2S1 interface and set to slave mode, stereo channel, I2S format */
    I2S_Open(I2S1, I2S_MODE_SLAVE, 16000, I2S_DATABIT_16, I2S_STEREO, I2S_FORMAT_I2S, I2S_I2S);

    /* Initialize WAU8822 codec */
    WAU8822_Setup();

    /* Configure wau8822 for specific sampling rate */
    WAU8822_ConfigSampleRate(audioInfo.mp3SampleRate);

    /* Set MCLK and enable MCLK */
    I2S_EnableMCLK(I2S1, 12000000);

    while(1) {
        if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) {
            if(Stream.next_frame != NULL) {
                /* Get the remaining frame */
                Remaining = Stream.bufend - Stream.next_frame;
                memmove(MadInputBuffer, Stream.next_frame, Remaining);
                ReadStart = MadInputBuffer + Remaining;
                ReadSize = FILE_IO_BUFFER_SIZE - Remaining;
            } else {
                ReadSize = FILE_IO_BUFFER_SIZE,
                ReadStart = MadInputBuffer,
                Remaining = 0;
            }

            /* read the file from SDCard */
            res = f_read(&mp3FileObject, ReadStart, ReadSize, &ReturnSize);
            if((res != FR_OK) || f_eof(&mp3FileObject)) {
                printf("Stop !(%x)\n\r", res);
                goto stop;
            }

            /* if the file is over */
            if (ReadSize > ReturnSize) {
                GuardPtr=ReadStart+ReadSize;
                memset(GuardPtr,0,MAD_BUFFER_GUARD);
                ReadSize+=MAD_BUFFER_GUARD;
            }

            Mp3FileOffset = Mp3FileOffset + ReturnSize;
            /* Pipe the new buffer content to libmad's stream decoder
                     * facility.
            */
            mad_stream_buffer(&Stream,MadInputBuffer,ReadSize+Remaining);
            Stream.error=(enum  mad_error)0;
        }

        /* decode a frame from the mp3 stream data */
        if(mad_frame_decode(&Frame,&Stream)) {
            if(MAD_RECOVERABLE(Stream.error)) {
                /*if(Stream.error!=MAD_ERROR_LOSTSYNC ||
                   Stream.this_frame!=GuardPtr)
                {
                }*/
                continue;
            } else {
                /* the current frame is not full, need to read the remaining part */
                if(Stream.error==MAD_ERROR_BUFLEN) {
                    continue;
                } else {
                    printf("Something error!!\n");

                    /* play the next file */
                    audioInfo.mp3FileEndFlag = 1;
                    goto stop;
                }
            }
        }

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

        //
        // decode finished, try to copy pcm data to audio buffer
        //

        if(audioInfo.mp3Playing) {
            //if next buffer is still full (playing), wait until it's empty
            if(aPCMBuffer_Full[u8PCMBufferTargetIdx] == 1)
                while(aPCMBuffer_Full[u8PCMBufferTargetIdx]);
        } else {

            if((aPCMBuffer_Full[0] == 1) && (aPCMBuffer_Full[1] == 1 )) {       //all buffers are full, wait
                StartPlay();
            }
        }

        for(i=0; i<(int)Synth.pcm.length; i++) {
            /* Get the left/right samples */
            sampleL = Synth.pcm.samples[0][i];
            sampleR = Synth.pcm.samples[1][i];

            /* Fill PCM data to I2S(PDMA) buffer */
            aPCMBuffer[u8PCMBufferTargetIdx][pcmbuf_idx++] = sampleR | (sampleL << 16);

            /* Need change buffer ? */
            if(pcmbuf_idx == PCM_BUFFER_SIZE) {
                aPCMBuffer_Full[u8PCMBufferTargetIdx] = 1;      //set full flag
                u8PCMBufferTargetIdx ^= 1;

                pcmbuf_idx = 0;
//               printf("change to ==>%d ..\n", u8PCMBufferTargetIdx);
                /* if next buffer is still full (playing), wait until it's empty */
                if((aPCMBuffer_Full[u8PCMBufferTargetIdx] == 1) && (audioInfo.mp3Playing))
                    while(aPCMBuffer_Full[u8PCMBufferTargetIdx]);
            }
        }
    }

stop:

    printf("Exit MP3\r\n");

    mad_synth_finish(&Synth);
    mad_frame_finish(&Frame);
    mad_stream_finish(&Stream);

    f_close(&mp3FileObject);
    StopPlay();
}
/*
 * NAME:  scan_header()
 * DESCRIPTION: read the initial frame(s) to get stream statistics
 */
static
int scan_header(CPs_InStream* pInStream, struct mad_header *header, struct xing *xing)
{

	struct mad_stream stream;
	
	struct mad_frame frame;
	unsigned char buffer[8192];
	unsigned int buflen = 0;
	int count = 0, result = 0;
	
	mad_stream_init(&stream);
	mad_frame_init(&frame);
	
	if (xing)
		xing->flags = 0;
		
	while (1)
	{
		if (buflen < sizeof(buffer))
		{
			// DWORD bytes;
			unsigned int bytes;
			
			if (pInStream->Read(pInStream, buffer + buflen, sizeof(buffer) - buflen, &bytes) == FALSE
					|| bytes == 0)
			{
				result = -1;
				break;
			}
			
			buflen += bytes;
		}
		
		mad_stream_buffer(&stream, buffer, buflen);
		
		while (1)
		{
			if (mad_frame_decode(&frame, &stream) == -1)
			{
				if (!MAD_RECOVERABLE(stream.error))
					break;
					
				continue;
			}
			
			if (count++ ||
					(xing && parse_xing(xing, stream.anc_ptr,
										stream.anc_bitlen) == 0))
				break;
		}
		
		if (count || stream.error != MAD_ERROR_BUFLEN)
			break;
			
		memmove(buffer, stream.next_frame,
				buflen = &buffer[buflen] - stream.next_frame);
	}
	
	if (count)
	{
		if (header)
			*header = frame.header;
	}
	
	else
		result = -1;
		
	mad_frame_finish(&frame);
	
	mad_stream_finish(&stream);
	
	return result;
}
Exemple #14
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;
}
void CodecMpeg1::process(const QByteArray &data,bool is_last)
{
#ifdef HAVE_LIBMAD
  float pcm[32768*4];
  int frame_offset=0;
  int err_count=0;

  mpeg1_mpeg.append(data);
  mad_stream_buffer(&mpeg1_mad_stream,(const unsigned char *)mpeg1_mpeg.data(),
		    mpeg1_mpeg.length());
  do {
    while(mad_frame_decode(&mpeg1_mad_frame,&mpeg1_mad_stream)==0) {  
      mad_synth_frame(&mpeg1_mad_synth,&mpeg1_mad_frame);
      for(int i=0;i<mpeg1_mad_synth.pcm.length;i++) {
	for(int j=0;j<mpeg1_mad_synth.pcm.channels;j++) {
	  pcm[frame_offset+i*mpeg1_mad_synth.pcm.channels+j]=
	    (float)mad_f_todouble(mpeg1_mad_synth.pcm.samples[j][i]);
	}
      }
      frame_offset+=(mpeg1_mad_synth.pcm.length*mpeg1_mad_synth.pcm.channels);
    }
    if(MAD_RECOVERABLE(mpeg1_mad_stream.error)!=0) {
      if(err_count++>10) {
	Reset();
	break;
      }
    }
  } while(mpeg1_mad_stream.error!=MAD_ERROR_BUFLEN);

  if(mpeg1_mad_stream.error==MAD_ERROR_BUFLEN) {
    if(frame_offset>0) {
      mpeg1_mad_header=mpeg1_mad_frame.header;
      if(!isFramed()) {
	int channels=2;
	if(mpeg1_mad_frame.header.mode==MAD_MODE_SINGLE_CHANNEL) {
	  channels=1;
	}
	setFramed(channels,mpeg1_mad_frame.header.samplerate,
		  mpeg1_mad_frame.header.bitrate/1000);
      }
      else {
	writePcm(pcm,frame_offset/channels(),is_last);
      }
    }
    mpeg1_mpeg=
      mpeg1_mpeg.right(mpeg1_mad_stream.bufend-mpeg1_mad_stream.next_frame);
  }
  if(is_last) {
    frame_offset=0;
    mpeg1_mpeg.append(0,MAD_BUFFER_GUARD);
    mad_stream_buffer(&mpeg1_mad_stream,(const unsigned char *)mpeg1_mpeg.data(),
		      mpeg1_mpeg.length());
    do {
      while(mad_frame_decode(&mpeg1_mad_frame,&mpeg1_mad_stream)==0) {  
	mad_synth_frame(&mpeg1_mad_synth,&mpeg1_mad_frame);
	for(int i=0;i<mpeg1_mad_synth.pcm.length;i++) {
	  for(int j=0;j<mpeg1_mad_synth.pcm.channels;j++) {
	    pcm[frame_offset+i*mpeg1_mad_synth.pcm.channels+j]=
	      (float)mad_f_todouble(mpeg1_mad_synth.pcm.samples[j][i]);
	  }
	}
	frame_offset+=(mpeg1_mad_synth.pcm.length*mpeg1_mad_synth.pcm.channels);
      }
      if(MAD_RECOVERABLE(mpeg1_mad_stream.error)!=0) {
	if(err_count++>10) {
	  Reset();
	  break;
	}
      }
    } while(mpeg1_mad_stream.error!=MAD_ERROR_BUFLEN);
    writePcm(pcm,frame_offset/channels(),is_last);
  }
#endif  // HAVE_LIBMAD
}
Exemple #16
0
/* 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);
int Mp3Decoder::Read(u8 * buffer, int buffer_size, int pos UNUSED)
{
    if(!file_fd)
        return -1;

    if(Format == VOICE_STEREO_16BIT)
        buffer_size &= ~0x0003;
    else
        buffer_size &= ~0x0001;

    u8 * write_pos = buffer;
    u8 * write_end = buffer+buffer_size;

    while(1)
    {
        while(SynthPos < Synth.pcm.length)
        {
            if(write_pos >= write_end)
                return write_pos-buffer;

            *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[0][SynthPos]);
            write_pos += 2;

            if(MAD_NCHANNELS(&Frame.header) == 2)
            {
                *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[1][SynthPos]);
                write_pos += 2;
            }
            SynthPos++;
        }

        if(Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN)
        {
            u8 * ReadStart = ReadBuffer;
            int ReadSize = SoundBlockSize*SoundBlocks;
            int Remaining = 0;

            if(Stream.next_frame != NULL)
            {
                Remaining = Stream.bufend - Stream.next_frame;
                memmove(ReadBuffer, Stream.next_frame, Remaining);
                ReadStart += Remaining;
                ReadSize -= Remaining;
            }

            ReadSize = file_fd->read(ReadStart, ReadSize);
            if(ReadSize <= 0)
            {
                GuardPtr = ReadStart;
                memset(GuardPtr, 0, MAD_BUFFER_GUARD);
                ReadSize = MAD_BUFFER_GUARD;
            }

            CurPos += ReadSize;
            mad_stream_buffer(&Stream, ReadBuffer, Remaining+ReadSize);
        }

        if(mad_frame_decode(&Frame,&Stream))
        {
            if(MAD_RECOVERABLE(Stream.error))
            {
                if(Stream.error != MAD_ERROR_LOSTSYNC || !GuardPtr)
                    continue;
            }
            else
            {
                if(Stream.error != MAD_ERROR_BUFLEN)
                    return -1;
                else if(Stream.error == MAD_ERROR_BUFLEN && GuardPtr)
                    return -1;
            }
        }

        mad_timer_add(&Timer,Frame.header.duration);
        mad_synth_frame(&Synth,&Frame);
        SynthPos = 0;
    }
    return 0;
}
Exemple #18
0
int
mp3_mad_stream_frame (mp3_info_t *info) {
    int eof = 0;
    while (!eof && (info->mad_stream.buffer == NULL || info->buffer.decode_remaining <= 0)) {
        // read more MPEG data if needed
        if(info->mad_stream.buffer==NULL || info->mad_stream.error==MAD_ERROR_BUFLEN) {
            // copy part of last frame to beginning
            if (info->mad_stream.next_frame && info->mad_stream.bufend <= info->mad_stream.next_frame) {
                eof = 1;
                break;
            }
            if (info->mad_stream.next_frame != NULL) {
                info->buffer.remaining = info->mad_stream.bufend - info->mad_stream.next_frame;
                memmove (info->buffer.input, info->mad_stream.next_frame, info->buffer.remaining);
            }
            int size = READBUFFER - info->buffer.remaining;
            int bytesread = 0;
            uint8_t *bytes = info->buffer.input + info->buffer.remaining;
            bytesread = deadbeef->fread (bytes, 1, size, info->buffer.file);
            if (!bytesread) {
                // add guard
                eof = 1;
                memset (bytes, 0, 8);
                bytesread = 8;
            }
            if (bytesread < size) {
                // end of file
                size -= bytesread;
                bytes += bytesread;
            }
            bytesread += info->buffer.remaining;
            mad_stream_buffer(&info->mad_stream,info->buffer.input,bytesread);
            if (info->mad_stream.buffer==NULL) {
                // check sync bits
                if (bytes[0] != 0xff || (bytes[1]&(3<<5)) != (3<<5)) {
                    trace ("mp3: read didn't start at frame boundary!\ncmp3_scan_stream is broken\n");
                }
                else {
                    trace ("mp3: streambuffer=NULL\n");
                }
            }
        }
        info->mad_stream.error=0;

        // decode next frame
        if(mad_frame_decode(&info->mad_frame, &info->mad_stream))
        {
            if(MAD_RECOVERABLE(info->mad_stream.error))
            {
                if(info->mad_stream.error!=MAD_ERROR_LOSTSYNC) {
                    //                    printf ("mp3: recoverable frame level error (%s)\n", MadErrorString(&info->stream));
                }
                if (info->buffer.lead_in_frames > 0) {
                    info->buffer.lead_in_frames--;
                }
                continue;
            }
            else {
                if(info->mad_stream.error==MAD_ERROR_BUFLEN) {
                    //                    printf ("mp3: recoverable frame level error (%s)\n", MadErrorString(&info->stream));
                    continue;
                }
                else
                {
                    //                    printf ("mp3: unrecoverable frame level error (%s).\n", MadErrorString(&info->stream));
                    return -1; // fatal error
                }
            }
        }
        mad_synth_frame(&info->mad_synth,&info->mad_frame);
        if (info->buffer.lead_in_frames > 0) {
            info->buffer.lead_in_frames--;
            info->buffer.decode_remaining = 0;
            continue;
        }

        info->info.fmt.samplerate = info->mad_frame.header.samplerate;

        // synthesize single frame
        info->buffer.decode_remaining = info->mad_synth.pcm.length;
        deadbeef->streamer_set_bitrate (info->mad_frame.header.bitrate/1000);
        break;
    }
    
    return eof;
}
Exemple #19
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;
}
Exemple #20
0
static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {

  mad_decoder_t *this = (mad_decoder_t *) this_gen;
  int bytes_in_buffer_at_pts;

  lprintf ("decode data, size: %d, decoder_flags: %d\n", buf->size, buf->decoder_flags);

  if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) {
    xprintf (this->xstream->xine, XINE_VERBOSITY_DEBUG,
	     "libmad: ALERT input buffer too small (%d bytes, %d avail)!\n",
	     buf->size, INPUT_BUF_SIZE-this->bytes_in_buffer);
    buf->size = INPUT_BUF_SIZE-this->bytes_in_buffer;
  }

  if ((buf->decoder_flags & BUF_FLAG_HEADER) == 0) {

    /* reset decoder on leaving preview mode */
    if ((buf->decoder_flags & BUF_FLAG_PREVIEW) == 0) {
      if (this->preview_mode) {
	mad_reset (this_gen);
      }
    } else {
      this->preview_mode = 1;
    }

    bytes_in_buffer_at_pts = this->bytes_in_buffer;

    xine_fast_memcpy (&this->buffer[this->bytes_in_buffer],
                        buf->content, buf->size);
    this->bytes_in_buffer += buf->size;

    /*
    printf ("libmad: decode data - doing it\n");
    */

    mad_stream_buffer (&this->stream, this->buffer,
		       this->bytes_in_buffer);

    if (this->bytes_in_buffer < MAD_MIN_SIZE && buf->pts == 0)
      return;

    if (!this->needs_more_data) {
      this->pts = buf->pts;
      if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) {
        this->start_padding = buf->decoder_info[1];
        this->end_padding = buf->decoder_info[2];
      } else {
        this->start_padding = 0;
        this->end_padding = 0;
      }
    }

    while (1) {

      if (mad_frame_decode (&this->frame, &this->stream) != 0) {

	if (this->stream.next_frame) {
	  int num_bytes =
	    this->buffer + this->bytes_in_buffer - this->stream.next_frame;

	  /* printf("libmad: MAD_ERROR_BUFLEN\n"); */

	  memmove(this->buffer, this->stream.next_frame, num_bytes);
	  this->bytes_in_buffer = num_bytes;
	}

	switch (this->stream.error) {

	case MAD_ERROR_BUFLEN:
	  /* libmad wants more data */
	  this->needs_more_data = 1;
	  return;

	default:
	  lprintf ("error 0x%04X, mad_stream_buffer %d bytes\n", this->stream.error, this->bytes_in_buffer);
	  mad_stream_buffer (&this->stream, this->buffer,
			     this->bytes_in_buffer);
	}

      } else {
	int mode = (this->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? AO_CAP_MODE_MONO : AO_CAP_MODE_STEREO;

	if (!this->output_open
	    || (this->output_sampling_rate != this->frame.header.samplerate)
	    || (this->output_mode != mode)) {

	  lprintf ("audio sample rate %d mode %08x\n", this->frame.header.samplerate, mode);

          /* the mpeg audio demuxer can set audio bitrate */
          if (! _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE)) {
            _x_stream_info_set(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE,
                               this->frame.header.bitrate);
          }

          /* the mpeg audio demuxer can set this meta info */
          if (! _x_meta_info_get(this->xstream, XINE_META_INFO_AUDIOCODEC)) {
            switch (this->frame.header.layer) {
            case MAD_LAYER_I:
              _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC,
                "MPEG audio layer 1 (lib: MAD)");
              break;
            case MAD_LAYER_II:
              _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC,
                "MPEG audio layer 2 (lib: MAD)");
              break;
            case MAD_LAYER_III:
              _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC,
                "MPEG audio layer 3 (lib: MAD)");
              break;
            default:
              _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC,
                "MPEG audio (lib: MAD)");
            }
          }

	  if (this->output_open) {
	    this->xstream->audio_out->close (this->xstream->audio_out, this->xstream);
	    this->output_open = 0;
          }
          if (!this->output_open) {
	    this->output_open = (this->xstream->audio_out->open) (this->xstream->audio_out,
				   this->xstream, 16,
				   this->frame.header.samplerate,
			           mode) ;
          }
          if (!this->output_open) {
            return;
          }
	  this->output_sampling_rate = this->frame.header.samplerate;
	  this->output_mode = mode;
	}

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

	if ( (buf->decoder_flags & BUF_FLAG_PREVIEW) == 0 ) {

	  unsigned int         nchannels, nsamples;
	  mad_fixed_t const   *left_ch, *right_ch;
	  struct mad_pcm      *pcm = &this->synth.pcm;
	  audio_buffer_t      *audio_buffer;
	  uint16_t            *output;
          int                  bitrate;
          int                  pts_offset;

	  audio_buffer = this->xstream->audio_out->get_buffer (this->xstream->audio_out);
	  output = audio_buffer->mem;

	  nchannels = pcm->channels;
	  nsamples  = pcm->length;
	  left_ch   = pcm->samples[0];
	  right_ch  = pcm->samples[1];

	  /* padding */
	  if (this->start_padding || this->end_padding) {
	    /* check padding validity */
	    if (nsamples < (this->start_padding + this->end_padding)) {
	      lprintf("invalid padding data");
	      this->start_padding = 0;
	      this->end_padding = 0;
	    }
	    lprintf("nsamples=%d, start_padding=%d, end_padding=%d\n",
	            nsamples, this->start_padding, this->end_padding);
	    nsamples -= this->start_padding + this->end_padding;
	    left_ch  += this->start_padding;
	    right_ch += this->start_padding;
	  }
	  audio_buffer->num_frames = nsamples;
	  audio_buffer->vpts       = this->pts;

	  while (nsamples--) {
	    /* output sample(s) in 16-bit signed little-endian PCM */

	    *output++ = scale(*left_ch++);

	    if (nchannels == 2)
	      *output++ = scale(*right_ch++);

	  }

	  audio_buffer->num_frames = pcm->length;

          /* pts computing */
          if (this->frame.header.bitrate > 0) {
            bitrate = this->frame.header.bitrate;
          } else {
            bitrate = _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE);
            lprintf("offset %d bps\n", bitrate);
          }
          audio_buffer->vpts = buf->pts;
          if (audio_buffer->vpts && (bitrate > 0)) {
            pts_offset = (bytes_in_buffer_at_pts * 8 * 90) / (bitrate / 1000);
            lprintf("pts: %"PRId64", offset: %d pts, %d bytes\n", buf->pts, pts_offset, bytes_in_buffer_at_pts);
            if (audio_buffer->vpts < pts_offset)
              pts_offset = audio_buffer->vpts;
            audio_buffer->vpts -= pts_offset;
          }

	  this->xstream->audio_out->put_buffer (this->xstream->audio_out, audio_buffer, this->xstream);

	  this->pts = buf->pts;
	  buf->pts = 0;
	  if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) {
	    this->start_padding = buf->decoder_info[1];
	    this->end_padding = buf->decoder_info[2];
	    buf->decoder_info[1] = 0;
	    buf->decoder_info[2] = 0;
	  } else {
	    this->start_padding = 0;
	    this->end_padding = 0;
	  }
	}
	lprintf ("decode worked\n");
      }
    }
  }
}
Exemple #21
0
/* Reads the next frame from the file.  Returns true on success or
   false on failure. */
static int
read_next_frame(mad_data *mp3_mad) {
  if (mp3_mad->stream.buffer == NULL ||
      mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
    size_t read_size;
    size_t remaining;
    unsigned char *read_start;

    /* There might be some bytes in the buffer left over from last
       time.  If so, move them down and read more bytes following
       them. */
    if (mp3_mad->stream.next_frame != NULL) {
      remaining = mp3_mad->stream.bufend - mp3_mad->stream.next_frame;
      memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
      read_start = mp3_mad->input_buffer + remaining;
      read_size = MAD_INPUT_BUFFER_SIZE - remaining;

    } else {
      read_size = MAD_INPUT_BUFFER_SIZE;
      read_start = mp3_mad->input_buffer;
      remaining = 0;
    }

    /* Now read additional bytes from the input file. */
    read_size = SDL_RWread(mp3_mad->src, read_start, 1, read_size);

    if (read_size <= 0) {
      if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
        if (read_size == 0) {
          mp3_mad->status |= MS_input_eof;
        } else {
          mp3_mad->status |= MS_input_error;
        }

        /* At the end of the file, we must stuff MAD_BUFFER_GUARD
           number of 0 bytes. */
        SDL_memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
        read_size += MAD_BUFFER_GUARD;
      }
    }

    /* Now feed those bytes into the libmad stream. */
    mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
                      read_size + remaining);
    mp3_mad->stream.error = MAD_ERROR_NONE;
  }

  /* Now ask libmad to extract a frame from the data we just put in
     its buffer. */
  if (mad_frame_decode(&mp3_mad->frame, &mp3_mad->stream)) {
    if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
      return 0;

    } else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
      return 0;

    } else {
      mp3_mad->status |= MS_decode_error;
      return 0;
    }
  }

  mp3_mad->frames_read++;
  mad_timer_add(&mp3_mad->next_frame_start, mp3_mad->frame.header.duration);

  return 1;
}
Exemple #22
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;
            }
        }
    }
}
Exemple #23
0
void XMp3Decomp::Decompress(XS16* dstWord, XS32 nSamples) 
{

    long            bytesCleared;
    XS32             nBytes  = nSamples * snd->BytesPerBlock();
    XS8              *dstByte = (XS8 *) dstWord;

//    XBOOL            seeking = (!dstWord) ? (true) : false;

	bytesCleared = GetBufferedData(dstByte, nBytes);

	if (!isInitMad())
	{
		if (dstByte)
		{
			memset(dstByte, 0x00, nBytes);
		}
		goto exit_gracefully;
	}
	else
	{
		nBytes -= bytesCleared;

        // dst byte can be zero during seeking
        if (dstByte)
            dstByte += bytesCleared;
	}

	if (m_firstBuf)	// first enter
	{
		// read head. and give data
		bool b = fillBufferMad();
		assert(b);
		m_firstBuf = false;
	}

    // check first if there is any buffered data
    if (bytesCleared == nBytes)
        goto exit_gracefully;
  
	mad_error madError;

	
	while(nBytes > 0)
	{
		int success = mad_frame_decode(&Frame, &Stream);
		madError = Stream.error;
		if (success == 0)
		{
			// do success things.
			mad_synth_frame(&Synth,&Frame);

			struct mad_pcm *pcm = &(Synth.pcm);

			int nchannels = pcm->channels;
//			int nsamples  = pcm->length;

			assert(Synth.pcm.length * nchannels * 2 <= kBufSize);
			assert(Synth.pcm.length > 0);

			XU8* p = pcmBuf;

			for (int i = 0; i < Synth.pcm.length; i++)
			{
				signed int Sample = scale(Synth.pcm.samples[0][i]);
				*p++ = Sample & 0xff;
				*p++ = (Sample >> 8) & 0xff;
				if (nchannels == 2)
				{
					Sample = scale(Synth.pcm.samples[0][i]);
					*p++ = Sample & 0xff;
					*p++ = (Sample >> 8) & 0xff;
				}
			}

			bufLength = Synth.pcm.length * nchannels * 2;

			bytesCleared = GetBufferedData(dstByte, nBytes);
			nBytes -= bytesCleared;
			if (dstByte)
			{
				dstByte += bytesCleared;
            }
		}
Exemple #24
0
static
int run_sync(struct mad_decoder *decoder)
{
  enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *);
  void *error_data;
  int bad_last_frame = 0;
  struct mad_stream *stream;
  struct mad_frame *frame;
  struct mad_synth *synth;
  int result = 0;

  if (decoder->input_func == 0)
    return 0;

  if (decoder->error_func) {
    error_func = decoder->error_func;
    error_data = decoder->cb_data;
  }
  else {
    error_func = error_default;
    error_data = &bad_last_frame;
  }

  stream = &decoder->sync->stream;
  frame  = &decoder->sync->frame;
  synth  = &decoder->sync->synth;

  mad_stream_init(stream);
  mad_frame_init(frame);
  mad_synth_init(synth);

  mad_stream_options(stream, decoder->options);

  do {
    switch (decoder->input_func(decoder->cb_data, stream)) {
    case MAD_FLOW_STOP:
      goto done;
    case MAD_FLOW_BREAK:
      goto fail;
    case MAD_FLOW_IGNORE:
      continue;
    case MAD_FLOW_CONTINUE:
      break;
    }

    while (1) {

      if (decoder->header_func) {
	if (mad_header_decode(&frame->header, stream) == -1) {
	  if (!MAD_RECOVERABLE(stream->error))
	    break;

	  switch (error_func(error_data, stream, frame)) {
	  case MAD_FLOW_STOP:
	    goto done;
	  case MAD_FLOW_BREAK:
	    goto fail;
	  case MAD_FLOW_IGNORE:
	  case MAD_FLOW_CONTINUE:
	  default:
	    continue;
	  }
	}

	switch (decoder->header_func(decoder->cb_data, &frame->header)) {
	case MAD_FLOW_STOP:
	  goto done;
	case MAD_FLOW_BREAK:
	  goto fail;
	case MAD_FLOW_IGNORE:
	  continue;
	case MAD_FLOW_CONTINUE:
	  break;
	}
      }

      if (mad_frame_decode(frame, stream) == -1) {
	if (!MAD_RECOVERABLE(stream->error))
	  break;

	switch (error_func(error_data, stream, frame)) {
	case MAD_FLOW_STOP:
	  goto done;
	case MAD_FLOW_BREAK:
	  goto fail;
	case MAD_FLOW_IGNORE:
	  break;
	case MAD_FLOW_CONTINUE:
	default:
	  continue;
	}
      }
      else
	bad_last_frame = 0;

      if (decoder->filter_func) {
	switch (decoder->filter_func(decoder->cb_data, stream, frame)) {
	case MAD_FLOW_STOP:
	  goto done;
	case MAD_FLOW_BREAK:
	  goto fail;
	case MAD_FLOW_IGNORE:
	  continue;
	case MAD_FLOW_CONTINUE:
	  break;
	}
      }

      mad_synth_frame(synth, frame);

      if (decoder->output_func) {
	switch (decoder->output_func(decoder->cb_data,
				     &frame->header, &synth->pcm)) {
	case MAD_FLOW_STOP:
	  goto done;
	case MAD_FLOW_BREAK:
	  goto fail;
	case MAD_FLOW_IGNORE:
	case MAD_FLOW_CONTINUE:
	  break;
	}
      }
    }
  }
  while (stream->error == MAD_ERROR_BUFLEN);

 fail:
  result = -1;

 done:
  mad_synth_finish(synth);
  mad_frame_finish(frame);
  mad_stream_finish(stream);

  return result;
}
Exemple #25
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;
}
Exemple #26
0
static int
MP3Callback_22k(void *_buf2, unsigned int numSamples, void *pdata)
{
  int i;
  short *_buf = (short *)_buf2;
  unsigned long samplesOut = 0;

  numSamples /= 2;
  //  Playing , so mix up a buffer
  if (samplesInOutput > 0) 
  {
    if (samplesInOutput > numSamples) {
      write22k_buf((short *) _buf, (short *) OutputBuffer, numSamples * 2);
      samplesOut = numSamples;
      samplesInOutput -= numSamples;
    } else {
      write22k_buf((short *) _buf, (short *) OutputBuffer, samplesInOutput * 2);
      samplesOut = samplesInOutput;
      samplesInOutput = 0;
    }
  }
  while (samplesOut < numSamples) 
  {
    if (Stream.buffer == NULL) {
      Stream.error = 0;
      mad_stream_buffer(&Stream, mp3_data, size);
    }
    if (Stream.error == MAD_ERROR_BUFLEN) {
      Stream.error = 0;
      if (isRepeatMode) {
        MP3_Restart();
        mad_stream_buffer(&Stream, mp3_data, size);
        samplesInOutput = 0;
      } else {
        MP3_Stop();
        return 0;
      }
    }

    if (mad_frame_decode(&Frame, &Stream)) {
      if (MAD_RECOVERABLE(Stream.error)) {
        return 0;
      } else
      if (Stream.error == MAD_ERROR_BUFLEN) {
        if (! isRepeatMode) {
          MP3_Stop();
          return 0;
        }
      } else {
        MP3_Stop();
      }
    }

    FrameCount++;
    mad_timer_add(&Timer, Frame.header.duration);
    mad_synth_frame(&Synth, &Frame);

    for (i = 0; i < Synth.pcm.length; i++) {
      signed short Sample;
      if (samplesOut < numSamples) {
        /* Left channel */
        Sample = MadFixedToSshort(Synth.pcm.samples[0][i]);
        _buf[((samplesOut * 2) * 2)    ] = Sample;
        _buf[((samplesOut * 2) * 2) + 1] = 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]);
        }
        _buf[(((samplesOut * 2) + 1) * 2)    ] = Sample;
        _buf[(((samplesOut * 2) + 1) * 2) + 1] = Sample;
        samplesOut++;
      } else {
        Sample = MadFixedToSshort(Synth.pcm.samples[0][i]);
        OutputBuffer[samplesInOutput * 2] = Sample;
        if (MAD_NCHANNELS(&Frame.header) == 2) {
          Sample = MadFixedToSshort(Synth.pcm.samples[1][i]);
        }
        OutputBuffer[samplesInOutput * 2 + 1] = Sample;
        samplesInOutput++;
      }
    }
  } 
  
  return isPlaying;
}
Exemple #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;
        }
    }
}
Exemple #28
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;
}
Exemple #29
0
/**
 * MP3音乐播放回调函数,
 * 负责将解码数据填充声音缓存区
 *
 * @note 声音缓存区的格式为双声道,16位低字序
 *
 * @param buf 声音缓冲区指针
 * @param reqn 缓冲区帧大小
 * @param pdata 用户数据,无用
 */
static int mp3_audiocallback(void *buf, unsigned int reqn, void *pdata)
{
	int avail_frame;
	int snd_buf_frame_size = (int) reqn;
	int ret;
	double incr;
	signed short *audio_buf = buf;
	unsigned i;
	uint16_t *output;

	UNUSED(pdata);

	if (g_status != ST_PLAYING) {
		if (handle_seek() == -1) {
			__end();
			return -1;
		}

		xAudioClearSndBuf(buf, snd_buf_frame_size);
		xrKernelDelayThread(100000);
		return 0;
	}

	while (snd_buf_frame_size > 0) {
		avail_frame = g_buff_frame_size - g_buff_frame_start;

		if (avail_frame >= snd_buf_frame_size) {
			send_to_sndbuf(audio_buf,
						   &g_buff[g_buff_frame_start * 2],
						   snd_buf_frame_size, 2);
			g_buff_frame_start += snd_buf_frame_size;
			audio_buf += snd_buf_frame_size * 2;
			snd_buf_frame_size = 0;
		} else {
			send_to_sndbuf(audio_buf,
						   &g_buff[g_buff_frame_start * 2], avail_frame, 2);
			snd_buf_frame_size -= avail_frame;
			audio_buf += avail_frame * 2;

			if (stream.buffer == NULL || stream.error == MAD_ERROR_BUFLEN) {
				size_t read_size, remaining = 0;
				uint8_t *read_start;
				int bufsize;

				if (stream.next_frame != NULL) {
					remaining = stream.bufend - stream.next_frame;
					memmove(g_input_buff, stream.next_frame, remaining);
					read_start = g_input_buff + remaining;
					read_size = BUFF_SIZE - remaining;
				} else {
					read_size = BUFF_SIZE;
					read_start = g_input_buff;
					remaining = 0;
				}

				if (mp3_data.use_buffer)
					bufsize =
						buffered_reader_read(mp3_data.r, read_start, read_size);
				else
					bufsize = xrIoRead(mp3_data.fd, read_start, read_size);

				if (bufsize <= 0) {
					__end();
					return -1;
				}
				if (bufsize < read_size) {
					uint8_t *guard = read_start + read_size;

					memset(guard, 0, MAD_BUFFER_GUARD);
					read_size += MAD_BUFFER_GUARD;
				}
				mad_stream_buffer(&stream, g_input_buff, read_size + remaining);
				stream.error = 0;
			}

			ret = mad_frame_decode(&frame, &stream);

			if (ret == -1) {
				if (MAD_RECOVERABLE(stream.error)
					|| stream.error == MAD_ERROR_BUFLEN) {
					if (stream.error == MAD_ERROR_LOSTSYNC) {
						long tagsize = id3_tag_query(stream.this_frame,
													 stream.bufend -
													 stream.this_frame);

						if (tagsize > 0) {
							mad_stream_skip(&stream, tagsize);
						}

						if (mad_header_decode(&frame.header, &stream) == -1) {
							if (stream.error != MAD_ERROR_BUFLEN) {
								if (!MAD_RECOVERABLE(stream.error)) {
									__end();
									return -1;
								}
							}
						} else {
							stream.error = MAD_ERROR_NONE;
						}
					}

					g_buff_frame_size = 0;
					g_buff_frame_start = 0;
					continue;
				} else {
					__end();
					return -1;
				}
			}

			output = &g_buff[0];

			if (stream.error != MAD_ERROR_NONE) {
				continue;
			}

			mad_synth_frame(&synth, &frame);
			for (i = 0; i < synth.pcm.length; i++) {
				signed short sample;

				if (MAD_NCHANNELS(&frame.header) == 2) {
					/* Left channel */
					sample = MadFixedToSshort(synth.pcm.samples[0][i]);
					*(output++) = sample;
					sample = MadFixedToSshort(synth.pcm.samples[1][i]);
					*(output++) = sample;
				} else {
					sample = MadFixedToSshort(synth.pcm.samples[0][i]);
					*(output++) = sample;
					*(output++) = sample;
				}
			}

			g_buff_frame_size = synth.pcm.length;
			g_buff_frame_start = 0;
			incr = frame.header.duration.seconds;
			incr +=
				mad_timer_fraction(frame.header.duration,
								   MAD_UNITS_MILLISECONDS) / 1000.0;
			g_play_time += incr;
			add_bitrate(&g_inst_br, frame.header.bitrate, incr);
		}
	}

	return 0;
}
Exemple #30
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;
  }