私は次の問題の解決策を見つけるために数日間インターネットを検索してきました。
私のプログラムでは、2つの16ビット.wavファイルからサウンドバッファ(タイプの配列short
)にデータのチャンクを読み取り、ヒープにメモリを割り当てています。データはdouble
fftw関数用にキャストされ、処理されてから縮小され、キャストさshort
れてコレクションバッファーに配置されてから、出力ファイルがディスクに書き込まれます。このようにして、データのいくつかのチャンクを読み取っていて(つまり、ファイル内を移動し)、各反復でディスクに書き込みたくないので、ハードディスクにアクセスする必要がある回数を減らします。
これが私がしていることです:
short* sound_buffer_zero;
short* sound_buffer_one;
short* collection_buffer_one;
sound_buffer_zero = (short *) fftw_malloc(sizeof(short) * BUFFERSIZE);
sound_buffer_one = (short *) fftw_malloc(sizeof(short) * BUFFERSIZE);
collection_buffer_one = (short *) fftw_malloc(sizeof(short) * COLLECTIONLENGTH);
// read BUFFERSIZE samples from file into sound_buffer
inFileZero.read((char*)sound_buffer_zero, sizeof(short)*BUFFERSIZE);
inFileOne.read((char*)sound_buffer_one, sizeof(short)*BUFFERSIZE);
// typecast the short int values of sound_buffer into double values
// and write them to in_
for(int p = 0; p < BUFFERSIZE; ++p) {
*(in_zero + p) = (double)*(sound_buffer_zero + p);
*(in_one + p) = (double)*(sound_buffer_one + p);
}
// cross correlation in the frequency domain
// FFT on input zero (output is f_zero)
fftw_execute(p_zero);
// FFT on input one (output is f_one)
fftw_execute(p_one);
// complex multiplication (output is almost_one, also array of type double)
fastCplxConjProd(almost_one, f_zero, f_one, COMPLEXLENGTH);
// IFFT on almost_one (output is out_one, array of double)
fftw_execute(pi_one);
// finalize the output array (sort the parts correctly, output is final_one, array of double)
// last half without first value becomes first half of final array
for(int i = ARRAYLENGTH/2 + 1; i < ARRAYLENGTH; ++i) {
*(final_one + i - (ARRAYLENGTH/2 + 1)) = *(out_one + i);
}
// first half becomes second half of final array
for(int i = 0; i < ARRAYLENGTH/2; ++i) {
*(final_one + i + (ARRAYLENGTH/2 - 1)) = *(out_one + i);
}
short* scaling_vector;
scaling_vector = (short *) fftw_malloc(sizeof(short) * ARRAYLENGTH-1);
// fill the scaling_vector with the numbers from 1, 2, 3, ..., BUFFERSIZE, ..., 3, 2, 1
for(short i = 0; i < BUFFERSIZE; ++i) {
*(scaling_vector + i) = i + 1;
if(i + BUFFERSIZE > ARRAYLENGTH-1) break;
*(scaling_vector + i + BUFFERSIZE) = BUFFERSIZE - i - 1;
}
// scale values in relation to their position in the output array
// to values suitable for short int for storage
for(int i = 0; i < ARRAYLENGTH-1; ++i) {
*(final_one + i) = *(final_one + i) * SCALEFACTOR; // #define SCALEFACTOR SHRT_MAX/pow(2,42)
*(final_one + i) = *(final_one + i) / *(scaling_vector + i);
}
// transform the double values of final_ into rounded short int values
// and write them to the collection buffer
for(int p = 0; p < ARRAYLENGTH-1; ++p) {
*(collection_buffer_one + collectioncount*(ARRAYLENGTH) + p) = (short)round(*(final_one + p));
}
// write collection_buffer to disk
outFileOne.write((char*)collection_buffer_one, sizeof(short)*collectioncount*(ARRAYLENGTH));
相互相関で計算される値はタイプdouble
であり、正または負の符号があります。それらを縮小することにより、符号は変わりません。しかしshort
、collection_arrayに到着する数値にキャストすると、すべて正になります。
配列はとしてshort
ではなく、として宣言され、unsigned short
スケーリング後、値は保持できる範囲内にあります(投稿を読みやすくするためにすべてshort
のコードを投稿したくないので、これを信頼する必要があります)。小数部の切り捨ては気にしません。それ以上の計算には必要ありませんが、符号は同じままである必要があります。
入力値と出力値の小さな例を次に示します(配列の最初の10個の値が示されています)。
input: 157
input: 4058
input: -1526
input: 1444
input: -774
input: -1507
input: -1615
input: -1895
input: -987
input: -1729
// converted to double
as double: 157
as double: 4058
as double: -1526
as double: 1444
as double: -774
as double: -1507
as double: -1615
as double: -1895
as double: -987
as double: -1729
// after the computations
after scaling: -2.99445
after scaling: -42.6612
after scaling: -57.0962
after scaling: 41.0415
after scaling: -18.3168
after scaling: 43.5853
after scaling: -14.3663
after scaling: -3.58456
after scaling: -46.3902
after scaling: 16.0804
// in the collection array and before writing to disk
collection [short(round*(final_one))]: 3
collection [short(round*(final_one))]: 43
collection [short(round*(final_one))]: 57
collection [short(round*(final_one))]: 41
collection [short(round*(final_one))]: 18
collection [short(round*(final_one))]: 44
collection [short(round*(final_one))]: 14
collection [short(round*(final_one))]: 4
collection [short(round*(final_one))]: 46
collection [short(round*(final_one))]: 16
私の質問は、なぜ標識が保持されないのですか?内部転換が欠けていますか?他の投稿で私の質問に対する答えが見つかりませんでした。見逃した場合はお知らせください。重要な情報を省略した場合もお知らせください。ご協力いただきありがとうございます!
乾杯、マンゴー
テスト出力のコードは次のとおりです。
//contents of sound_buffer (input from file):
// test output
for(int i = 0; i < 10; ++i) {
cout << "input: " << *(sound_buffer_zero + i) << endl;
}
// content of in_ after converting to double
// test output
for(int i = 0; i < 10; ++i) {
cout << "as double: " << *(in_zero + i) << endl;
}
// contents of final_ after the scaling
// test output
for(int i = 0; i < 10; ++i) {
cout << "after scaling: " << *(final_one + i) << endl;
}
// contents of collection_buffer after converting to short
// test output
for(int i = 0; i < 10; ++i) {
cout << "collection [short(round*(final_one))]: " << *(collection_buffer_one + i) << endl;
}
alegunaのおかげで、次の計算で兆候が消えることがわかりました。私は自分がしているそのステップを完全に逃していfinal_one = fabs(final_one)
ました。私はそれをテストのために入れましたが、それを完全に忘れていました。
コメントと回答ありがとうございます。結局、私はただ愚かでした。ごめんなさい。