⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maddecoder.cpp

📁 OggPlay for Symbian 是symbian上的一个媒体播放程序的源码。它支持ogg,wav等等多媒体格式。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
     */

    getframeinfo();
//    if(iFrameCount==0) {
//        getframeinfo();
//        gettaginfo();
//    }

    /* 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!
     */
    iFrameCount++;
    mad_timer_add(&iTimer,iFrame.header.duration);

    if(iPlaystate==EREVERSE) {
      jumpseek();
      continue;
    }

    if(iPlaystate==EFASTFORWARD) {
      /* This should be the right way to do it.
         Unfortunately, it's too slow on flash-based low power devices
         like ours.

      if(mad_timer_compare(iGlobalTimer,iTimer)>0) {
        continue;
      } else {
        iPlaystate=EPLAY;
      }
      */
      jumpseek();
      continue;

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

    /* Synthesized samples must be converted from libmad's fixed
     * point number to the consumer format. Here we use unsigned
     * 16 bit little endian integers on two channels. Integer samples
     * are temporarily stored in a buffer that is flushed when
     * full.
     */
    if(outputbuffer) { 
      int CurrentBytesWritten=mad_outputpacket(iOutputPtr,iOutputBufferEnd);
      BytesWritten+=CurrentBytesWritten;
      iOutputPtr+=CurrentBytesWritten;
      // it's full already
      if(!CurrentBytesWritten||iRememberPcmSamples) return BytesWritten;
    }
    else {
          // remember the remaining samples:
          iRememberPcmSamples=iSynth.pcm.length;
          return BytesWritten;
    }

  }

}

TInt CMadDecoder::Channels()
{
  if(iFrame.header.mode==MAD_MODE_SINGLE_CHANNEL) {
      //TRACEF(_L("CMadDecoder::Channels: 1 channel"));

    return 1;
  }
      //TRACEF(_L("CMadDecoder::Channels: 2 channels"));
  return 2;
}

TInt CMadDecoder::Rate()
{
  //TRACEF(COggLog::VA(_L("CMadDecoder::Rate:%d"), iFrame.header.samplerate ));
  return iFrame.header.samplerate;
}

TInt CMadDecoder::Bitrate()
{ 
  //TRACEF(COggLog::VA(_L("CMadDecoder::Bitrate:%d"), iFrame.header.bitrate ));
  return iFrame.header.bitrate;
}

TInt64 CMadDecoder::Position()
{ 
  signed long timer=mad_timer_count(iTimer,MAD_UNITS_MILLISECONDS);
  TInt64 pos;
  pos=(TInt)timer;
  return pos;
}

void CMadDecoder::Setposition(TInt64 aPosition)
{
    unsigned long ms;
    if(aPosition<0) aPosition=0;
    ms=(unsigned long) aPosition.Low();
    mad_timer_set(&iGlobalTimer,0,ms,1000);
    if(mad_timer_compare(iGlobalTimer,iTimer)>0) {
        iPlaystate=EFASTFORWARD;
    } else {
        iPlaystate=EREVERSE;
    }
    
}

TInt64 CMadDecoder::TimeTotal()
{
  signed long timer;
  if(mad_timer_compare(iTotalTime,mad_timer_zero)!=0)
    timer=mad_timer_count(iTotalTime,MAD_UNITS_MILLISECONDS);
  else if(mad_timer_compare(iEstTotalTime,mad_timer_zero)!=0)
    timer=mad_timer_count(iEstTotalTime,MAD_UNITS_MILLISECONDS);
  else
    timer=0;
  TInt64 pos;
  pos=(TInt)timer;
  return pos;
  
}

TInt CMadDecoder::FileSize()
{
  return iFilesize;
}

void CMadDecoder::ParseTags(TDes& aTitle, TDes& aArtist, TDes& aAlbum, TDes& aGenre, TDes& aTrackNumber) {
  //TRACEF(_L("CMadDecoder::ParseTags"));
  aArtist.SetLength(0);
  aTitle.SetLength(0);
  aAlbum.SetLength(0);
  aGenre.SetLength(0);
  aTrackNumber.SetLength(0);

  if(id3tag || filetag) {
    Id3GetString(aTitle,ID3_FRAME_TITLE);
    Id3GetString(aArtist,ID3_FRAME_ARTIST);
    Id3GetString(aAlbum,ID3_FRAME_ALBUM);
    Id3GetString(aTrackNumber,ID3_FRAME_TRACK);
    Id3GetString(aGenre,ID3_FRAME_GENRE);
  } else {
    //FIXMAD: breakpoint for testing
    int i=5;
    i++;
  }
}

void CMadDecoder::Id3GetString(TDes& aString,char const *id)
{
  struct id3_frame const *frame;
  id3_ucs4_t const *ucs4;
  id3_utf8_t* utf8;
  union id3_field const *field;
  struct id3_tag* tagtouse;

  if(id3tag) { tagtouse=id3tag; } // ID3V2 tag
  else if(filetag) { tagtouse=id3_file_tag(filetag); } //ID3V1
  else return; 

  frame = id3_tag_findframe(tagtouse,id,0);
  if (frame) 
  {
    field = id3_frame_field(frame, 1);
    ucs4 = id3_field_getstrings(field, 0);
    if (strcmp(id, ID3_FRAME_GENRE) == 0) ucs4 = id3_genre_name(ucs4);
    if(ucs4)
    {
      utf8=id3_ucs4_utf8duplicate(ucs4);
      TPtrC8 p((const unsigned char *)utf8);  
      CnvUtfConverter::ConvertToUnicodeFromUtf8(aString,p);
      free(utf8);
      utf8=NULL;
    }
  }
}

void CMadDecoder::GetFrequencyBins(TInt32* /*aBins*/,TInt /*NumberOfBins*/)
{
}


/*
 * NAME:	get_id3()
 * DESCRIPTION:	read and parse an ID3 tag from a stream
 */
struct id3_tag* CMadDecoder::get_id3(struct mad_stream *stream, id3_length_t tagsize)
{
//  struct id3_tag *tag = 0;
  id3_length_t count;
  id3_byte_t const *data;
  id3_byte_t *allocated = 0;

  count = stream->bufend - stream->this_frame;

  if (tagsize <= count) {
    data = stream->this_frame;
    mad_stream_skip(stream, tagsize);
  }
  else {
    allocated = (id3_byte_t*)malloc(tagsize);
    if (allocated == 0) {
      //error("id3", _("not enough memory to allocate tag data buffer"));
      goto fail;
    }

    memcpy(allocated, stream->this_frame, count);
    mad_stream_skip(stream, count);

    while (count < tagsize) {
      int len;
      do
        len = BstdRead(allocated + count, 1,tagsize - count,iBstdFile  );
      while (len == -1 );

      if (len == -1) {
      //	error("id3", ":read");
	      goto fail;
      }

      if (len == 0) {
      //	error("id3", _("EOF while reading tag data"));
	      goto fail;
      }

      count += len;
    }

    data = allocated;
  }

  id3tag = id3_tag_parse(data, tagsize); //FXIMAD: leak?

 fail:
  if (allocated) {
    free(allocated);
    allocated=NULL;
  }

  return id3tag;
}


void CMadDecoder::MadHandleError() 
{
  signed long tagsize;

	/* Do nothing 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(iStream.error!=MAD_ERROR_LOSTSYNC ||
		 iStream.this_frame!=iGuardPtr)
	{
    // recoverable frame level error:
    // ahm, do ... nothing
	}

  if(iStream.error== MAD_ERROR_LOSTSYNC) {
    tagsize = id3_tag_query(iStream.this_frame,iStream.bufend - iStream.this_frame);
    if (tagsize > 0) {
        
        id3tag = get_id3(&iStream, tagsize);
        if (id3tag) {
            process_id3(id3tag);
        }
     }
  }

}

/*
* NAME:	process_id3()
* DESCRIPTION:	display and process ID3 tag information
*/

void CMadDecoder::process_id3(struct id3_tag const *tag)
{
  struct id3_frame const *frame;
    
  /* length information */
  
  frame = id3_tag_findframe(tag, "TLEN", 0);
  if (frame) {
    union id3_field const *field;
    unsigned int nstrings;
    
    field    = id3_frame_field(frame, 1);
    nstrings = id3_field_getnstrings(field);
    
    if (nstrings > 0) {
      id3_latin1_t *latin1;
      
      latin1 = id3_ucs4_latin1duplicate(id3_field_getstrings(field, 0));
      if (latin1) {
        signed long ms;
        
        /*
        * "The 'Length' frame contains the length of the audio file
        * in milliseconds, represented as a numeric string."
        */
        
        ms = atoi((const char*)latin1);
        if (ms > 0)
          mad_timer_set(&iTotalTime, 0, ms, 1000);
        
        free(latin1);
        latin1=NULL;
      }
    }
  }
  
  /* relative volume adjustment information */
//IMPROVE_MAD: RGAIN_SUPPORT 
//  if ((player->options & PLAYER_OPTION_SHOWTAGSONLY) ||
//    !(player->options & PLAYER_OPTION_IGNOREVOLADJ)) {
  if(0) {
    frame = id3_tag_findframe(tag, "RVA2", 0);
    if (frame) {
      id3_latin1_t const *id;
      id3_byte_t const *data;
      id3_length_t length;
      
      enum {
        CHANNEL_OTHER         = 0x00,
          CHANNEL_MASTER_VOLUME = 0x01,
          CHANNEL_FRONT_RIGHT   = 0x02,
          CHANNEL_FRONT_LEFT    = 0x03,
          CHANNEL_BACK_RIGHT    = 0x04,
          CHANNEL_BACK_LEFT     = 0x05,
          CHANNEL_FRONT_CENTRE  = 0x06,
          CHANNEL_BACK_CENTRE   = 0x07,
          CHANNEL_SUBWOOFER     = 0x08
      };
      
      id   = id3_field_getlatin1(id3_frame_field(frame, 0));
      data = id3_field_getbinarydata(id3_frame_field(frame, 1), &length);
      
//      assert(id && data);
      
      /*
      * "The 'identification' string is used to identify the situation
      * and/or device where this adjustment should apply. The following is
      * then repeated for every channel
      *
      *   Type of channel         $xx
      *   Volume adjustment       $xx xx
      *   Bits representing peak  $xx
      *   Peak volume             $xx (xx ...)"
      */
      
      while (length >= 4) {
        unsigned int peak_bytes;
        
        peak_bytes = (data[3] + 7) / 8;
        if (4 + peak_bytes > length)
          break;
        
        if (data[0] == CHANNEL_MASTER_VOLUME) {
          signed int voladj_fixed;
          double voladj_float;
          
          /*
          * "The volume adjustment is encoded as a fixed point decibel
          * value, 16 bit signed integer representing (adjustment*512),
          * giving +/- 64 dB with a precision of 0.001953125 dB."
          */
          
          voladj_fixed  = (data[1] << 8) | (data[2] << 0);
          voladj_fixed |= -(voladj_fixed & 0x8000);
          
          voladj_float  = (double) voladj_fixed / 512;
          
 //         set_gain(player, GAIN_VOLADJ, voladj_float);
          
//          if (player->verbosity >= 0) {
//            detail(_("Relative Volume"),
//              _("%+.1f dB adjustment (%s)"), voladj_float, id);
//          }
          
          break;
        }
        
        data   += 4 + peak_bytes;
        length -= 4 + peak_bytes;
      }
    }
  }

//IMPROVE_MAD: RGAIN_SUPPORT 
  
  /* Replay Gain */
  
//  if ((player->options & PLAYER_OPTION_SHOWTAGSONLY) ||
//    ((player->output.replay_gain & PLAYER_RGAIN_ENABLED) &&
//    !(player->output.replay_gain & PLAYER_RGAIN_SET))) {
//    frame = id3_tag_findframe(tag, "RGAD", 0);
//    if (frame) {
//      id3_byte_t const *data;
//      id3_length_t length;
//      
//      data = id3_field_getbinarydata(id3_frame_field(frame, 0), &length);
//      assert(data);
//      
//      /*
//      * Peak Amplitude                          $xx $xx $xx $xx
//      * Radio Replay Gain Adjustment            $xx $xx
//      * Audiophile Replay Gain Adjustment       $xx $xx
//      */
//      
//      if (length >= 8) {
//        struct mad_bitptr ptr;
//        mad_fixed_t peak;
//        struct rgain rgain[2];
//        
//        mad_bit_init(&ptr, data);
//        
//        peak = mad_bit_read(&ptr, 32) << 5;
//        
//        rgain_parse(&rgain[0], &ptr);
//        rgain_parse(&rgain[1], &ptr);
//        
//        use_rgain(player, rgain);
//        
//        mad_bit_finish(&ptr);
//      }
//    }
//  }
}

void CMadDecoder::gettaginfo(void) {
        
  if (xltag.flags == 0 &&	tag_parse(&xltag, &iStream) == 0) {
    unsigned int frame_size;

//IMPROVE_MAD: RGAIN_SUPPORT 
//	if ((xltag.flags & xltag_LAME) &&
//	    (player->output.replay_gain & PLAYER_RGAIN_ENABLED) &&
//	    !(player->output.replay_gain & PLAYER_RGAIN_SET))
//	  use_rgain(player, xltag.lame.replay_gain);
//      }

    if ((xltag.flags & TAG_XING) &&
        (xltag.xing.flags & TAG_XING_FRAMES)) {
      iTotalTime = iFrame.header.duration;
      mad_timer_multiply(&iTotalTime, xltag.xing.frames);
    }

    /* total stream byte size adjustment */

    frame_size = iStream.next_frame - iStream.this_frame;

    if (iFilesize == 0) {
      if ((xltag.flags & TAG_XING) && (xltag.xing.flags & TAG_XING_BYTES) &&
        xltag.xing.bytes > frame_size)
        iFilesize = xltag.xing.bytes - frame_size;
    }
    else if (iFilesize >= iStream.next_frame - iStream.this_frame)
	      iFilesize -= frame_size;
  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -