2016-08-30 20 views
1

同時サウンドが必要なアンドロイドオーディオアプリを開発しています。2つのオーディオバッファを混在させたときのクリック/歪み

私は2つのサウンドバッファを組み合わせようとしており、大きな振幅で歪みを得ています。

for(int i=0;i<data2.length;i+=2) 
      { 

       short buf1a = data[i+1]; 
       short buf2a = data[i]; 
       buf1a = (short)((buf1a & 0xff) << 8); 
       buf2a = (short) (buf2a & 0xff); 
       short buf1b = data2[i+1]; 
       short buf2b = data2[i]; 
       buf1b = (short) ((buf1b & 0xff) << 8); 
       buf2b = (short) (buf2b & 0xff); 

       short buf1c = (short) (buf1a + buf1b); 
       short buf2c = (short) (buf2a + buf2b); 

       short res = (short) (buf1c + buf2c); 
     int res2 = res/2; 
     res = (short)res2; 
       data3[i]=(byte)res; 
       data3[i+1]=(byte)(res>>8); 

      } 

バッファを使用して再生されます:: これは私がやっているものですJava: Mixing two WAV files without introducing noise

AudioTrack at = new AudioTrack(STREAM_MUSIC,44100,CHANNEL_OUT_MONO,ENCODING_PCM_16BIT,dataSize,MODE_STATIC); 
      at.write(data3,0,data3.length); 
      int frames = data3.length/2; //2 bytes per frame. 
      Log.d(TAG,"this is data length: "+data3.length); 
      Log.d(TAG,"this is assumed frame number:"+frames); 
      at.setLoopPoints(0,frames,3); 
      at.play(); 

私はほぼ正確にここで説明する手順に従いました。

バッファdataとdata2には、ミックスするwavファイルのデータが含まれています。 AudioTrackを使って自分で演奏するときは、音が綺麗です。また、「高振幅クリック」とは別に、ミックスはうまく聞こえます。

私は、短い値が最大振幅では大きすぎると仮定しましたが、私は2で割るので、理由はわかりません。

更新:私はwavにミックスを出力し、それをAudacityで見ました。 下の一番上の波形は、クリックとのミックスです。下の波形は、Audacityが2つのwavをミックスし、クリックがない場合です。波形がグラフの '屋根'/'床'に接触すると、ミックスのクリックが発生します。 私のミックスは、これらの場所でより広いピークを持つように見えます。まだこれを解決していない。 enter image description here 更新2: これは、問題領域が近づいているように見えます。それはAudacityバージョンのように最高/最低値(床/屋根)にカットされますが、私のバージョンでは、それは反対側にジャンプし、そこのカーブを「終了」しているようです。 enter image description here

答えて

1

あなたのコードは私を鼓舞し、同じ問題に直面しました。 buf1abuf1bbuf2abuf2bという値を16バイト短く加算して、結果を16バイトの短いbuf1cbuf2cにキャストします。加算の結果は、Oracleドキュメントから抽出

...それはshortデータ型の容量を超えるbecouse 32,767次いで-32,768以上loss conversation occours次に低い場合:

は狭くプリミティブ変換が情報を失う可能性があり数値の全体的な大きさであり、精度と範囲も失う可能性があります。

short buf1c = (short) (buf1a + buf1b); 
short buf2c = (short) (buf2a + buf2b); 

私の簡単な修正:)。これは歪みなく完全に動作します:

int buf1c = (buf1a + buf1b)/2; 
int buf2c = (buf2a + buf2b)/2; 
+0

ありがとう!はい、そのソリューションははるかに良いです - 私はあなたのソリューションに私のコードで今変更し、素晴らしい動作します。 :) – gnyrfta

2

私は、大きな数字が突然サインを変更したかどうかをチェックすることでクリップを取り除くことができました。 forループの最後に追加された以下のコードは仕事をしていると思われ、上記の質問で大胆グラフがどのように見えるかのような結果が得られます。

 if(res>10000) //Avoid 'normal' cases where amplitude shifts from f.ex. 4 to -2, which we want to keep. 
     { 
      if((res*resPrevious)<0) //If the sign has changed suddenly for a large number, use the previous number. 
      { 
       Log.d(TAG,"res:"+res+""); 
       res = resPrevious; 
      } 
     } 
     if(res<-10000) 
     { 
      if((res*resPrevious)<0) //If the sign has changed suddenly for a large number, use the previous number. 
      { 
       res = resPrevious; 
      } 
     } 
     resPrevious=res; 
     data3[i] = (byte) res; 
     data3[i + 1] = (byte) (res >> 8); 
関連する問題