-1

Java サウンド ( javax.sound パッケージ ) について、あまり単純ではない質問があります。

クロスフェードとスムーズなボリュームとシーク コントロールを備えた MP3 プレーヤーを実装しています。

サウンドを 4096 バイトのチャンクでストリームとして読み取り、位置をミリ秒単位で手動で計算しています。

seek() (ストリームが赤くなる場所からベース位置を変更) したいとき、音波で本当に醜い「ジャンプ」が聞こえます。JLayer やその他の MP3 API を調べてみましたが、seek() 関数がまったくないか、この「醜いサウンド ジャンプ」もあります。

私の質問は次のとおりです。1 つの音波チャンクから別の音波チャンクへのこのジャンプをよりスムーズにするにはどうすればよいですか? 補間を試みましたが、「ジャンプが聞こえない」までの妥当な時間は 300 ミリ秒であり、seek() 関数には長すぎます。

この問題に遭遇しましたか?

解決策を知っていますか?

念のため、ここにコード サンプルを貼り付けます。

public void seek( long pPosition )
{
  sourceDataLine.flush();

  seekIndex = ( sourceDataLine.getMicrosecondPosition() / 1000 ) - currentPositionInMilliseconds;

}

public long getPositionInMilliseconds()
{ return ( sourceDataLine.getMicrosecondPosition() / 1000 ) - seekIndex; }

javax.sound の DataLine API のため、「ミリ秒単位の位置」が必要です。

ありがとう イライラする…

4

2 に答える 2

0

これを行う唯一の方法は、フレームごとのレベルでデータを直接操作することです。バイトを取得して直接計算を行うには、サウンドを「開く」必要があります。ほとんどのビルトイン Java コントロールは、バッファのサイズによって妨げられる粒度を持っています。つまり、サウンド データ バッファごとに 1 つのボリューム変更しか処理できません。

フレームごとのレベルで作業している場合でも、Java にはリアルタイムの保証がないため、克服しなければならない問題があります。しかし、それらは克服可能です。

たとえば、クリップに相当するものを原音とする「クリップスライサー」を作りました。サンプルのランダムなスライスを取り、それらをつなぎ合わせます。わずか 16 フレームのオーバーラップ補間で、サウンドの流れをスムーズに保ちます。16 フ​​レームのオーバーラップを含む 1/10 秒のスライスを使用すると、4 秒間の録画から無限に流れる小川を作成するのにうまく機能しました。

ボリュームとピッチのマウス モーション リスナーの位置を取るテルミンを作成しました。約 30 または 40 フレームのレイテンシで非常にスムーズに動作するようになりました。トリックは、マウスモーションリスナーの出力にタイムスタンプを付け、そのデータに基づいて行われた計算に基づいて制御を行うことでした。これは、イベントが到着しないか、リアルタイムでスムーズに処理されず、ジッパリングやその他の不連続が生じるためです。

考慮すべきもう 1 つの点は、データの範囲がデシベルにうまく対応していないことです。そのため、ローエンドでの小さなボリューム差は、ハイエンドでの同じボリューム間隔よりもはるかに不連続です (そしてクリックが発生しやすくなります)。これを解決するには、オーディオ データをデシベル ボリュームにマッピングし、振幅マッピングに基づいてボリュームの変化量を調整しました。これらのアイデアのいくつかが役立つことを願っています!

于 2013-07-15T01:04:56.997 に答える
0

トランジションするチャンクが短すぎてクロスフェードできない場合、スムーズなトランジションを実際に作成することはできませんが、境界から最悪のアーティファクトを排除することはできます。

私が言及している悪いアーティファクトは、クリックやポップのように聞こえることがよくありますが、短い連続で多数ある場合は、スラッシング サウンドのように聞こえるか、間隔が規則的であれば、独自の特定のピッチを導入することさえあります。この種のアーティファクトは、オーディオの任意のブロックを作成した結果です。これは、境界でのオーディオの振幅が 1 つのブロックから次のブロックにジャンプしたり、ブロックの最後から無音になったりする可能性があるためです。これを解消するにはいくつかの方法がありますが、最も一般的な方法は、境界を任意の位置から最も近い「ゼロ クロッシング」に移動して、ジャンプや不連続がなくなるようにすることです。または、ブロックが重なり合って腐敗しているため、ブロックの値が互いに交差する場所、できれば同じ方向に向かう場所を見つけるために何かをすることができます。

于 2013-07-14T20:24:26.247 に答える