//=========================================================================== 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]; }
//=========================================================================== 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; }