2016-12-15 10 views
0

私は、テキスト読み上げ合成のためのJavaプログラム(他人が開発した)を使って作業しています。合成は、「ディフォン」の連結によって行われる。 Orginalバージョンでは、信号処理はありませんでした。ジフォンはちょうど集められ、一緒に連結されて出力を生成した。出力を向上させるために、私は連結音声信号の "位相整合"を試みた。私が作った変更はここに要約されています:どのように信号重複のノイズを減らすには、Javaで追加?

  • オーディオデータは、AudioInputStreamからバイト配列に集められます。 オーディオデータは16ビットなので、バイト配列を短い 配列に変換しました。
  • "信号処理"は、短い配列に対して行われます。
  • オーディオデータを出力するには、short配列を再びバイト配列に変換します。このセグメントは、すべてのディフォーンのために呼び出され

    オーディオ入力:

は、ここで私は、既存のプログラムに変更したコードの一部です。

オリジナルバージョン

audioInputStream = AudioSystem.getAudioInputStream(sound); 
while ((cnt = audioInputStream.read(byteBuffer, 0, byteBuffer.length)) != -1) { 
    if (cnt > 0) { 
     byteArrayPlayStream.write(byteBuffer, 0, cnt); 
    } 
} 

マイバージョン

// public varialbe declarations 
byte byteSoundFile[];        // byteSoundFile will contain a whole word or the diphones of a whole word 
short shortSoundFile[] = new short[5000000]; // sound contents are taken in a short[] array for signal processing 
short shortBuffer[]; 
int  pos     = 0; 
int  previousPM   = 0; 
boolean isWord    = false; 
public static HashMap<String, Integer> peakMap1 = new HashMap<String, Integer>(); 
public static HashMap<String, Integer> peakMap2 = new HashMap<String, Integer>(); 

// code for receiving and processing audio data 
if(pos == 0) { 
    // a new word is going to be processed. 
    // so reset the shortSoundFile array 
    Arrays.fill(shortSoundFile, (short)0); 
} 

audioInputStream = AudioSystem.getAudioInputStream(sound); 
while ((cnt = audioInputStream.read(byteBuffer, 0, byteBuffer.length)) != -1) { 
    if (cnt > 0) { 
     byteArrayPlayStream.write(byteBuffer, 0, cnt); 
    } 
} 

byteSoundFile = byteArrayPlayStream.toByteArray(); 
int nSamples = byteSoundFile.length; 
byteArrayPlayStream.reset(); 

if(nSamples > 80000) { // it is a word 
    pos  = nSamples; 
    isWord = true; 
} 
else {    // it is a diphone 
    // audio data is converted from byte to short, so nSamples is halved 
    nSamples /= 2; 

    // transfer byteSoundFile contents to shortBuffer using byte-to-short conversion 
    shortBuffer = new short[nSamples]; 
    for(int i=0; i<nSamples; i++) { 
     shortBuffer[i] = (short)((short)(byteSoundFile[i<<1]) << 8 | (short)byteSoundFile[(i<<1)+1]); 
    } 

    /************************************/ 
    /**** phase-matching starts here ****/ 
    /************************************/ 
    int pm1 = 0; 
    int pm2 = 0; 
    String soundStr = sound.toString(); 
    if(soundStr.contains("\\") && soundStr.contains(".")) { 
     soundStr = soundStr.substring(soundStr.indexOf("\\")+1, soundStr.indexOf(".")); 
    }      
    if(peakMap1.containsKey(soundStr)) { 
     // perform overlap and add 
     System.out.println("we are here"); 
     pm1 = peakMap1.get(soundStr); 
     pm2 = peakMap2.get(soundStr); 

     /* 
     Idea: 
     If pm1 is located after more than one third of the samples, 
     then threre will be too much overlapping. 
     If pm2 is located before the two third of the samples, 
     then where will also be extra overlapping for the next diphone. 
     In both of the cases, we will not perform the peak-matching operation. 
     */ 
     int idx1 = (previousPM == 0) ? pos : previousPM - pm1; 
     if((idx1 < 0) || (pm1 > (nSamples/3))) { 
      idx1 = pos; 
     } 
     int idx2 = idx1 + nSamples - 1; 
     for(int i=idx1, j=0; i<=idx2; i++, j++) { 
      if(i < pos) { 
       shortSoundFile[i] = (short) ((shortSoundFile[i] >> 1) + (shortBuffer[j] >> 1)); 
      } 
      else { 
       shortSoundFile[i] = shortBuffer[j]; 
      } 
     } 
     previousPM = (pm2 < (nSamples/3)*2) ? 0 : idx1 + pm2; 
     pos = idx2 + 1; 
    } 
    else { 
     // no peak found. simply concatenate the audio data 
     for(int i=0; i<nSamples; i++) { 
      shortSoundFile[pos++] = shortBuffer[i]; 
    } 
    previousPM = 0; 
} 

オーディオ出力
単語のすべてのディフォーンを収集した後、このセグメントは、オーディオ出力を再生するために呼び出されます。
オリジナルバージョン

byte audioData[] = byteArrayPlayStream.toByteArray(); 
... code for writing audioData to output steam 

マイバージョン

byte audioData[]; 
if(isWord) { 
    audioData = Arrays.copyOf(byteSoundFile, pos); 
    isWord = false; 
} 
else { 
    audioData = new byte[pos*2]; 
    for(int i=0; i<pos; i++) { 
     audioData[(i<<1)] = (byte) (shortSoundFile[i] >>> 8); 
     audioData[(i<<1)+1] = (byte) (shortSoundFile[i]); 
    } 
} 
pos = 0; 
... code for writing audioData to output steam 

しかし、変更が行われた後、出力が悪くなってきました。出力には多くのノイズがあります。ここで

は、修正したサンプルのオーディオである:ここでmodified output

は、元のバージョンからのサンプルのオーディオです:誰でもノイズを発生する理由を指摘することができるかどうoriginal output

今、私はそれを感謝し、それを取り除く方法。コードで何か間違っているのですか?私はMablabで私のアルゴリズムをテストし、うまくいきました。

+0

私はあなたが試した変更とあなたが期待している結果についてもう少し明確にすべきだと思います。 あなたは私たちに問題を与えており、コード全体をコピーアンドペーストすることによって解決策を期待しています。 また、リファクタリングを実行するのにも役立つでしょうか(おそらくいくつかのOO?) –

+0

は、短くなっていないことをチェックします。バイトですべての処理を行うことを強くお勧めします。 〜とナンセンスショート – gpasch

答えて

0

問題は一時的に解決されました。 byteアレイとshortアレイの間の変換は必要ないことが判明しました。必要な信号処理操作は、byteアレイで直接実行できます。
私はこの質問を開いて、誰かが特定のコードでバグを見つけた場合に備えて開いておきたいと思います。

関連する問題