Esempio n. 1
0
static
	enum mad_flow input(void *data,
struct mad_stream *stream)
{
	struct buffer *buffer = data;

	if (!buffer->length)
		return MAD_FLOW_STOP;

	mad_stream_buffer(stream, buffer->start, buffer->length);

	buffer->length = 0;

	return MAD_FLOW_CONTINUE;
}
Esempio n. 2
0
bool XMp3Decomp::fillBufferMad()
{
	unsigned char	*ReadStart;
	int acceptCount;

	//if(snd->dataLen<srcIndex)
	//	int v=0;
	assert(snd->dataLen >= srcIndex);
	int numDataLeft = snd->dataLen - srcIndex;
	if (numDataLeft == 0)
	{
		return false;
	}

	if (Stream.next_frame != XNULL)
	{
//		srcIndex -= Stream.bufend-Stream.next_frame;
//		assert(srcIndex >= 0);
		int remaining = Stream.bufend - Stream.next_frame;
		memmove(tempBuf, Stream.next_frame, remaining);
		assert(remaining < kBufSize);
		acceptCount = min(numDataLeft + remaining, kBufSize);
		ReadStart = tempBuf;
		int numFromData = acceptCount - remaining;
		assert(numFromData > 0);
		memcpy(tempBuf + remaining, src + srcIndex, numFromData);
		srcIndex += numFromData;
	}
	else
	{
		acceptCount = min(numDataLeft, kBufSize);
		ReadStart = src + srcIndex;
		srcIndex += acceptCount;
	}
	mad_stream_buffer(&Stream, ReadStart, acceptCount);
////	ReadStart = src + srcIndex;
//
//	int acceptCount = min(acceptCount, kBufSize);
//	assert(acceptCount >= 0);
////	assert(acceptCount >= Stream.bufend - Stream.next_frame);
//
//	if (acceptCount == 0)
//		return false;
////	mad_stream_buffer(&Stream, src, 
//	mad_stream_buffer(&Stream,ReadStart,acceptCount);
////	srcIndex += acceptCount;
	return true;
}
Esempio n. 3
0
File: mp3.c Progetto: uniite/imd
static enum mad_flow audeng_mad_input (void *data, struct mad_stream *stream) {
	while (audeng_mode == paused) {}
	switch (audeng_mode) {
		case seeking:
			audeng_song_pos = audeng_seek_pos;
			audeng_mode = playing;
		case playing:
			audeng_mp3_bufferframes();
			mad_stream_buffer(stream, audeng_buffer, audeng_buffer_sz);
			return MAD_FLOW_CONTINUE;
		case stopped:
			/* Just so it's visible through all the clutter */
			return MAD_FLOW_STOP;
		default:
			return MAD_FLOW_CONTINUE;
	}
}
Esempio n. 4
0
static
enum mad_flow input(void *data,
		    struct mad_stream *stream)
{
//  struct buffer *buffer = data;

  if (done) return MAD_FLOW_STOP; 

  printf ("stream.error %x\n", stream->error);

  #define SIZE 64000
  //char *buf = malloc (SIZE+8);
  static char buf1[SIZE + 8];
  static char buf2[SIZE + 8];

  static char *buf = buf1;

  memset (buf, 0, SIZE + 8);

  int Remaining;
  char * ReadStart = buf;
  int ReadSize = SIZE;
  if (stream->error == MAD_ERROR_BUFLEN)
  {

    Remaining = stream->bufend - stream->next_frame;
    memcpy (buf, stream->next_frame, Remaining);
    ReadStart=buf + Remaining;
    ReadSize = SIZE - Remaining;

  }

//  if (!buffer->length)
 //   return MAD_FLOW_STOP;

  if (read (in, ReadStart , ReadSize) != ReadSize)
    done = 1;

  mad_stream_buffer(stream, buf, SIZE);

  if (buf == buf1) buf = buf2; else buf = buf1;


  return MAD_FLOW_CONTINUE;
}
static
enum mad_flow mad_input(void *data,
		    struct mad_stream *stream)
{
	slimaudio_t *audio = (slimaudio_t *) data;
	int remainder, data_len;
	slimaudio_buffer_status ok;

	pthread_mutex_lock(&audio->decoder_mutex);

	VDEBUGF("decode_input state=%i\n", audio->decoder_state);
	if (audio->decoder_state != STREAM_PLAYING) {
		pthread_mutex_unlock(&audio->decoder_mutex);
		DEBUGF("mad: decode_state != STREAM_PLAYING\n");
		return MAD_FLOW_STOP;
	}

	pthread_mutex_unlock(&audio->decoder_mutex);

	if (audio->decoder_end_of_stream)
	{
		DEBUGF("mad: audio->decoder_end_of_stream == TRUE\n");
		return MAD_FLOW_STOP;
	}

	/* keep partial frame from last decode ... */
	remainder = stream->bufend - stream->next_frame;

	memcpy (audio->decoder_data, stream->this_frame, remainder);
	
	data_len = AUDIO_CHUNK_SIZE-MAD_BUFFER_GUARD-remainder;
	VDEBUGF("mad: data_len:%i remainder:%i available:%i\n", data_len, remainder, slimaudio_buffer_available(audio->decoder_buffer));
	ok = slimaudio_buffer_read(audio->decoder_buffer, audio->decoder_data + remainder, &data_len);
	if (ok == SLIMAUDIO_BUFFER_STREAM_END) {
		DEBUGF("mad: SLIMAUDIO_BUFFER_STREAM_END\n");
		memset(audio->decoder_data + remainder + data_len, 0, MAD_BUFFER_GUARD);
		audio->decoder_end_of_stream = true;
	}

	mad_stream_buffer(stream, (const unsigned char *)audio->decoder_data, data_len + remainder);

	VDEBUGF("mad: mad_input: CONTINUE\n");
	return MAD_FLOW_CONTINUE;
}
Esempio n. 6
0
static enum mad_flow
input(void *data, struct mad_stream *stream)
{
	int fd, n, m;
	static uint8_t buf[32768];

	fd = (int)data;
	n = stream->bufend - stream->next_frame;
	memmove(buf, stream->next_frame, n);
	m = read(fd, buf+n, sizeof buf-n);
	offset += m;
	if(m < 0)
		sysfatal("reading input: %r");
	if(m == 0)
		return MAD_FLOW_STOP;
	n += m;
	mad_stream_buffer(stream, buf, n);
	return MAD_FLOW_CONTINUE;
}
Esempio n. 7
0
SINT SoundSourceMp3::restartDecoding(
        const SeekFrameType& seekFrame) {
    qDebug() << "restartDecoding @" << seekFrame.frameIndex;

    // Discard decoded output
    m_madSynthCount = 0;

    if (getMinFrameIndex() == seekFrame.frameIndex) {
        mad_frame_finish(&m_madFrame);
        mad_synth_finish(&m_madSynth);
    }
    mad_stream_finish(&m_madStream);

    mad_stream_init(&m_madStream);
    mad_stream_options(&m_madStream, MAD_OPTION_IGNORECRC);
    if (getMinFrameIndex() == seekFrame.frameIndex) {
        mad_synth_init(&m_madSynth);
        mad_frame_init(&m_madFrame);
    }

    // Fill input buffer
    mad_stream_buffer(&m_madStream, seekFrame.pInputData,
            m_fileSize - (seekFrame.pInputData - m_pFileData));

    if (getMinFrameIndex() < seekFrame.frameIndex) {
        // Muting is done here to eliminate potential pops/clicks
        // from skipping Rob Leslie explains why here:
        // http://www.mars.org/mailman/public/mad-dev/2001-August/000321.html
        mad_frame_mute(&m_madFrame);
        mad_synth_mute(&m_madSynth);
    }

    if (!decodeFrameHeader(&m_madFrame.header, &m_madStream, false)) {
        if (!isStreamValid(m_madStream)) {
            // Failure -> Seek to EOF
            return getFrameCount();
        }
    }

    return seekFrame.frameIndex;
}
Esempio n. 8
0
enum mad_flow input_cb(void *_data, struct mad_stream *stream)
{
   struct private_data *data = (struct private_data *)_data;

   if(data->progressCallback) {
      data->cancelled = data->progressCallback(data->userData,
                                               (float)data->file->Tell() /
                                               data->file->Length());
      if(data->cancelled)
         return MAD_FLOW_STOP;
   }

   if(data->file->Eof()) {
      data->cancelled = false;
      return MAD_FLOW_STOP;
   }

   /* "Each time you refill your buffer, you need to preserve the data in
    *  your existing buffer from stream.next_frame to the end.
    *
    *  This usually amounts to calling memmove() on this unconsumed portion
    *  of the buffer and appending new data after it, before calling
    *  mad_stream_buffer()"
    *           -- Rob Leslie, on the mad-dev mailing list */

   unsigned int unconsumedBytes;
   if(stream->next_frame) {
      unconsumedBytes = data->inputBuffer + INPUT_BUFFER_SIZE - stream->next_frame;
      memmove(data->inputBuffer, stream->next_frame, unconsumedBytes);
   }
   else
      unconsumedBytes = 0;


   off_t read = data->file->Read(data->inputBuffer + unconsumedBytes,
                                 INPUT_BUFFER_SIZE - unconsumedBytes);

   mad_stream_buffer(stream, data->inputBuffer, read + unconsumedBytes);

   return MAD_FLOW_CONTINUE;
}
Esempio n. 9
0
enum mad_flow read_from_mmap(void *data, struct mad_stream *stream)
{
    buffer *playbuf = (buffer *)data;
    void *mpegdata = NULL;
    
    /* libmad asks us for more data when it runs out. We don't have any more,
       so we want to quit here. */
    if (status != MPG321_REWINDING && playbuf->done)
    {
        status = MPG321_STOPPED;
        if (options.opt & MPG321_REMOTE_PLAY) printf("@P 3\n");
	if(options.opt & MPG321_ENABLE_BUFFER) Decoded_Frames->done = 1;
        return MAD_FLOW_STOP;
    }

    if(playbuf->fd != -1)
    {
        fprintf(stderr, "read_from_mmap called when not expected!\n");
        exit(1);
    }
    
    mpegdata = playbuf->buf;

    if(status == MPG321_REWINDING)
    {
        mpegdata = playbuf->frames[current_frame];
        options.seek = 0;
        status = MPG321_PLAYING;
    }

    if (status != MPG321_SEEKING) /* seeking goes to playing during the decoding process */
        status = MPG321_PLAYING;

    playbuf->done = 1;

    current_frame = 0;

    mad_stream_buffer(stream, mpegdata, playbuf->length - (mpegdata - playbuf->buf));
    
    return MAD_FLOW_CONTINUE;
}
Esempio n. 10
0
File: play.c Progetto: trazyn/GTRS
static enum mad_flow input(void *data, struct mad_stream *stream)
{
    struct stream *ptr = (struct stream *)data;

    static unsigned char buf[BUFSIZE] = { 0 };
    static int nbyte = 0;
    int remnbyte = 0;

    if(feof(ptr->fp))
    {
        /* end of trace */
        return MAD_FLOW_STOP;
    }

    if(stream->next_frame)
    {
        remnbyte = (unsigned)(buf + nbyte - stream->next_frame);
        memcpy(buf, stream->next_frame, remnbyte);
    }

    nbyte = timeout_read(fileno(ptr->fp), (char *)(buf + remnbyte), BUFSIZE - remnbyte, 5);

    if(nbyte <= 0)
    {
        if(-1 == nbyte)
        {
            fprintf(stderr, "timeout or occurred an error");
            return MAD_FLOW_STOP;
        }

        return MAD_FLOW_STOP;
    }

    nbyte += remnbyte;

    mad_stream_buffer(stream, buf, nbyte);

    return MAD_FLOW_CONTINUE;
}
int RageSoundReader_MP3::fill_buffer()
{
	/* Need more data. */
	int inbytes = 0;
	if( mad->Stream.next_frame != NULL )
	{
		/* Pull out remaining data from the last buffer. */
		inbytes = mad->Stream.bufend-mad->Stream.next_frame;
		memmove( mad->inbuf, mad->Stream.next_frame, inbytes );
		mad->inbuf_filepos += mad->Stream.next_frame - mad->inbuf;
	}

	const bool bWasAtEOF = m_pFile->AtEOF();

	int rc = m_pFile->Read( mad->inbuf + inbytes, sizeof(mad->inbuf)-inbytes-MAD_BUFFER_GUARD );
	if( rc < 0 )
	{
		SetError( m_pFile->GetError() );
		return -1;
	}

	if ( m_pFile->AtEOF() && !bWasAtEOF )
	{
		/* We just reached EOF.  Append MAD_BUFFER_GUARD bytes of NULs to the
		 * buffer, to ensure that the last frame is flushed. */
		memset( mad->inbuf + inbytes + rc, 0, MAD_BUFFER_GUARD );
		rc += MAD_BUFFER_GUARD;
	}

	if ( rc == 0 )
		return 0;

	inbytes += rc;
	mad_stream_buffer( &mad->Stream, mad->inbuf, inbytes );
	return rc;
}
bool RageSoundReader_MP3::MADLIB_rewind()
{
	m_pFile->Seek(0);
			
	mad_frame_mute(&mad->Frame);
	mad_synth_mute(&mad->Synth);
	mad_timer_reset(&mad->Timer);
	mad->outpos = mad->outleft = 0;

	mad_stream_finish(&mad->Stream);
	mad_stream_init(&mad->Stream);
	mad_stream_buffer(&mad->Stream, NULL, 0);
	mad->inbuf_filepos = 0;

	/* Be careful.  We need to leave header_bytes alone, so if we try to SetPosition_estimate
	 * immediately after this, we still know the header size.  However, we need to set first_frame
	 * to true, since the first frame is handled specially in do_mad_frame_decode; if we don't
	 * set it, then we'll be desynced by a frame after an accurate seek. */
//	mad->header_bytes = 0;
	mad->first_frame = true;
	mad->Stream.this_frame = NULL;

	return true;
}
Esempio n. 13
0
static enum mad_flow input(void * data, struct mad_stream * stream) {
	static unsigned char buf[BUFSIZE + 1] = { 0 };
	struct stream * ptr = (struct stream *) data;

	static int nbyte = 0;
	int remnbyte = 0;

	if(feof(ptr->streamfd))
		return MAD_FLOW_STOP;

	if(stream->next_frame) {
		remnbyte = (unsigned) (& buf[nbyte] - stream->next_frame);
		memmove(buf, stream->next_frame, remnbyte);
	}

	if(ptr->preload) {
		nbyte = timed_read(fileno(ptr->streamfd), buf + remnbyte, BUFSIZE - remnbyte, ptr->timeout);

		if(nbyte == -1) {
			fputs("Stream timed out.\n", stderr);
		}

		else if(ptr->dump)
			fwrite(buf + remnbyte, sizeof(buf[0]), nbyte, ptr->dump);
	}
	else {
		while(nbyte < BUFSIZE) {
			int retval = timed_read(fileno(ptr->streamfd), buf + nbyte, BUFSIZE - nbyte, ptr->timeout);

			if(retval <= 0)
				break;

			if(ptr->dump)
				fwrite(buf + nbyte, sizeof(buf[0]), retval, ptr->dump);

			nbyte += retval;
		}

		if(!nbyte) {
			fputs("Stream timed out while trying to preload data.\n", stderr);
		}

		ptr->preload = !0;
	}
	
	if(nbyte <= 0)
		return MAD_FLOW_STOP;

	nbyte += remnbyte;

	mad_stream_buffer(stream, (unsigned char *) buf, nbyte);


	if(kill(ptr->parent, 0) == -1 && errno == ESRCH) {
		fclose(ptr->streamfd);
		killed = !0;
		return MAD_FLOW_STOP;
	}

	if(killed)
		return MAD_FLOW_STOP;

	return MAD_FLOW_CONTINUE;
}
Esempio n. 14
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
}
Esempio n. 15
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;
}
Esempio n. 16
0
static void 
MP3_getInfo()
{
    int FrameCount = 0;
    struct mad_stream stream;
    struct mad_header header; 
    mad_stream_init (&stream);
    mad_header_init (&header);

    MP3_info.fileSize = size;
    mad_timer_reset(&MP3_info.length);
    mad_stream_buffer (&stream, mp3_data, size);
    while (1){
        if (mad_header_decode (&header, &stream) == -1){
            if (MAD_RECOVERABLE(stream.error)){
                continue;                
            }else{
                break;
            }
        }
        //Informazioni solo dal primo frame:
        if (FrameCount == 0){
            switch (header.layer) {
            case MAD_LAYER_I:
                strcpy(MP3_info.layer,"I");
                break;
            case MAD_LAYER_II:
                strcpy(MP3_info.layer,"II");
                break;
            case MAD_LAYER_III:
                strcpy(MP3_info.layer,"III");
                break;
            default:
                strcpy(MP3_info.layer,"unknown");
                break;
            }

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

            switch (header.emphasis) {
            case MAD_EMPHASIS_NONE:
                strcpy(MP3_info.emphasis,"no");
                break;
            case MAD_EMPHASIS_50_15_US:
                strcpy(MP3_info.emphasis,"50/15 us");
                break;
            case MAD_EMPHASIS_CCITT_J_17:
                strcpy(MP3_info.emphasis,"CCITT J.17");
                break;
            case MAD_EMPHASIS_RESERVED:
                strcpy(MP3_info.emphasis,"reserved(!)");
                break;
            default:
                strcpy(MP3_info.emphasis,"unknown");
                break;
            }            
        }
        FrameCount++;
        mad_timer_add (&MP3_info.length, header.duration);
    }
    mad_header_finish (&header);
    mad_stream_finish (&stream);

    MP3_info.frames = FrameCount;
    mad_timer_string(MP3_info.length, MP3_info.strLength, "%02lu:%02u:%02u", MAD_UNITS_HOURS, MAD_UNITS_MILLISECONDS, 0);
}
Esempio n. 17
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;
}
Esempio n. 18
0
void LibMadWrapper::open()
{
    // avoid multiple calls to open()
    if (this->infile != nullptr)
    {
        return;
    }

    this->infile = fopen(this->Filename.c_str(), "rb");
    if (this->infile == nullptr)
    {
        THROW_RUNTIME_ERROR("fopen failed, errno: " << string(strerror(errno)));
    }

    int fd = fileno(this->infile);
    this->mpeglen = getFileSize(fd);
    this->mpegbuf = static_cast<unsigned char *>(mmap(nullptr, this->mpeglen, PROT_READ, MAP_SHARED, fd, 0));
    if (this->mpegbuf == MAP_FAILED)
    {
        THROW_RUNTIME_ERROR("mmap failed for File \"" << this->Filename << ")\"");
    }


    this->stream = new struct mad_stream;
    mad_stream_init(this->stream);
    /* load buffer with MPEG audio data */
    mad_stream_buffer(this->stream, this->mpegbuf, this->mpeglen);

    // we want to know how many pcm frames there are decoded in this file
    // therefore decode header of every mpeg frame
    // pretty expensive, so only to this once
    if (this->numFrames == 0)
    {
        struct mad_header header;
        mad_header_init(&header);

        // try to find a valid header
        int ret = this->findValidHeader(header);
        if (ret != 0)
        {
            // only free the locally used header here, this->stream and this->mpegbuf are freed in LibMadWrapper::close()
            mad_header_finish(&header);

            THROW_RUNTIME_ERROR("unable to find a valid frame-header for File \"" + this->Filename + "\"");
        }

        this->Format.SetVoices(1);
        // a first valid header is good, but it may contain garbage
        this->Format.VoiceChannels[0] = MAD_NCHANNELS(&header);
        this->Format.SampleRate = header.samplerate;
        CLOG(LogLevel_t::Debug, "found a first valid header within File \"" << this->Filename << "\"\n\tchannels: " << MAD_NCHANNELS(&header) << "\nsrate: " << header.samplerate);

        // no clue what this 32 does
        // stolen from mad_synth_frame() in synth.c
        this->numFrames += 32 * MAD_NSBSAMPLES(&header);

        // try to find a second valid header
        ret = this->findValidHeader(header);
        if (ret == 0)
        {
            // better use format infos from this header
            this->Format.VoiceChannels[0] = max<int>(MAD_NCHANNELS(&header), this->Format.VoiceChannels[0]);
            this->Format.SampleRate = header.samplerate;
            CLOG(LogLevel_t::Debug, "found a second valid header within File \"" << this->Filename << "\"\n\tchannels: " << MAD_NCHANNELS(&header) << "\nsrate: " << header.samplerate);

            this->numFrames += 32 * MAD_NSBSAMPLES(&header);

            // now lets go on and decode rest of file
            while (1)
            {
                if (mad_header_decode(&header, this->stream) != 0)
                {
                    if (MAD_RECOVERABLE(this->stream->error))
                    {
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }

                // sanity checks
                if (this->Format.Channels() != MAD_NCHANNELS(&header))
                {
                    CLOG(LogLevel_t::Warning, "channelcount varies (now: " << MAD_NCHANNELS(&header) << ") within File \"" << this->Filename << ")\"");

                    if (!gConfig.MadPermissive)
                    {
                        THROW_RUNTIME_ERROR("invalid mp3: channelcount varies");
                    }
                }

                if (this->Format.SampleRate != header.samplerate)
                {
                    CLOG(LogLevel_t::Warning, "samplerate varies (now: " << header.samplerate << ") within File \"" << this->Filename << ")\"");

                    if (!gConfig.MadPermissive)
                    {
                        THROW_RUNTIME_ERROR("invalid mp3: samplerate varies");
                    }
                }

                this->numFrames += 32 * MAD_NSBSAMPLES(&header);
            }
        }
        else
        {
            CLOG(LogLevel_t::Warning, "only one valid header found, probably no valid mp3 File \"" << this->Filename << "\"");
        }

        // somehow reset libmad stream
        mad_stream_finish(this->stream);
        mad_stream_init(this->stream);
        /* load buffer with MPEG audio data */
        mad_stream_buffer(this->stream, this->mpegbuf, this->mpeglen);

        mad_header_finish(&header);
    }

    this->frame.hasValue = true;
    mad_frame_init(&this->frame.Value);

    this->synth.hasValue = true;
    mad_synth_init(&this->synth.Value);
}
Esempio n. 19
0
/**
 * 搜索下一个有效MP3 frame
 *
 * @return
 * - <0 失败
 * - 0 成功
 */
static int seek_valid_frame(void)
{
	int cnt = 0;
	int ret;

	mad_stream_finish(&stream);
	mad_stream_init(&stream);

	do {
		cnt++;
		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) {
				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;
		}

		if ((ret = mad_header_decode(&frame.header, &stream)) == -1) {
			/*
			 * MAD_ERROR_BUFLEN should be ignored
			 *
			 * We haven't reached the EOF as long as xrIoRead returned positive.
			 */
			if (!MAD_RECOVERABLE(stream.error) && stream.error != MAD_ERROR_BUFLEN) {
				return -1;
			}
		} else {
			ret = 0;
			stream.error = 0;
		}
	} while (!(ret == 0 && stream.sync == 1));
	dbg_printf(d, "%s: tried %d times", __func__, cnt);

	return 0;
}
Esempio n. 20
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;
}
Esempio n. 21
0
SoundSource::OpenResult SoundSourceMp3::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) {
    DEBUG_ASSERT(!hasValidChannelCount());
    DEBUG_ASSERT(!hasValidSamplingRate());

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

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

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

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

    // Decode all the headers and calculate audio properties

    unsigned long sumBitrate = 0;

    mad_header madHeader;
    mad_header_init(&madHeader);

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

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

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

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

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

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

        addSeekFrame(m_curFrameIndex, m_madStream.this_frame);

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

        // Update current stream position
        m_curFrameIndex += madFrameLength;

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

    mad_header_finish(&madHeader);

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

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

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

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

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

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

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

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

    // Terminate m_seekFrameList
    addSeekFrame(m_curFrameIndex, 0);

    // Reset positions
    m_curFrameIndex = getMinFrameIndex();

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

    return OpenResult::SUCCEEDED;
}
Esempio n. 22
0
/*
 * 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;
}
Esempio n. 23
0
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;
}
Esempio n. 24
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;
  }
Esempio n. 25
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;
}
Esempio n. 26
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();
}
Esempio n. 27
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
  }
Esempio n. 28
0
/* Following two functions are adapted from mad_timer, from the 
   libmad distribution */
void scan(void const *ptr, ssize_t len, buffer *buf)
{
    struct mad_stream stream;
    struct mad_header header;
    struct xing xing;
    
    unsigned long bitrate = 0;
    int has_xing = 0;
    int is_vbr = 0;

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

    mad_stream_buffer(&stream, ptr, len);

    buf->num_frames = 0;

    /* There are three ways of calculating the length of an mp3:
      1) Constant bitrate: One frame can provide the information
         needed: # of frames and duration. Just see how long it
         is and do the division.
      2) Variable bitrate: Xing tag. It provides the number of 
         frames. Each frame has the same number of samples, so
         just use that.
      3) All: Count up the frames and duration of each frames
         by decoding each one. We do this if we've no other
         choice, i.e. if it's a VBR file with no Xing tag.
    */

    while (1)
    {
        if (mad_header_decode(&header, &stream) == -1)
        {
            if (MAD_RECOVERABLE(stream.error))
                continue;
            else
                break;
        }

        /* Limit xing testing to the first frame header */
        if (!buf->num_frames++)
        {
            if(parse_xing(&xing, stream.anc_ptr, stream.anc_bitlen))
            {
                is_vbr = 1;
                
                if (xing.flags & XING_FRAMES)
                {
                    /* We use the Xing tag only for frames. If it doesn't have that
                       information, it's useless to us and we have to treat it as a
                       normal VBR file */
                    has_xing = 1;
                    buf->num_frames = xing.frames;
                    break;
                }
            }
        }                

        /* Test the first n frames to see if this is a VBR file */
        if (!is_vbr && !(buf->num_frames > 20))
        {
            if (bitrate && header.bitrate != bitrate)
            {
                is_vbr = 1;
            }
            
            else
            {
                bitrate = header.bitrate;
            }
        }
        
        /* We have to assume it's not a VBR file if it hasn't already been
           marked as one and we've checked n frames for different bitrates */
        else if (!is_vbr)
        {
            break;
        }
            
        mad_timer_add(&buf->duration, header.duration);
    }

    if (!is_vbr)
    {
        double time = (len * 8.0) / (header.bitrate); /* time in seconds */
        double timefrac = (double)time - ((long)(time));
        long nsamples = 32 * MAD_NSBSAMPLES(&header); /* samples per frame */
        
        /* samplerate is a constant */
        buf->num_frames = (long) (time * header.samplerate / nsamples);

        mad_timer_set(&buf->duration, (long)time, (long)(timefrac*100), 100);
    }
        
    else if (has_xing)
    {
        /* modify header.duration since we don't need it anymore */
        mad_timer_multiply(&header.duration, buf->num_frames);
        buf->duration = header.duration;
    }

    else
    {
        /* the durations have been added up, and the number of frames
           counted. We do nothing here. */
    }
    
    mad_header_finish(&header);
    mad_stream_finish(&stream);
}
Esempio n. 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;
}
Esempio n. 30
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;
}