Beispiel #1
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);
}
Beispiel #2
0
/*
 * NAME:	frame->init()
 * DESCRIPTION:	initialize frame struct
 */
void mad_frame_init(struct mad_frame *frame)
{
  mad_header_init(&frame->header);
  frame->options = 0;
//  frame->overlap = 0;
  mad_frame_mute(frame);
}
Beispiel #3
0
static int mp_init (int samplerate)
{
  mad_stream_init (&Stream);
  mad_frame_init (&Frame);
  mad_synth_init (&Synth);
  mad_header_init (&Header);
  mp_samplerate_target = samplerate;
  return 1;
}
Beispiel #4
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);
}
Beispiel #5
0
static int mp_init (music_player_t *music, int samplerate)
{
	mp_player_t *mp = (mp_player_t*)music;
  mad_stream_init (&mp->Stream);
  mad_frame_init (&mp->Frame);
  mad_synth_init (&mp->Synth);
  mad_header_init (&mp->Header);
  mp->mp_samplerate_target = samplerate;
  return 1;
}
Beispiel #6
0
int Mp3PspStream::initStream() {
	DEBUG_ENTER_FUNC();

	if (_state != MP3_STATE_INIT)
		deinitStream();

	// Init MAD
	mad_stream_init(&_stream);
	mad_header_init(&_header);

	// Reset the stream data
	_inStream->seek(0, SEEK_SET);
	_totalTime = mad_timer_zero;
	_posInFrame = 0;

	// Update state
	_state = MP3_STATE_READY;

	// Read the first few sample bytes into the buffer
	readMP3DataIntoBuffer();

	return true;
}
Beispiel #7
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);
}
Beispiel #8
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;
}
Beispiel #9
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);
}
Beispiel #10
0
static int get_format(bgav_stream_t * s)
  {
  mad_priv_t * priv;
  const char * version_string;

  struct mad_header h;
  
  priv = s->decoder_priv;

  mad_header_init(&h);
  mad_header_decode(&h, &priv->stream);
  
  /* Get audio format and create frame */

  s->data.audio.format.samplerate = h.samplerate;

  if(h.mode == MAD_MODE_SINGLE_CHANNEL)
    s->data.audio.format.num_channels = 1;
  else
    s->data.audio.format.num_channels = 2;
    
  s->data.audio.format.samplerate = h.samplerate;
  s->data.audio.format.sample_format = GAVL_SAMPLE_FLOAT;
  s->data.audio.format.interleave_mode = GAVL_INTERLEAVE_NONE;
  s->data.audio.format.samples_per_frame =
    MAD_NSBSAMPLES(&h) * 32;

  if(!s->codec_bitrate)
    {
    if(s->container_bitrate == GAVL_BITRATE_VBR)
      s->codec_bitrate = GAVL_BITRATE_VBR;
    else
      s->codec_bitrate = h.bitrate;
    }
  gavl_set_channel_setup(&s->data.audio.format);

  if(h.flags & MAD_FLAG_MPEG_2_5_EXT)
    {
    if(h.layer == 3)
      s->data.audio.preroll = s->data.audio.format.samples_per_frame * 30;
    else
      s->data.audio.preroll = s->data.audio.format.samples_per_frame;
    version_string = "2.5";
    }
  else if(h.flags & MAD_FLAG_LSF_EXT)
    {
    if(h.layer == 3)
      s->data.audio.preroll = s->data.audio.format.samples_per_frame * 30;
    else
      s->data.audio.preroll = s->data.audio.format.samples_per_frame;
    version_string = "2";
    }
  else
    {
    if(h.layer == 3)
      s->data.audio.preroll = s->data.audio.format.samples_per_frame * 10;
    else
      s->data.audio.preroll = s->data.audio.format.samples_per_frame;
    version_string = "1";
    }
  
  gavl_metadata_set_nocpy(&s->m, GAVL_META_FORMAT,
                          bgav_sprintf("MPEG-%s layer %d",
                                       version_string, h.layer));
  
  priv->audio_frame = gavl_audio_frame_create(&s->data.audio.format);
  return 1;
  }
Beispiel #11
0
// This is a shorter and faster version of scanFile(), that only scans the samplerate and number of Channels of the stream.
void mpgDecoder::readMetaFromFile( playListItem * pli )
{
#ifdef HAVE_MAD
	// use QFile as input Buffer, which is needed by libMad, cause it cannot detect EOF....
	QFile madFile(pli->getFile());
	madFile.open( QIODevice::ReadOnly );

	unsigned char buffer[65536];

	mad_stream scanStream;
	mad_header scanHeader;

	mad_stream_init (&scanStream);
	mad_header_init (&scanHeader);

	// get some more Byte from File...
	int readCnt = 0;
	while( !madFile.atEnd() && readCnt < 65536 )
	{
                buffer[readCnt] = madFile.read(1).at(0);
		readCnt++;
	}

	if (madFile.atEnd())
		return;

	mad_stream_buffer (&scanStream, buffer, readCnt );

	while (1)
        {
		if (mad_header_decode (&scanHeader, &scanStream) == -1)
		{
			if (scanStream.error == MAD_ERROR_BUFLEN)
				break;
			if (!MAD_RECOVERABLE (scanStream.error))
				break;
			continue;
		}
	}
	pli->setSamplerate( scanHeader.samplerate );
	pli->setChannels( MAD_NCHANNELS(&scanHeader) );

	mad_header_finish (&scanHeader);
	mad_stream_finish (&scanStream);
#endif
// read ID3 Metadata
#ifdef HAVE_ID3TAG
    id3_file* id3f = id3_file_open( pli->getFile().toAscii(), ID3_FILE_MODE_READONLY );
    id3_tag* id3 = id3_file_tag( id3f );

    // only overwrite metadata of playlist-item if files contains own ones...
    QString temp = getID3String(id3, ID3_FRAME_ARTIST);
    if(!temp.isEmpty())
        pli->setArtist( temp );

    temp = getID3String(id3, ID3_FRAME_TITLE);
    if(!temp.isEmpty())
        pli->setTitle( temp );

    temp = getID3String(id3, ID3_FRAME_GENRE);
    if(!temp.isEmpty())
        pli->setGenre( temp );
    id3_file_close( id3f );

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

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

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

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

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

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

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

    size -= startPos;

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

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

    double totalBitrate = 0;
    int i = 0;

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

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

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

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

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

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

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

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

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

    return 0;
}
Beispiel #13
0
static int himd_mp3stream_split_frames(struct himd_mp3stream * stream, unsigned int databytes, unsigned int firstframe, unsigned int lastframe, struct himderrinfo * status)
{
    int gotdata = 1;
    unsigned int i;
    struct mad_stream madstream;
    struct mad_header madheader;

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

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

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

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

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

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

    if(!gotdata)
        return -1;

    return 0;
}
Beispiel #14
0
static int mad_frame_seek(input_object *obj, int frame)
{
	struct mad_local_data *data;
	struct mad_header header;
	int skip;
	ssize_t byte_offset;

	if (!obj)
		return 0;
	data = (struct mad_local_data *)obj->local_data;

	if (!data || !data->seekable)
		return 0;

	//alsaplayer_error("frame_seek(..., %d)", frame);
	mad_header_init(&header);

	data->bytes_avail = 0;
	if (frame <= data->highest_frame) {
		skip = 0;

		if (frame > 4) {
			skip = 3;
		}
		byte_offset = data->frames[frame-skip];

		/* Prepare the buffer for a read */
		fill_buffer(data, byte_offset);
		mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail);
		skip++;
		while (skip != 0) {
			skip--;

			mad_frame_decode(&data->frame, &data->stream);
			if (skip == 0)
				mad_synth_frame (&data->synth, &data->frame);
		}
		data->bytes_avail = data->stream.bufend - 
			data->stream.next_frame;
		data->current_frame = frame;
		data->seeking = 0;
		return data->current_frame;
	}

	data->seeking = 1;
	fill_buffer(data, data->frames[data->highest_frame]);
	mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail);
	while (data->highest_frame < frame) {
		if (data->bytes_avail < 3072) {
			fill_buffer(data, data->map_offset + MAD_BUFSIZE - data->bytes_avail);
			mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail);
		}	
		if (mad_header_decode(&header, &data->stream) == -1) {
			if (!MAD_RECOVERABLE(data->stream.error)) {
				fill_buffer(data, 0);
				mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail);
				data->seeking = 0;
				return 0;
			}				
		}
		data->frames[++data->highest_frame] =
			data->map_offset + data->stream.this_frame - data->mad_map;
		data->bytes_avail = data->stream.bufend - data->stream.next_frame;
	}

	data->current_frame = data->highest_frame;
	if (data->current_frame > 4) {
		skip = 3;
		fill_buffer(data, data->frames[data->current_frame-skip]);
		mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail);
		skip++;
		while (skip != 0) { 
			skip--;
			mad_frame_decode(&data->frame, &data->stream);
			if (skip == 0) 
				mad_synth_frame (&data->synth, &data->frame);
			data->bytes_avail = data->stream.bufend -
				data->stream.next_frame;
		}
	}

	data->seeking = 0;
	return data->current_frame;

	return 0;
}
Beispiel #15
0
 MadDecoderPrivate()
     : outputBuffer(0),
       outputPointer(0),
       outputBufferEnd(0) {
     mad_header_init( &firstHeader );
 }
Beispiel #16
0
static int count_time_internal (struct mp3_data *data)
{
	struct xing xing;
	unsigned long bitrate = 0;
	int has_xing = 0;
	int is_vbr = 0;
	int num_frames = 0;
	mad_timer_t duration = mad_timer_zero;
	struct mad_header header;
	int good_header = 0; /* Have we decoded any header? */

	mad_header_init (&header);
	xing_init (&xing);

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

	while (1) {
		
		/* Fill the input buffer if needed */
		if (data->stream.buffer == NULL ||
			data->stream.error == MAD_ERROR_BUFLEN) {
			if (!fill_buff(data))
				break;
		}

		if (mad_header_decode(&header, &data->stream) == -1) {
			if (MAD_RECOVERABLE(data->stream.error))
				continue;
			else if (data->stream.error == MAD_ERROR_BUFLEN)
				continue;
			else {
				debug ("Can't decode header: %s",
						mad_stream_errorstr(
							&data->stream));
				break;
			}
		}

		good_header = 1;

		/* Limit xing testing to the first frame header */
		if (!num_frames++) {
			if (xing_parse(&xing, data->stream.anc_ptr,
						data->stream.anc_bitlen)
					!= -1) {
				is_vbr = 1;

				debug ("Has XING header");
				
				if (xing.flags & XING_FRAMES) {
					has_xing = 1;
					num_frames = xing.frames;
					break;
				}
				debug ("XING header doesn't contain number of "
						"frames.");
			}
		}				

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

	if (!good_header)
		return -1;

	if (!is_vbr) {
		/* time in seconds */
		double time = (data->size * 8.0) / (header.bitrate);
		
		double timefrac = (double)time - ((long)(time));

		/* samples per frame */
		long nsamples = 32 * MAD_NSBSAMPLES(&header);

		/* samplerate is a constant */
		num_frames = (long) (time * header.samplerate / nsamples);

		/* the average bitrate is the constant bitrate */
		data->avg_bitrate = bitrate;

		mad_timer_set(&duration, (long)time, (long)(timefrac*100),
				100);
	}
		
	else if (has_xing) {
		mad_timer_multiply (&header.duration, num_frames);
		duration = header.duration;
	}
	else {
		/* the durations have been added up, and the number of frames
		   counted. We do nothing here. */
		debug ("Counted duration by counting frames durations in "
				"VBR file.");
	}

	if (data->avg_bitrate == -1
			&& mad_timer_count(duration, MAD_UNITS_SECONDS) > 0) {
		data->avg_bitrate = data->size 
				/ mad_timer_count(duration, MAD_UNITS_SECONDS) * 8;
	}

	mad_header_finish(&header);

	debug ("MP3 time: %ld", mad_timer_count (duration, MAD_UNITS_SECONDS));

	return mad_timer_count (duration, MAD_UNITS_SECONDS);
}
Beispiel #17
0
    int64 MadDecoder::getDurationMs(unsigned char* buffer, size_t bufferSize)
    {
        struct mad_stream madStream;
        struct mad_frame  madFrame;
        struct mad_header madHeader;
        mad_timer_t  time = mad_timer_zero;

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


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

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

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

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

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

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

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

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

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

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

        return mad_timer_count(time, MAD_UNITS_MILLISECONDS);
    }
Beispiel #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);
}
Beispiel #19
0
// the following function has been copied from XMMS' mad input plugin
// Copyright (C) 2001-2002 Sam Clegg
void mpgDecoder::scanFile( )
{
#ifdef HAVE_MAD
  mad_stream scanStream;
  mad_header scanHeader;
  int remainder = 0;
  int data_used = 0;
  int pos = 0;
  unsigned char buffer[4096];

  // reset file, so we can read from the beginning
  madFile->reset();
  mad_timer_reset( endPositionTimer );

  mad_stream_init (&scanStream);
  mad_header_init (&scanHeader);
  while (1)
    {
      remainder = scanStream.bufend - scanStream.next_frame;
      memcpy (buffer, scanStream.this_frame, remainder);
	// get some more Byte from File...
	int readCnt = 0;
	unsigned char* readStart;
	readStart = buffer+remainder;
	while( !madFile->atEnd() && readCnt < (4096 - remainder) )
	{
                readStart[readCnt] = madFile->read(1).at(0);
		readCnt++;
	}

      if (madFile->atEnd())
	break;

      mad_stream_buffer (&scanStream, buffer, readCnt + remainder);

      while (1)
        {
	  if (mad_header_decode (&scanHeader, &scanStream) == -1)
	    {
	      if (scanStream.error == MAD_ERROR_BUFLEN)
		{
		  break;
		}
	      if (!MAD_RECOVERABLE (scanStream.error))
		{
		  break;
		}
	      continue;
	    }
	  pos++;
	  data_used += scanStream.next_frame - scanStream.this_frame;
      mad_timer_add( endPositionTimer, scanHeader.duration );
	  if (pos == 1)
	    {
          sampleRate = scanHeader.samplerate;
	      channels = MAD_NCHANNELS(&scanHeader);
	    }
	}
      if (scanStream.error != MAD_ERROR_BUFLEN)
	break;
    }

  mad_header_finish (&scanHeader);
  mad_stream_finish (&scanStream);

  // reset the file again, so we can read from the beginning when playing
  madFile->reset();
#endif
}