2

編集2

この問題の詳細については、他のSO の質問を参照してください。

編集1

この投稿を更新したため、内容が Alexey、Hicham、Jonathan、および Mat のコメントと一致しない可能性があります。

以下のコードは、この FFTを使用して開始検出を支援します。メソッドが 1 回呼び出されると、すべてが正常に機能し、値の優れたログが得られます。メソッドが2回目に呼び出されると、取得nanまたはジャンクします。何か案は?

{
    NSLog(@"Running onset.");
    NSMutableArray *mutableArrayOfFlags = [[NSMutableArray alloc] init];
    OnsetsDS  *ods = malloc(sizeof *ods); 
    float* odsdata = (float*) malloc(onsetsds_memneeded(ODS_ODF_RCOMPLEX, 512, 11));
    onsetsds_init(ods, odsdata, ODS_FFT_FFTW3_HC, ODS_ODF_RCOMPLEX, 512, 11, 44100);
    int i;
    int x;
    bool onset; 

    for (i = 0; i < vocalBuffer.numFrames; i=i+512){

        // convert vocal int to double 
        double (*vocalData)[2] =  malloc(2 * 512 * sizeof(double));
        for (x = 0; x < 512; x++){
            *vocalData[x] = (double)vocalBuffer.buffer[i+x]; 
        }

        // init malloc output double 
        double (*outPutDoubleFFTData)[2];
        outPutDoubleFFTData =  malloc(2 * 512 * sizeof(double)); 
        fft(512, vocalData, outPutDoubleFFTData);



        int z;
        // init malloc float fft data
        float *floatFFTData; 
        floatFFTData = malloc(512 * sizeof(float));
        for (z = 0; z < 512; z++){
            floatFFTData[z] = (float)*outPutDoubleFFTData[z];
            if (i==512*20) {
                // NSLog(@"PRE POST %f - %f",*vocalData[z], floatFFTData[z]);
                NSLog(@"PRE POST FLOAT %f - %f - %f",*vocalData[z], (*outPutDoubleFFTData)[z], floatFFTData[z]);

            }
        }

        onset = onsetsds_process(ods, floatFFTData);

        free((*outPutDoubleFFTData));
        free(floatFFTData);
        free(vocalData);

        if (onset){
            printf("onset --> %i\n", i);
            NSNumber *integer = [[NSNumber alloc] initWithInt:i];
            [mutableArrayOfFlags addObject:integer];
        }
    }


    free(ods->data); // Or free(odsdata), they point to the same thing in this case
    free(ods);
    return [[NSArray alloc] initWithArray:mutableArrayOfFlags];    
}

初めてメソッドが呼び出されたときのログ:

2012-10-20 11:22:19.625 XX[4125:1903] PRE POST FLOAT 4.000000 - 7979.000000 - 7979.000000
2012-10-20 11:22:19.628 XX[4125:1903] PRE POST FLOAT 25.000000 - 0.000000 - 861.794861
2012-10-20 11:22:19.635 XX[4125:1903] PRE POST FLOAT 32.000000 - 861.794875 - 248.516144
2012-10-20 11:22:19.640 XX[4125:1903] PRE POST FLOAT 22.000000 - 92.284860 - -190.525833
2012-10-20 11:22:19.645 XX[4125:1903] PRE POST FLOAT 23.000000 - 248.516141 - 37.045593
2012-10-20 11:22:19.648 XX[4125:1903] PRE POST FLOAT 30.000000 - -33.565115 - 7.444437

2 回目のメッセージが呼び出されたときのログ。

2012-10-20 11:22:36.353 XX[4125:3e07] PRE POST FLOAT 4.000000 - 7979.000000 - 7979.000000
2012-10-20 11:22:36.358 XX[4125:3e07] PRE POST FLOAT 25.000000 - 53979063281237364484736793729327605401034441222848177467876829146104162439787488863720409331484927794377967278456986000075570355992521879340404128702782598833969629491268820332191001022225312452183861587484411698307560976546539765760.000000 - inf
2012-10-20 11:22:36.364 XX[4125:3e07] PRE POST FLOAT 32.000000 - 
4

7 に答える 7

2
 OnsetsDS  *ods = malloc(sizeof *ods); 

このコードは私には少し奇妙です。これは良いかもしれません。

 OnsetsDS  *ods = malloc(sizeof OnsetsDS); 

これを C または C++ で行った場合、*ods は多くのことのいずれかを行うことができますが、すべてコンパイラによって異なります。まだ初期化されていない可能性があり、NULL を指している、ジャンク データを含むランダムなメモリ アドレスを指している、またはその他の何かを指している可能性があります。

次のようなこともできます

 OnsetsDS ods;

多くの場合、少なくとも C++ では変数に &ods を渡すだけです。私はまだObjective-Cを学んでいる途中です。

于 2012-10-25T20:25:51.267 に答える
1

malloc(size) の代わりに calloc(1, size) を使用してみてください

于 2012-10-24T09:46:06.717 に答える
0

double (*doubleFFTData)[2]doubleFFTData2の配列へのポインタとして定義しますdoubles

*doubleFFTData[b]最初に評価[b]し、次に評価するものとして評価され*ます。

doubleFFTData2の配列へのポインタとして、は2のbdoubles番目配列です。doubleFFTData[b]doubles

そのb番目の2の配列は、2doublesdoubleFFTData[b]配列の0番目の要素へのポインターであるポインターに減衰しますdoubles。このポインタを間接参照すると、2つのうち*最初doubleのポインタが得られます。

したがって、*doubleFFTData[b]と同等でdoubleFFTData[b][0]あり、複素数値のDFTポイントを表すdoubleのペアの最初のdoubleを取得します。

その部分は問題ないようです。

ただし、で割り当てられたメモリを初期化するわけではありませんmalloc()malloc()C言語標準では要求されていないため、割り当てられたメモリを所定の値に設定しません。そのため、そのメモリには、以前に実行されたコードから残っているデータを含めることができます。また、PCの電源を入れた後、メモリがまだ使用されていない場合は、純粋なゴミになる可能性があります。

初期化されていない変数は使用しないでください。ただし、SSLなどの疑似乱数ジェネレーターを実装している場合を除きます。

于 2012-08-12T16:38:13.920 に答える
0
float *floatFFTData; 
 floatFFTData = malloc(512 * sizeof(float));
 for (z = 0; z < 512; z++){
   floatFFTData[z] = (float)*outPutDoubleFFTData[z];
   if (i==512*20) {
     // NSLog(@"PRE POST %f - %f",*vocalData[z], floatFFTData[z]);
     NSLog(@"PRE POST FLOAT %f - %f - %f",*vocalData[z], (*outPutDoubleFFTData)[z], floatFFTData[z]);
   }
 }

512 個のフロートにメモリを割り当てましたが、約 513 個のフロートを反復しようとすると、0 から 512 までが 513 になるため、segfault が発生します。

于 2012-10-24T22:43:41.210 に答える
0
/// my comments are with ///

- (void)objcMallocEx
{
    NSLog(@"Running onset.");
    // an obj-c allocation
    NSMutableArray *mutableArrayOfFlags = [[NSMutableArray alloc] init];

/// i would prefer to see this, followed by &ods in the call below, and get rid of the free at the bottom
/// OnsetsDS  *ods = malloc(sizeof *ods); 
    OnsetsDS    ods = NULL;

/// Q: is onsetsds_init() expecting odsdata as a buffer it can fill?
///   or is it expecting you to be providing it with the address to a pointer that it will fill?
///   if the former, then you've done the right thing below.  if the latter, then
///    what you really need is
///     float* odsdata = NULL;
///   and then pass the &odsdata as the 2nd arg to onsetsds_init() on the next line.
    float* odsdata = (float*) malloc(onsetsds_memneeded(ODS_ODF_RCOMPLEX, 512, 11));

/// onsetsds_init(ods, odsdata, ODS_FFT_FFTW3_HC, ODS_ODF_RCOMPLEX, 512, 11, 44100);
    onsetsds_init(&ods, odsdata, ODS_FFT_FFTW3_HC, ODS_ODF_RCOMPLEX, 512, 11, 44100);

    int i;
    int x;
    bool onset; 

    for (i = 0; i < vocalBuffer.numFrames; i=i+512){

/// in the assignment for the loop, you are declaring that you want an array
/// of 2 double* .  but the malloc assignment is more like a single array
/// of 1024 double items.  it seems like what you really want is 2 arrays of
/// 512 double items.
///     // convert vocal int to double 
///     double (*vocalData)[2] =  malloc(2 * 512 * sizeof(double));
        double vocalData[2][512];

/// if you absolutely insist on using allocation for this, the closest
/// semantically declaration would be
///     double* vocalData[2] = { malloc(512) * sizeof(double)), malloc(512) * sizeof(double) }
/// or
///     double* vocalData[] = (double*)malloc(2 * sizeof(double*));
///     vocalData[0] = malloc(512) * sizeof(double);
///     vocalData[1] = malloc(512) * sizeof(double);

/// THE FOLLOWING IS PART I OF WHAT'S LEADING TO THE DISPLAY OF "RANDOM" DATA
///
/// now, according to your original declaration, you have an array of two pointer-to-double,
/// but in the loop below, c++ operator precedence means it will operate on [x] first, and then on
/// * .  so ... you are getting what's at the xth pointer-to-double, and then getting the value of
/// of that.  if x is 100, and sizeof(double)==8 and sizeof(pointer-to-double)==4, then you the
/// code below is acting as though it wants to get what's at the memory 400 bytes from vocalData,
/// but if you want the 100th double, you should be getting what's at the memory 800 bytes from
/// vocalData.
///     for (x = 0; x < 512; x++){
///         *vocalData[x] = (double)vocalBuffer.buffer[i+x]; 
///     }
        for (x = 0; x < 512; x++)
            vocalData[0][x] = (double)vocalBuffer.buffer[i+x];
/// or      (*vocalData)[x] = (double)vocalBuffer.buffer[i+x];

/// if you absolutely insist on using pointer arithmetic for this, the closest 
/// semantically correct code would be
///     for (x = 0; x < 512; x++)
///         *(vocalData+(sizeof(double)*x)) = (double)vocalBuffer.buffer[i+x];

/// again, with outPutDoubleFFTData, you are declaring that you want an array
/// of 2 double*, but the malloc assignment is more like a single array of
/// 1024 double items.
/// some of what is correct depends upon what the arg signature of fft() is ...

        // init malloc output double 
///     double (*outPutDoubleFFTData)[2];
///     outPutDoubleFFTData =  malloc(2 * 512 * sizeof(double)); 

        double outPutDoubleFFTData[2][512];

/// if you absolutely insist on using allocation for this, the closest
/// semantically equivalent declaration would be
///     double* outPutDoubleFFTData[2] = { malloc(512) * sizeof(double), malloc(512) * sizeof(double) }
/// or
///     double* outPutDoubleFFTData[] = (double*)malloc(2 * sizeof(double*));
///     outPutDoubleFFTData[0] = malloc(512) * sizeof(double);
///     outPutDoubleFFTData[1] = malloc(512) * sizeof(double);

        fft(512, vocalData, outPutDoubleFFTData);

        int z;
        // init malloc float fft data
        float *floatFFTData; 
        floatFFTData = malloc(512 * sizeof(float));
        for (z = 0; z < 512; z++){

/// THE FOLLOWING IS PART II OF WHAT'S LEADING TO THE DISPLAY OF "RANDOM" DATA
/// and, again, according to the original declaration, below, if z == 100 and
/// sizeof(double)==8 and sizeof(double*)==4, then you'll be accessing the memory
/// at the location 400 away from outPutDoubleFFTData when what you really want is
/// the memory that's 800 away from outPutDoubleFFTData.
///
///         floatFFTData[z] = (float)*outPutDoubleFFTData[z];
///
            floatFFTData[z] = (float)((*outPutDoubleFFTData)[z]);

            if (i==512*20) {
                // NSLog(@"PRE POST %f - %f",*vocalData[z], floatFFTData[z]);
/// here, you got the pointer arithmetic into outPutDoubleFFTData correct !!
/// the trouble is, what you stored there is unknown because of the calculations above !!!
                NSLog(@"PRE POST FLOAT %f - %f - %f",*vocalData[z], (*outPutDoubleFFTData)[z], floatFFTData[z]);

            }
        }

        onset = onsetsds_process(ods, floatFFTData);

/// the following isn't going to free what you allocated
///     free((*outPutDoubleFFTData));
/// to do that, you should have
///     free(outPutDoubleFFTData);
/// but best of all is to use the 2-d array in the stack, and then you won't need the heep 

        free(floatFFTData);
/// also don't need the following if using the simple array declaration instead
///     free(vocalData);

        if (onset){
            printf("onset --> %i\n", i);
            NSNumber *integer = [[NSNumber alloc] initWithInt:i];
            [mutableArrayOfFlags addObject:integer];
        }
    }

/// here, since you did a malloc into odsdata, the best thing to do would be to free
/// the same variable as well.
    free(ods->data); // Or free(odsdata), they point to the same thing in this case


/// this isn't necessary if you use the code i've replaced above, rather than what
/// you had that is now commented out.
///  free(ods);

    return [[NSArray alloc] initWithArray:mutableArrayOfFlags];    
}
于 2012-10-22T23:36:41.237 に答える
0

あなたが参照しているfftコードの例で行われているように、明示的な2D配列表記を使用してデータにアクセスして操作する方がはるかに簡単で安全だと思います。を使用して宣言しdouble (*x)[2]、単一のチャンクとして割り当てることx = malloc(2 * N * sizeof(double))は、数値作業のためにデータを最適にローカライズしたままでこれを可能にするように設計されています。

この方法で配列参照をクリアしてみると、発生している初期化されていないメモリの問題を突き止めることができるはずです。

また、この行は、free((*outPutDoubleFFTData))割り当てられたものについて混乱を示しています。

于 2012-10-23T11:05:00.197 に答える
0

あなたはポインタを混合しています:*doubleFFTData[b]そしてdouble (*doubleFFTData)[2]一致しません。

512 double の 2 つの配列が必要な場合:

int b; double (*doubleFFTData)[2]; 
doubleFFTData[0] =  calloc(1 , 2 * 512 * sizeof(double)); // initialize the array to 0       
doubleFFTData[1] = doubleFFTData[0] + 512;  

for (b = 0; b < 512;b++){    
    NSLog(@"results: %f", doubleFFTData[0][b]);
} 
/*and : */

for (b = 0; b < 512;b++){ 
    NSLog(@"results: %f", doubleFFTData[1][b]); 
}
于 2012-08-12T15:54:28.580 に答える