예제 #1
0
int GetMADSamples(MFAudioStream *pStream, void *pBuffer, uint32 bytes)
{
	MFMADDecoder *pDecoder = (MFMADDecoder*)pStream->pStreamData;

	int written = 0;

	if(pDecoder->overflowBytes)
	{
		// grab from the overflow until we run out...
		uint32 numBytes = MFMin(pDecoder->overflowBytes - pDecoder->overflowOffset, bytes);
		MFCopyMemory(pBuffer, pDecoder->overflow + pDecoder->overflowOffset, numBytes);
		pDecoder->overflowOffset += numBytes;
		if(pDecoder->overflowOffset == pDecoder->overflowBytes)
			pDecoder->overflowBytes = 0;

		// increment timer
		mad_timer_t t = { 0, MAD_TIMER_RESOLUTION / pDecoder->firstHeader.samplerate };
		mad_timer_multiply(&t, numBytes >> 2);
		mad_timer_add(&pDecoder->timer, t);

		if(bytes == numBytes)
			return numBytes;

		bytes -= numBytes;
		(char*&)pBuffer += numBytes;
		written = (int)numBytes;
	}
예제 #2
0
파일: mp3.cpp 프로젝트: Glyth/xoreos
void MP3Stream::readHeader() {
	if (_state != MP3_STATE_READY)
		return;

	// If necessary, load more data into the stream decoder
	if (_stream.error == MAD_ERROR_BUFLEN)
		readMP3Data();

	while (_state != MP3_STATE_EOS) {
		_stream.error = MAD_ERROR_NONE;

		// Decode the next header. Note: mad_frame_decode would do this for us, too.
		// However, for seeking we don't want to decode the full frame (else it would
		// be far too slow). Hence we perform this explicitly in a separate step.
		if (mad_header_decode(&_frame.header, &_stream) == -1) {
			if (_stream.error == MAD_ERROR_BUFLEN) {
				readMP3Data();  // Read more data
				continue;
			} else if (MAD_RECOVERABLE(_stream.error)) {
				//status("MP3Stream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
				continue;
			} else {
				warning("MP3Stream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
				break;
			}
		}

		// Sum up the total playback time so far
		mad_timer_add(&_totalTime, _frame.header.duration);
		break;
	}

	if (_stream.error != MAD_ERROR_NONE)
		_state = MP3_STATE_EOS;
}
예제 #3
0
파일: mp3.c 프로젝트: tedkulp/bossogg
static int mp3_read (song_s *song, char *buffer)
{
  static int i;
  static int ret;
  static struct audio_dither dither;
  static char buffer2[BUF_SIZE];
  static char *out_ptr = buffer2;
  static char *out_buf_end = buffer2 + BUF_SIZE;
  mp3_s *mp3 = song->songlib->mp3;

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

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

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

    if (out_ptr == out_buf_end) {
      memcpy (buffer, buffer2, BUF_SIZE);
      bossao_play_chunk (song, buffer, BUF_SIZE);
      out_ptr = buffer2;
    }
  }
예제 #4
0
파일: mad_plugin.c 프로젝트: azuwis/mpd
static void
mp3_update_timer_next_frame(struct mp3_data *data)
{
	if (data->current_frame >= data->highest_frame) {
		/* record this frame's properties in
		   data->frame_offsets (for seeking) and
		   data->times */
		data->bit_rate = (data->frame).header.bitrate;

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

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

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

	data->current_frame++;
	data->elapsed_time =
		mad_timer_count(data->timer, MAD_UNITS_MILLISECONDS) / 1000.0;
}
예제 #5
0
// Seek in the stream, finding the next valid header
void Mp3PspStream::findValidHeader() {
	DEBUG_ENTER_FUNC();

	if (_state != MP3_STATE_READY)
		return;

	// If necessary, load more data into the stream decoder
	if (_stream.error == MAD_ERROR_BUFLEN)
		readMP3DataIntoBuffer();

	while (_state != MP3_STATE_EOS) {
		_stream.error = MAD_ERROR_NONE;

		// Decode the next header.
		if (mad_header_decode(&_header, &_stream) == -1) {
			if (_stream.error == MAD_ERROR_BUFLEN) {
				readMP3DataIntoBuffer();  // Read more data
				continue;
			} else if (MAD_RECOVERABLE(_stream.error)) {
				debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
				continue;
			} else {
				warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
				break;
			}
		}

		// Sum up the total playback time so far
		mad_timer_add(&_totalTime, _header.duration);
		break;
	}

	if (_stream.error != MAD_ERROR_NONE)
		_state = MP3_STATE_EOS;
}
예제 #6
0
파일: MadDecoder.cpp 프로젝트: dreieier/E3
    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
    }
예제 #7
0
파일: MadDecoder.cpp 프로젝트: dreieier/E3
    //
    // Read up samples from madSynth_
    // If needed, read some more MP3 data, decode them and synth them
    // Place in audioBuffer_.
    // Return number of samples read.
    //
    size_t MadDecoder::decode(size_t numPendingTotal, AudioBuffer* buffer)
    {
        size_t numProcessedTotal = 0;
        int numChannels = getNumChannels();
        mad_fixed_t sample;

        do {
            size_t numPendingFrame = (madSynth_.pcm.length - currentFrame_) * numChannels;
            numPendingFrame = std::min(numPendingTotal, numPendingFrame);
            size_t numProcessedFrame = 0;

            while (numProcessedFrame < numPendingFrame)
            {
                for (int channel = 0; channel < numChannels; channel++)
                {
                    sample = madSynth_.pcm.samples[channel][currentFrame_];
                    if (sample < -MAD_F_ONE)
                        sample = -MAD_F_ONE;
                    else if (sample >= MAD_F_ONE)
                        sample = MAD_F_ONE - 1;

                    float fSample = (float)(sample / (float)(1L << MAD_F_FRACBITS));
                    float* pos = buffer->getHead() + numProcessedTotal;
                    *pos = fSample;
                    numProcessedFrame++;
                    numProcessedTotal++;
                }
                currentFrame_++;
            }

            numPendingTotal -= numProcessedFrame;
            if (numPendingTotal == 0)
                break;

            if (madStream_.error == MAD_ERROR_BUFLEN) {     // check whether input buffer needs a refill 
                if (readMpgFile() == false)                  // eof
                    break;
            }

            if (mad_frame_decode(&madFrame_, &madStream_))
            {
                if (MAD_RECOVERABLE(madStream_.error)) {
                    consumeId3Tag();
                    continue;
                }
                else  {
                    if (madStream_.error == MAD_ERROR_BUFLEN)
                        continue;
                    else
                        THROW(std::exception, "unrecoverable frame level error (%s).", mad_stream_errorstr(&madStream_));
                }
            }
            mad_timer_add(&madTimer_, madFrame_.header.duration);
            mad_synth_frame(&madSynth_, &madFrame_);
            currentFrame_ = 0;
            numMpegFrames_++;
        } while (true);

        return numProcessedTotal;
    }
예제 #8
0
int TrackDuration::duration(const QFileInfo &fileinfo)
{
    QString fn = fileinfo.absoluteFilePath();
    if (fn.isEmpty())
        return 0;

    QFile file(fn);
    if (!file.open(QFile::ReadOnly))
        return 0;

    mad_stream infostream;
    mad_header infoheader;
    mad_timer_t infotimer;
    mad_stream_init(&infostream);
    mad_header_init(&infoheader);
    mad_timer_reset(&infotimer);

    qint64 r;
    qint64 l = 0;
    unsigned char* buf = new unsigned char[INPUT_BUFFER_SIZE];

    while (!file.atEnd()) {
        if (l < INPUT_BUFFER_SIZE) {
            r = file.read(reinterpret_cast<char*>(buf) + l, INPUT_BUFFER_SIZE - l);
            l += r;
        }
        mad_stream_buffer(&infostream, buf, l);
        for (;;) {
            if (mad_header_decode(&infoheader, &infostream)) {
                if (!MAD_RECOVERABLE(infostream.error))
                    break;
                if (infostream.error == MAD_ERROR_LOSTSYNC) {
                    TagLib::ID3v2::Header header;
                    uint size = (uint)(infostream.bufend - infostream.this_frame);
                    if (size >= header.size()) {
                        header.setData(TagLib::ByteVector(reinterpret_cast<const char*>(infostream.this_frame), size));
                        uint tagsize = header.tagSize();
                        if (tagsize > 0) {
                            mad_stream_skip(&infostream, qMin(tagsize, size));
                            continue;
                        }
                    }
                }
                qDebug() << "header decode error while getting file info" << infostream.error;
                continue;
            }
            mad_timer_add(&infotimer, infoheader.duration);
        }
        if (infostream.error != MAD_ERROR_BUFLEN && infostream.error != MAD_ERROR_BUFPTR)
            break;
        memmove(buf, infostream.next_frame, &(buf[l]) - infostream.next_frame);
        l -= (infostream.next_frame - buf);
    }

    mad_stream_finish(&infostream);
    mad_header_finish(&infoheader);
    delete[] buf;

    return timerToMs(&infotimer);
}
예제 #9
0
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); 
} 
예제 #10
0
static void
scan_file (FILE * fd, int *length, int *bitrate)
{
    struct mad_stream stream;
    struct mad_header header;
    mad_timer_t timer;
    unsigned char buffer[8192];
    unsigned int buflen = 0;

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

    timer = mad_timer_zero;

    while (1)
    {
	if (buflen < 8192)
	{
            int bytes = 0;

            bytes = fread (buffer + buflen, 1, 8192 - buflen, fd);
            if (bytes <= 0)
		break;

            buflen += bytes;
	}

	mad_stream_buffer (&stream, buffer, buflen);

	while (1)
	{
            if (mad_header_decode (&header, &stream) == -1)
            {
		if (!MAD_RECOVERABLE (stream.error))
                    break;
		continue;
            }
            if (length)
		mad_timer_add (&timer, header.duration);

	}

	if (stream.error != MAD_ERROR_BUFLEN)
            break;

	memmove (buffer, stream.next_frame, &buffer[buflen] - stream.next_frame);
	buflen -= stream.next_frame - &buffer[0];
        SDL_Delay(1);
    }

    mad_header_finish (&header);
    mad_stream_finish (&stream);

    if (length)
	*length = mad_timer_count (timer, MAD_UNITS_MILLISECONDS);
}
예제 #11
0
void
MADTranscode::onSeek( int seconds )
{
    mad_timer_t t;
    t.seconds = seconds;
    t.fraction = 0;

    timer = mad_timer_zero;
    mad_timer_add( &timer, t );

    m_encodedBuffer.clear();
    m_decodedBuffer.clear();
}
예제 #12
0
파일: timer.c 프로젝트: bugengine/BugEngine
/*
 * NAME:	timer->multiply()
 * DESCRIPTION:	multiply a timer by a scalar value
 */
void mad_timer_multiply(mad_timer_t *timer, s32 scalar)
{
  mad_timer_t addend;
  u32 factor;

  factor = scalar;
  if (scalar < 0) {
    factor = -scalar;
    mad_timer_negate(timer);
  }

  addend = *timer;
  *timer = mad_timer_zero;

  while (factor) {
    if (factor & 1)
      mad_timer_add(timer, addend);

    mad_timer_add(&addend, addend);
    factor >>= 1;
  }
}
예제 #13
0
/*
 * NAME:	timer->multiply()
 * DESCRIPTION:	multiply a timer by a scalar value
 */
void ICACHE_FLASH_ATTR mad_timer_multiply(mad_timer_t *timer, signed long scalar)
{
  mad_timer_t addend;
  unsigned long factor;

  factor = scalar;
  if (scalar < 0) {
    factor = -scalar;
    mad_timer_negate(timer);
  }

  addend = *timer;
  *timer = mad_timer_zero;

  while (factor) {
    if (factor & 1)
      mad_timer_add(timer, addend);

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

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

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

	if( !MADLIB_rewind() )
		return 0;

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

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

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

	/* Count milliseconds. */
	return mad_timer_count( end, MAD_UNITS_MILLISECONDS );
}
/* Do a seek based on the bitrate. */
int RageSoundReader_MP3::SetPosition_estimate( int iFrame )
{
	/* This doesn't leave us accurate. */
	mad->timer_accurate = 0;

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

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

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

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

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

	return 1;
}
예제 #16
0
파일: mad.c 프로젝트: mvd7793/RED-SIREN
/* 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);
}
예제 #17
0
파일: mad.c 프로젝트: mvd7793/RED-SIREN
enum mad_flow read_header(void *data, struct mad_header const * header)
{
    char long_currenttime_str[14]; /* this *will* fill if you're using 100000+ minute mp3s */
    char long_remaintime_str[14];
    static int frames_played = 0;
    
    buffer *playbuf = (buffer *)data;
    mad_timer_t time_remaining;
    char *ao_time;

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

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

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

    current_frame++;

    mad_timer_add(&current_time, header->duration);

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

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

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


        mad_timer_negate(&current_time);

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

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

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

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

        return MAD_FLOW_IGNORE;
    }
    else
    {
        status = MPG321_PLAYING;
    }

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

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

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

			    fprintf(stderr,"@F %ld %ld %.2f %.2f\n", current_frame, playbuf->num_frames - current_frame,
				    	    ((double)mad_timer_count(current_time, MAD_UNITS_CENTISECONDS)/100.0),
			    		    ((double)mad_timer_count(time_remaining, MAD_UNITS_CENTISECONDS)/100.0));
		    }
	    }
    }
    return MAD_FLOW_CONTINUE;
}        
예제 #18
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;
}
예제 #19
0
파일: snd_mp3.c 프로젝트: dommul/super8
/* Read up to len samples from p->Synth
 * If needed, read some more MP3 data, decode them and synth them
 * Place in buf[].
 * Return number of samples read.  */
static int mp3_decode(snd_stream_t *stream, byte *buf, int len)
{
	mp3_priv_t *p = (mp3_priv_t *) stream->priv;
	int donow, i, done = 0;
	mad_fixed_t sample;
	int chan, x;

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

		len -= donow;
		done += donow;

		if (len == 0)
			break;

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

		if (mad_frame_decode(&p->Frame, &p->Stream))
		{
			if (MAD_RECOVERABLE(p->Stream.error))
			{
				mp3_inputtag(stream);
				continue;
			}
			else
			{
				if (p->Stream.error == MAD_ERROR_BUFLEN)
					continue;
				else
				{
					Con_Printf("MP3: unrecoverable frame level error (%s)\n",
							mad_stream_errorstr(&p->Stream));
					break;
				}
			}
		}
		p->FrameCount++;
		mad_timer_add(&p->Timer, p->Frame.header.duration);
		mad_synth_frame(&p->Synth, &p->Frame);
		p->cursamp = 0;
	} while (1);
예제 #20
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;
}
예제 #21
0
unsigned int mpgDecoder::decode( float *** data, int count )
{
#ifdef HAVE_MAD
        if(data)
		*data=returnBuffer;

	while( mad_outputBuffer[0].canWrite(1152) )  // well letts refill the Input buffer..........
	{
		if( madStream->buffer == NULL || madStream->error == MAD_ERROR_BUFLEN)  // well letts refill the Input buffer..........
		{
			size_t readSize, remaining;
			unsigned char* readStart;
			unsigned char* guardPtr;

			if( madFile->atEnd() )
				return(0);

			if(madStream->next_frame)  // move remaining bytes to start wich has not been decoded yet...
			{
				remaining = mad_inputBuffer + 163840 - madStream->next_frame;
				memmove( mad_inputBuffer, madStream->next_frame, remaining );
				readStart = mad_inputBuffer + remaining;
				readSize = 163840 - remaining;
			}
			else
			{
				readSize = 163840;
				readStart = mad_inputBuffer;
				remaining = 0;
			}

			// get some more Byte from File...
			unsigned int readCnt = 0;
			while( !madFile->atEnd() && readCnt < readSize)
			{
                            readStart[readCnt] = madFile->read(1).at(0);
                            readCnt++;
			}
			
                        //bei EOF ein paar GUARD 0Bytes anhaengen die MAD benötigt..
			if( madFile->atEnd() )
			{
				guardPtr = readStart + readCnt;
				memset( guardPtr, 0, MAD_BUFFER_GUARD);
				readCnt += MAD_BUFFER_GUARD;
			}
			mad_stream_buffer( madStream, mad_inputBuffer, readCnt+remaining);
			madStream->error = MAD_ERROR_NONE;
		}

		// well lets decode the buffer and get some Music out of it :-)
		mad_frame_decode( madFrame, madStream );
		frameCounter++;

		// first MPeg Frame isnt Played cause it contains noisy Metadata if we Play it :D
		// frame is also not played if we could not decode the whole MPeg frame in case of end of input buffer
		if(madStream->error==MAD_ERROR_BUFLEN || frameCounter ==1)
			continue;

        mad_timer_add( currentPositionTimer, madFrame->header.duration );
		mad_synth_frame( madSynth, madFrame );

		// decoding done.. convert sampletype...
		for( unsigned int j=0; j<channels; j++ )
			for(unsigned int i=0; i<madSynth->pcm.length; i++ )
			{
                                float temp = scale( madSynth->pcm.samples[j][i]);
                                mad_outputBuffer[j].write( &temp, 1 );
                        }
	}
	//nice little workarround so the buffer never gets so much back it wants to....
	int dataAvailable = mad_outputBuffer[0].canRead(count*.95)?count*.95:mad_outputBuffer[0].getAvailable()-8;

        // ensure the return buffer is clean...
        memset(returnBuffer[0], 0, 8192*sizeof(float));
        memset(returnBuffer[1], 0, 8192*sizeof(float));

        for( unsigned int j=0; j<channels; j++ )
		mad_outputBuffer[j].read( returnBuffer[j], dataAvailable );

        return dataAvailable;
#endif
}
예제 #22
0
파일: mp3.c 프로젝트: 173210/mvspsp
static void MP3Update(void)
{
	int flip;
	UINT8 *GuardPtr;
	INT16 *OutputPtr, *OutputEnd;
	struct mad_stream Stream;
	struct mad_frame Frame;
	struct mad_synth Synth;
	mad_timer_t Timer;

	mad_stream_init(&Stream);
	mad_frame_init(&Frame);
	mad_synth_init(&Synth);
	mad_timer_reset(&Timer);

	OutputPtr = (INT16 *)mp3_out[0];
	OutputEnd = (INT16 *)(mp3_out[0] + MP3_BUFFER_SIZE);
	GuardPtr = NULL;

	mp3_filepos = 0;
	mp3_frame = 0;
	flip = 0;
	cdda_command_ack = 1;

	while (mp3_active && mp3_status != MP3_STOP)
	{
		if (Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN)
		{
			UINT32 ReadSize, Remaining;
			UINT8 *ReadStart;

			if (Stream.next_frame != NULL)
			{
				Remaining = Stream.bufend - Stream.next_frame;
				ReadStart = mp3_in + Remaining;
				ReadSize  = (2 * MP3_BUFFER_SIZE) - Remaining;
				memmove(mp3_in, Stream.next_frame, Remaining);
			}
			else
			{
				ReadSize  = 2 * MP3_BUFFER_SIZE;
				ReadStart = mp3_in;
				Remaining = 0;
			}

			if (MP3SleepCheck()) break;

			ReadSize = sceIoRead(mp3_fd, ReadStart, ReadSize);
			mp3_filepos += ReadSize;
			if (mp3_filepos == mp3_fsize)
			{
				if (cdda_autoloop)
				{
					mp3_filepos = 0;
					sceIoLseek(mp3_fd, 0, PSP_SEEK_SET);
				}
				else
				{
					cdda_playing = CDDA_STOP;
					mp3_status = MP3_STOP;
				}
			}

			if (mp3_filepos == mp3_fsize)
			{
				GuardPtr = ReadStart + ReadSize;
				memset(GuardPtr, 0, MAD_BUFFER_GUARD);
				ReadSize += MAD_BUFFER_GUARD;
			}

			mad_stream_buffer(&Stream, mp3_in, ReadSize + Remaining);

			Stream.error = 0;
		}

		if (mad_frame_decode(&Frame, &Stream))
		{
			if (MAD_RECOVERABLE(Stream.error))
			{
//				if (Stream.error != MAD_ERROR_LOSTSYNC || Stream.this_frame != GuardPtr)
				continue;
			}
			else if (Stream.error == MAD_ERROR_BUFLEN)
			{
				continue;
			}
			else
			{
				ui_popup(TEXT(MP3_DECODE_ERROR));
				mp3_status = MP3_STOP;
				break;
			}
		}

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

		if (mp3_status == MP3_PLAY)
		{
			int i;

			for (i = 0; i < Synth.pcm.length; i++)
			{
				if (MAD_NCHANNELS(&Frame.header) == 2)
				{
					*OutputPtr++ = MP3Limit(Synth.pcm.samples[0][i]);
					*OutputPtr++ = MP3Limit(Synth.pcm.samples[1][i]);
				}
				else
				{
					INT16 data = MP3Limit(Synth.pcm.samples[0][i]);

					*OutputPtr++ = data;
					*OutputPtr++ = data;
				}

				if (OutputPtr == OutputEnd)
				{
					sceAudioOutputPannedBlocking(mp3_handle, mp3_volume, mp3_volume, mp3_out[flip]);
					flip ^= 1;
					OutputPtr = (INT16 *)mp3_out[flip];
					OutputEnd = (INT16 *)(mp3_out[flip] + MP3_BUFFER_SIZE);
				}
			}
		}
		else if (mp3_status == MP3_SEEK)
		{
			if (mp3_frame >= mp3_start_frame)
			{
				mp3_start_frame = 0;
				mp3_status = MP3_SLEEP;
				sceKernelSleepThread();
			}
		}
	}

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

	if (mp3_fd >= 0)
	{
		sceIoClose(mp3_fd);
		mp3_fd = -1;
	}
}
예제 #23
0
bool Mp3AudioFileReader::run(AudioProcessor& processor)
{
    if (file_ == nullptr) {
        return false;
    }

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

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

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

    int channels = 0;

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

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

    BStdFile bstd_file(file_);

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

    mad_timer_t timer;
    mad_timer_reset(&timer);

    // This is the decoding loop.

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

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

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

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

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

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

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

                break;
            }

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

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

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

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

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

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

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

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

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

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

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

            dumpInfo(output_stream, frame.header);

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

            showProgress(0, file_size_);
        }

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

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

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

        mad_synth_frame(&synth, &frame);

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

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

            *output_ptr++ = sample;

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

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

            // Flush the output buffer if it is full

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

                showProgress(pos, file_size_);

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

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

                output_ptr = output_buffer;
            }
        }
    }

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

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

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

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

    // Accounting report if no error occurred.

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

        char buffer[80];

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

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

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

    processor.done();

    close();

    return status == STATUS_OK;
}
예제 #24
0
/*
 * NAME:	parse_time()
 * DESCRIPTION:	parse a time specification string
 */
static
int parse_time(mad_timer_t *timer, char const *str)
{
  mad_timer_t time, accum = mad_timer_zero;
  signed long decimal;
  unsigned long seconds, fraction, fracpart;
  int minus;

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

  do {
    seconds = fraction = fracpart = 0;

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

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

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

      seconds += decimal;

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

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

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

      fraction = decimal;

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

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

      fraction = seconds;
      fracpart = decimal;

      seconds  = 0;
    }

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

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

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

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

  *timer = accum;

  return 0;
}
예제 #25
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;
}
예제 #26
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);
}
예제 #27
0
/*
 * NAME:	main()
 * DESCRIPTION:	program entry point
 */
int main(int argc, char *argv[])
{
  struct player player;
  int result = 0;

  argv0 = argv[0];

  /* ensure binary standard I/O */

# if defined(_WIN32)
  _setmode(_fileno(stdin),  _O_BINARY);
  _setmode(_fileno(stdout), _O_BINARY);
# endif

  /* internationalization support */

# if defined(ENABLE_NLS)
  setlocale(LC_ALL, "");
  bindtextdomain(PACKAGE, LOCALEDIR);
  textdomain(PACKAGE);
# endif

  /* initialize and get options */

  player_init(&player);

# if !defined(__CYGWIN__)  /* Cygwin support for this is currently buggy */

  /* check for default tty control */

  if (isatty(STDIN_FILENO))
    player.options |= PLAYER_OPTION_TTYCONTROL;
# endif

  get_options(argc, argv, &player);

  /* main processing */

  if (player.verbosity >= 0)
    ver_banner(stderr);

  if (player.options & PLAYER_OPTION_CROSSFADE) {
    if (!(player.options & PLAYER_OPTION_GAP))
      warn(_("cross-fade ignored without gap"));
    else if (mad_timer_sign(player.gap) >= 0)
      warn(_("cross-fade ignored without negative gap"));
  }

  if (player.output.replay_gain & PLAYER_RGAIN_ENABLED) {
    if (player.options & PLAYER_OPTION_IGNOREVOLADJ)
      warn(_("volume adjustment ignored with Replay Gain enabled"));
    else
      player.options |= PLAYER_OPTION_IGNOREVOLADJ;
  }

  if ((player.options & PLAYER_OPTION_SHOWTAGSONLY) &&
      player.repeat != 1) {
    warn(_("ignoring repeat"));
    player.repeat = 1;
  }

  /* make stop time absolute */
  if (player.options & PLAYER_OPTION_TIMED)
    mad_timer_add(&player.global_stop, player.global_start);

  /* get default audio output module */
  if (player.output.command == 0 &&
      !(player.options & PLAYER_OPTION_SHOWTAGSONLY))
    player.output.command = audio_output(0);

# if defined(EXPERIMENTAL)
  if (external_mix) {
    player.options |= PLAYER_OPTION_EXTERNALMIX;
    player.output.command = 0;
  }
  if (experimental)
    player.options |= PLAYER_OPTION_EXPERIMENTAL;
# endif

  /* run the player */
  if (player_run(&player, argc - optind, (char const **) &argv[optind]) == -1)
    result = 4;

  /* finish up */
  player_finish(&player);

  return result;
}
예제 #28
0
파일: snd_mp3.c 프로젝트: dommul/super8
static int mp3_startread(snd_stream_t *stream)
{
	mp3_priv_t *p = (mp3_priv_t *) stream->priv;
	size_t ReadSize;

	mad_stream_init(&p->Stream);
	mad_frame_init(&p->Frame);
	mad_synth_init(&p->Synth);
	mad_timer_reset(&p->Timer);

	/* 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.
	 */
	ReadSize = FS_fread(p->mp3_buffer, 1, MP3_BUFFER_SIZE, &stream->fh);
	if (ReadSize != MP3_BUFFER_SIZE)
	{
		if (FS_feof(&stream->fh) || FS_ferror(&stream->fh))
			return -1;
	}

	mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);

	/* Find a valid frame before starting up.  This makes sure
	 * that we have a valid MP3 and also skips past ID3v2 tags
	 * at the beginning of the audio file.
	 */
	p->Stream.error = MAD_ERROR_NONE;
	while (mad_frame_decode(&p->Frame,&p->Stream))
	{
		/* check whether input buffer needs a refill */
		if (p->Stream.error == MAD_ERROR_BUFLEN)
		{
			if (mp3_inputdata(stream) == -1)
				return -1;

			continue;
		}

		/* Consume any ID3 tags */
		mp3_inputtag(stream);

		/* 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.
		 */
		p->Stream.error = MAD_ERROR_NONE;
	}

	if (p->Stream.error)
	{
		Con_Printf("MP3: No valid MP3 frame found\n");
		return -1;
	}

	switch(p->Frame.header.mode)
	{
	case MAD_MODE_SINGLE_CHANNEL:
	case MAD_MODE_DUAL_CHANNEL:
	case MAD_MODE_JOINT_STEREO:
	case MAD_MODE_STEREO:
		stream->info.channels = MAD_NCHANNELS(&p->Frame.header);
		break;
	default:
		Con_Printf("MP3: Cannot determine number of channels\n");
		return -1;
	}

	p->FrameCount = 1;

	mad_timer_add(&p->Timer,p->Frame.header.duration);
	mad_synth_frame(&p->Synth,&p->Frame);
	stream->info.width = MP3_MAD_SAMPLEWIDTH;
	stream->info.rate = p->Synth.pcm.samplerate;

	p->cursamp = 0;

	return 0;
}
예제 #29
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
  }
예제 #30
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;
}