私は、テキスト読み上げ合成のための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で私のアルゴリズムをテストし、うまくいきました。
私はあなたが試した変更とあなたが期待している結果についてもう少し明確にすべきだと思います。 あなたは私たちに問題を与えており、コード全体をコピーアンドペーストすることによって解決策を期待しています。 また、リファクタリングを実行するのにも役立つでしょうか(おそらくいくつかのOO?) –
は、短くなっていないことをチェックします。バイトですべての処理を行うことを強くお勧めします。 〜とナンセンスショート – gpasch