2012-04-02 18 views
2

私は、mp3ストリームのデコードと再生を含むプロジェクトに入る予定です。mp3でシークを実装する方法

私はJavaデコーダ(JLayer)を持っていますが、シーク機能はありません(私は組み込みのプレーヤーを使用しません。自分のプレーヤーを実装する必要があります)。

また、ストリームは暗号化されているため、リアルタイムで復号化+復号化する必要があります。復号化されたファイル全体を持つことはできません。

だから、どのようにmp3ストリームを求めてアプローチしますか?私は時間値を設定し、デコードするファイル内の適切なオフセットを取得したいと思います。

VBRのサポートも検討してください。

ありがとうございました

+0

すでにデコードされ、読み込まれたMP3を使用すると簡単にシークできます。まだAudioInputStreamには形成されておらず、特にVBR MP3では難しいものではそれほど簡単ではありません。 –

+0

純粋なJavaである必要がありますか? [CASampledSP](http://www.tagtraum.com/casampledsp/apidocs/com/tagtraum/casampledsp/CAAudioInputStream.html)は、カスタムの 'seek()'メソッドをサポートしています。[MFSampledSP](http: /www.tagtraum.com/mfsampledsp/apidocs/com/tagtraum/mfsampledsp/MFAudioInputStream.html)。 CASampledSPは、Windows 7以降ではMFSampledSP(MF = MediaFoundation) – hendrik

答えて

1

私はまったく同じことを探しています。 JLayerのコードはやや乱雑です。 mp3デコードコアが書かれた(またはどこかから取られた)ので、Javaに移植されたことを確信して、余計に最適でないレイヤーが追加されました。いかなる場合でも。シークするには、プレーヤーのコードを見てください(http://code.google.com/p/jesuifoo/source/browse/trunk/src/javazoom/jlgui/basicplayer/BasicPlayer.java?r=23)

/** 
    * Skip bytes in the File inputstream. It will skip N frames matching to 
    * bytes, so it will never skip given bytes length exactly. 
    * 
    * @param bytes 
    * @return value>0 for File and value=0 for URL and InputStream 
    * @throws BasicPlayerException 
    */ 
    protected long skipBytes(long bytes) throws BasicPlayerException { 
      long totalSkipped = 0; 
      if (m_dataSource instanceof File) { 
        log.info("Bytes to skip : " + bytes); 
        int previousStatus = m_status; 
        m_status = SEEKING; 
        long skipped = 0; 
        try { 
          synchronized (m_audioInputStream) { 
            notifyEvent(BasicPlayerEvent.SEEKING, 
                getEncodedStreamPosition(), -1, null); 
            initAudioInputStream(); 
            if (m_audioInputStream != null) { 
              // Loop until bytes are really skipped. 
              while (totalSkipped < (bytes - SKIP_INACCURACY_SIZE)) { 
                skipped = m_audioInputStream.skip(bytes 
                    - totalSkipped); 
                if (skipped == 0) 
                  break; 
                totalSkipped = totalSkipped + skipped; 
                log.info("Skipped : " + totalSkipped + "/" + bytes); 
                if (totalSkipped == -1) 
                  throw new BasicPlayerException(
                      BasicPlayerException.SKIPNOTSUPPORTED); 
              } 
            } 
          } 
          notifyEvent(BasicPlayerEvent.SEEKED, 
              getEncodedStreamPosition(), -1, null); 
          m_status = OPENED; 
          if (previousStatus == PLAYING) 
            startPlayback(); 
          else if (previousStatus == PAUSED) { 
            startPlayback(); 
            pausePlayback(); 
          } 
        } catch (IOException e) { 
          throw new BasicPlayerException(e); 
        } 
      } 
      return totalSkipped; 
    } 

このルーチンは、ビットストリームをデコードせずにどのように進めるのかを示します(m_audioInputStream.skip(...))。私はそれが最初からスキップされているかどうか(前にinitAudioStream呼び出しがあります)、または現在の再生位置からかどうかはわかりません。

フレームは個別にスキップされるので、VBRは問題ありません。

解読に関しては、このルーチンは個々のフレームを入力ストリームから読み取ったものとしてスキップするので問題にならない。入力ストリームがデコードをサポートしていれば、それはwokrでなければなりません。どのくらい速いのかは別の質問です。その場合は、mp3のインデックスを作成して、ジャンプしてデコードする位置を知っている方が良いかもしれませんが、それはやや異なったトピックです:暗号化されたストリームを探す方法。

+0

で動作します.4年後、私は実際にJLayerのポートへのリンクでこの回答を拡張したいと考えています。これは約4倍高速で、正確なバイト位置でストリームをシーク/デコードする方法に関するデモンストレーション可能なコードを提供しています。http://bpmdj.yellowcouch.org/credits.html JLayer 1.0.1のセクションを参照してください。これには、図書館と例の両方の公開リポジトリへのリンクがあります。 –

関連する問題