예제 #1
0
//===========================================================================
void Tform_Main::run_FFT ( CCollection<short int> *in, CCollectionStorage<float>  *fft, float *CentralFreq, float minFreq, float maxFreq )
{
    int aPower;
    CCollection<float> re; re.Clear();
    CCollection<float> im; im.Clear();

    int counter = 0;
    int MaximumIndex = -1;
    float temp;
    SoundData.Get_Maximum_ext(&temp, &MaximumIndex);

    for ( unsigned int i = MaximumIndex; i < SoundData.ValuesCount; i++) {
        re.Add(SoundData.Values[i]);
        //re.Add(LoadedData.Items[1]->Values[i]);
        im.Add(0);
        if ( counter++ > 263144 ) break; /// --- Если больше 2 ^18 ----
    }

    // ******************
        FFT(&re, &im, &aPower);
    // ******************

// -----
    fft->SetItemsCount(2);
     int DataCount = exp(aPower * std::log(2.0));
     for ( int i = 0; i < DataCount / 2; i++)
     {
         double xVal = i / (double)DataCount * WorkFreq;
         if ( xVal >= minFreq && xVal < maxFreq )
         {
             double yVal = sqrt(re.Values[i]*re.Values[i] + im.Values[i]*im.Values[i])*2.0 / (double)DataCount;
             fft->Items[0]->Add(xVal);
             fft->Items[1]->Add(yVal);
         }

    }

//    int   array_index = -1;
//      float array_value = -1;
//    fft->Items[1]->Get_Maximum_ext(&array_value, &array_index);
//    *CentralFreq = fft->Items[0]->Values[array_index];
}
예제 #2
0
//===========================================================================
void __fastcall Tform_Main::button_StartDTFCalcClick1(TObject *Sender)
{
    DecimalSeparator = '.';

    if ( listbox_DTFFreqs->Items->Count != 0 )
        if ( listbox_DTFFreqs->ItemIndex != -1 )
            ResonatorFreq = StrToFloat(listbox_DTFFreqs->Items->Strings[listbox_DTFFreqs->ItemIndex]);

    PageControl1->TabIndex = 3;
    PageControl2->TabIndex = 0;
    Application->ProcessMessages();

    ClearSeries(Chart2, true);
    Chart2->AutoSize = true;
    // -----------------------------------------
    AddStringToLog("DFT Calculate");
   // -----------------------------------------

        // -----------
        float Freq1 = 0;
        float Freq2 = 0;
        try {
            Freq1 = StrToFloat( e_Freq1->Text );
            Freq2 = StrToFloat( e_Freq2->Text );
        } catch (...)
        {
            MessageBox(Handle, "Ошибка ввода диапазона частот", "Ошибка", 0);
            return;
        }

        // ----------- Чарт -----------
        ClearSeries(Chart2, true);

        button_StartDTFCalc->Enabled = false;
        button_StopDTFCalc ->Enabled = true;
        isDTFStoped = false;

////////////////////////////////
/*
        SoundData.Clear();
        Freq1 = 5929.56;
        Freq2 = 5932.56;
        WorkFreq = 48000;
        for ( int i = 0; i < 500000; i++)
            SoundData.Add(10000.0 * sin(TWO_PI*5931.06*i / (float)WorkFreq));
*/
////////////////////////////////

        // --------------
///////////////
        int CountData = SoundData.ValuesCount;
        float *x_r  = (float*) malloc (sizeof(float) * CountData);
        float  s_r;
        float  s_i;
        float  t_r;
        float  t_i;

        for ( int i = 0; i < CountData; i++)
            x_r[i] = SoundData.Values[i];

        // -------------
        int    Mode =  0;  // ----- Прямое преобразование фурье ----
        float S    = -1; // ---- Прямое или обратное (-1 / 1) преобразование
        //float R    =  1; // ----

        if ( Mode == 1 )
        {
         S = 1.0;
         //R = 1.0 / (float)CountData;
        }
        CCollection<float> xFreqValues;  xFreqValues.Clear();
        CCollection<float> yFreqValues;  yFreqValues.Clear();

        // ------------- Индексы масивов , для которых будем  считать ДПФ -----
///////////////
        int i1 = (CountData) * Freq1 / WorkFreq;
        int i2 = (CountData) * Freq2 / WorkFreq;

        // -------------
        Chart2->BottomAxis->SetMinMax(i1 / (float) CountData * WorkFreq, i2 / (float)CountData * WorkFreq);
        float CountData_inv = 1.0 / (float)CountData;
        float S_TWO_PI_CountData_inv = S*TWO_PI*CountData_inv;

        float max = -121312;
        int   max_index = -1;

        for (int k = i1; k < i2; k++ )
        {
            if ( isDTFStoped == true ) break;

                s_i = 0;
                s_r = 0;
                for ( int n = 0; n < CountData; n++ )
                {
                    float argument = S_TWO_PI_CountData_inv * k*n;

                    t_r = cos(argument);
                    t_i = sin(argument);
                    s_r = s_r + x_r[n]*t_r;// - a.i*b.i;
                    s_i = s_i + x_r[n]*t_i;// + a.r*b.i;
                }
                float x_val = k * CountData_inv * WorkFreq;
                float y_val = sqrt(s_r*s_r + s_i*s_i);

                y_val = y_val * 2.0 * CountData_inv;

                if ( max < y_val ){
                    max = y_val;
                    max_index = k;
                }

                xFreqValues.Add(x_val);
                yFreqValues.Add(y_val);

                Chart2->Series[0]->AddXY(x_val, y_val);
                Application->ProcessMessages();
        }

        float index1 = (max_index - 2 < 0 ) ? 0 : max_index - 2;
        float index2 = (max_index + 2 > CountData - 1 ) ? CountData - 1 : max_index + 2;
        float indexator_incroment = 1.0 / (float)DTF_InterpolationPointsCount;
        for (float k = index1; k < index2; k = k + indexator_incroment )
        {
            if ( isDTFStoped == true ) break;

            s_i = s_r = 0;
            for ( int n = 0; n < CountData; n++ )
            {
                //float argument = k*n * S_TWO_PI_CountData_inv;
                float argument = S_TWO_PI_CountData_inv * k*n;
                t_r = cos(argument);
                t_i = sin(argument);

                s_r = s_r + x_r[n]*t_r;
                s_i = s_i + x_r[n]*t_i;
            }
            float x_val = k * CountData_inv * WorkFreq;
            float y_val = sqrt(s_r*s_r + s_i*s_i);

            y_val = y_val * 2.0 * CountData_inv;

            xFreqValues.Add(x_val);
            yFreqValues.Add(y_val);

            Chart2->Series[0]->AddXY(x_val, y_val);
            Application->ProcessMessages();
        }

        free(x_r);


   // -----------------------------------------
   // -----------------------------------------
   // ----- Расчет добротности ----------------
   // -----------------------------------------
        if ( isDTFStoped == true ){
            AddStringToLog("DFT stoped");
        } else {
            TFastLineSeries *ls = (TFastLineSeries *)Chart2->Series[0];
            float max = -1000;
            float CenterFreq = 0;
            int   Index_of_MaxFreq = -1;

            for ( int i = 0; i < ls->YValues->Count; i++)
                if ( max < ls->YValues->Value[i] ) {
                    max              = ls->YValues->Value[i];
                    CenterFreq       = ls->XValues->Value[i];
                    Index_of_MaxFreq = i;
                }

            float freq1 = 0, freq2 = 0;
            float val1, val2;

            float px_1[2], py_1[2];
            float px_2[2], py_2[2];

            // ---- Поиск Левого бока ----
            for ( int i = Index_of_MaxFreq; i > 1; i-- ) {
                if ( ls->YValues->Value[i] <= 0.707*max)
                {
                    float df = ls->XValues->Value[i+1] - ls->XValues->Value[i];
                    float ya = ls->YValues->Value[i  ];
                    float yb = ls->YValues->Value[i+1];

                    val1  = 0.707*max;
                    freq1 = ls->XValues->Value[i] + df * (0.707*max - ya) / (yb - ya);

                    break;
                }
            }

            // ---- Поиск Правой бока ----
            for ( int i = Index_of_MaxFreq; i < ls->YValues->Count; i++ ) {
                if ( ls->YValues->Value[i] <= 0.707*max)
                {
                    float df = ls->XValues->Value[i  ] - ls->XValues->Value[i-1];
                    float ya = ls->YValues->Value[i-1];
                    float yb = ls->YValues->Value[i  ];

                    val2  = 0.707*max;
                    freq2 = ls->XValues->Value[i-1] + df * (0.707*max - ya) / (yb - ya);

                    break;
                }
            }

/*
Index_of_MaxFreq
*/
/*
            for ( int i = 1; i < ls->YValues->Count; i++)
            {
                if ( ls->YValues->Value[i] >= 0.707*max && freq1 < 100)
                {
                    float df = ls->XValues->Value[i] - ls->XValues->Value[i-1];
                    float ya = ls->YValues->Value[i-1];
                    float yb = ls->YValues->Value[i  ];

                    val1  = 0.707*max;
                    freq1 = ls->XValues->Value[i-1] + df * (0.707*max - ya) / (yb - ya);
                }
                if ( ls->YValues->Value[i] <= 0.707*max && freq1 > 100 && freq2 < 100)
                {
                    float df = ls->XValues->Value[i] - ls->XValues->Value[i-1];
                    float ya = ls->YValues->Value[i-1];
                    float yb = ls->YValues->Value[i  ];

                    val2  = 0.707*max;
                    freq2 = ls->XValues->Value[i-1] + df * (0.707*max - ya) / (yb - ya);
                }
            }
*/
            float q = CenterFreq / (freq2 - freq1);
            AddStringToLog("F/dF = " + FloatToStrF(q, ffFixed, 20, 2));
            e_Dobrotnost2->Text = FloatToStrF(q, ffFixed, 20, 2);
            Chart2->Series[1]->AddXY(CenterFreq, max);
            Chart2->Series[1]->AddXY(freq1, val1);
            Chart2->Series[1]->AddXY(freq2, val2);

            Chart2->Series[2]->AddXY(freq1 - 0.5*(freq2 - freq1), 0.707 * max);
            Chart2->Series[2]->AddXY(freq2 + 0.5*(freq2 - freq1), 0.707 * max);

            Chart2->LeftAxis->SetMinMax(0, max*1.12);
            Chart2->BottomAxis->SetMinMax(freq1 - 2.0*(freq2 - freq1), freq2 + 2.0*(freq2 - freq1));
        }
    // -----------
    button_StartDTFCalc->Enabled = true;
    button_StopDTFCalc ->Enabled = false;
    isDTFStoped = false;
}