Guest User

Untitled

a guest
Jan 23rd, 2024
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.35 KB | None | 0 0
  1. //-----Начало .h файла-----//
  2. #pragma once
  3.  
  4. #include <QObject>
  5. #include <mutex>
  6. #include<complex>
  7. #include "include/fftw3.h"
  8.  
  9. #define FFT_PI 3.1415926535897932384626433832795
  10.  
  11. class MyFFT : public QObject
  12. {
  13.     Q_OBJECT
  14.  
  15.  
  16. public:
  17.     MyFFT(int sizeFFT, QObject *parent = nullptr);
  18.  
  19.  
  20.     int sizeFFT;    //Размер FFT
  21.  
  22.     void setSizeFFT(int inputSizeFFT);
  23.     void createWindowBlackmanHarris();
  24.     void makeFFT();
  25.  
  26.  
  27.     int currentBufferSizeFFT = 0;           //Размер накопившихся отчётов
  28.  
  29.     fftw_plan planFFT = nullptr;            //План для БПФ
  30.     fftw_plan planReverseFFT = nullptr;     //План для ОБПФ
  31.  
  32.  
  33.     //Буферы для FFT
  34.     std::vector<std::complex<double>>   inputBuffer;                        //Входной буфер
  35.     std::vector<std::complex<double>>   outputBuffer;                       //Выходной буфер
  36.     std::vector<double>                 moduleBuffer;                       //Буфер модуля
  37.     std::vector<double>                 dB_buffer;                          //Буфер децибелл
  38.  
  39.     std::vector<double>                 vectorWindowBlackmanHarris;         //Окно Блэкмана Харриса
  40.    
  41.     double maxValueADC = 1000000000.0;                                      //Максимальное значение с АЦП
  42.    
  43.    
  44. public slots:
  45.     void addIQ(const uint8_t* inputVectorIQ, const int len);
  46.  
  47. };
  48.  
  49.  
  50.  
  51. //-----Начало .cpp файла-----//
  52. #include "receiverfft.h"
  53. #include "qmath.h"
  54. #include <QCoreApplication>
  55.  
  56. MyFFT::MyFFT(int sizeFFT, QObject *parent) : QObject{parent}
  57. {
  58.     setSizeFFT(sizeFFT);
  59. }
  60.  
  61. void MyFFT::setSizeFFT(int inputSizeFFT)
  62. {
  63.     if(sizeFFT != inputSizeFFT)
  64.     {
  65.         sizeFFT = inputSizeFFT;
  66.  
  67.         inputBuffer.resize(sizeFFT, 0);
  68.         outputBuffer.resize(sizeFFT, 0);
  69.         moduleBuffer.resize(sizeFFT, 0);
  70.         dB_buffer.resize(sizeFFT, 0);
  71.         vectorWindowBlackmanHarris.resize(sizeFFT, 0);
  72.  
  73.         currentBufferSizeFFT = 0;
  74.  
  75.         createWindowBlackmanHarris();
  76.  
  77.         if(planFFT != nullptr)
  78.         {
  79.             fftw_destroy_plan(planFFT);
  80.             planFFT = nullptr;
  81.         }
  82.  
  83.         planFFT = fftw_plan_dft_1d(sizeFFT, (fftw_complex*)inputBuffer.data(), (fftw_complex*)outputBuffer.data(), FFTW_FORWARD, FFTW_ESTIMATE);
  84.     }
  85. }
  86.  
  87. void MyFFT::createWindowBlackmanHarris()
  88. {
  89.     double windowEnergyMux = 0.;
  90.  
  91.     for(int i = 0; i < sizeFFT; i++)
  92.     {
  93.        vectorWindowBlackmanHarris[i] = 0.35875f - 0.48829 * qCos(2.*FFT_PI * i / (sizeFFT - 1))
  94.                                                 + 0.14128 * qCos(4.*FFT_PI * i / (sizeFFT - 1))
  95.                                                 - 0.01168 * qCos(6.*FFT_PI * i / (sizeFFT - 1));
  96.  
  97.        windowEnergyMux += vectorWindowBlackmanHarris[i] * vectorWindowBlackmanHarris[i];
  98.     }
  99.  
  100.     windowEnergyMux /= sizeFFT;
  101.     windowEnergyMux = qSqrt(1/windowEnergyMux);
  102.  
  103.     for(int i = 0; i < sizeFFT; i++)
  104.     {
  105.         vectorWindowBlackmanHarris[i] *= windowEnergyMux;
  106.     }
  107. }
  108.  
  109. void MyFFT::makeFFT()
  110. {
  111.     //Делаем FFT
  112.     fftw_execute(planFFT);
  113.  
  114.  
  115.     //Меняем местами первую и вторую половину и при этом переводим в комплексный модуль
  116.     int offset = outputBuffer.size()/2;
  117.  
  118.     float module = 0;
  119.  
  120.     for(int i = 0; i < offset; i++)
  121.     {
  122.         module = outputBuffer[i + offset].real()*outputBuffer[i + offset].real() + outputBuffer[i + offset].imag()*outputBuffer[i + offset].imag();
  123.  
  124.         moduleBuffer[i] = module;
  125.     }
  126.  
  127.     for(int i = offset; i < outputBuffer.size(); i++)
  128.     {
  129.         module = outputBuffer[i - offset].real()*outputBuffer[i - offset].real() + outputBuffer[i - offset].imag()*outputBuffer[i - offset].imag();
  130.  
  131.         moduleBuffer[i] = module;
  132.     }
  133.  
  134.  
  135.     //Переводим в децибелы
  136.     for(int i = 0; i < dB_buffer.size(); i++)
  137.     {
  138.         dB_buffer[i] = 10.0 * std::log10(moduleBuffer[i] + 1e-300);
  139.     }
  140. }
  141.  
  142. void MyFFT::addIQ(const uint8_t* inputVectorIQ, const int len)
  143. {
  144.     //Вычисляем количество IQ содержащихся в размере байтового вектора
  145.     int countIQ = len/(sizeof(int)*2);
  146.  
  147.     //Получаем указатель на вектор интовых комплексных чисел
  148.     auto complexVector = (const std::complex<int>*)inputVectorIQ;
  149.  
  150.  
  151.     //Если текущий размер буфера FFT + размер пришедших данных IQ больше чем размер FFT
  152.     if((currentBufferSizeFFT + countIQ) > sizeFFT)
  153.     {
  154.         int offset = 0;
  155.  
  156.         //Будем вычитывать пока из пришедших данных, до тех пор пока не вычитаем всё или размер currentBufferSizeFFT + countIQ станет меньше или равен sizeFFT
  157.         while((currentBufferSizeFFT + countIQ) > sizeFFT)
  158.         {
  159.             //Узнаём сколько не хватает до полноценного FFT
  160.             const int delta = sizeFFT - currentBufferSizeFFT;
  161.  
  162.             //Вычисляем индекс последнего считанного элемента
  163.             const int size = offset + delta;
  164.  
  165.             //Считываем с offset по size
  166.             for(int i = offset; i < size; i++)
  167.             {
  168.                 inputBuffer[currentBufferSizeFFT].real(complexVector[i].real() * vectorWindowBlackmanHarris[currentBufferSizeFFT] / maxValueADC / sizeFFT);
  169.                 inputBuffer[currentBufferSizeFFT].imag(complexVector[i].imag() * vectorWindowBlackmanHarris[currentBufferSizeFFT] / maxValueADC / sizeFFT);
  170.  
  171.                 currentBufferSizeFFT++;
  172.             }
  173.  
  174.             //Увеличиваем отступ от начала буфера данных
  175.             offset += delta;
  176.  
  177.             //Уменьшаем количество оставшихся IQ отчётов
  178.             countIQ -= delta;
  179.  
  180.  
  181.             //Проверяем не накопилось ли FFT
  182.             if(currentBufferSizeFFT >= sizeFFT)
  183.             {
  184.                 //Делаем новое FFT
  185.                 makeFFT();
  186.  
  187.                 //Вычитаем из текущего размера FFT размер FFT
  188.                 currentBufferSizeFFT -= sizeFFT;
  189.             }
  190.         }
  191.  
  192.         //Если что то осталось
  193.         if(countIQ > 0)
  194.         {
  195.             //Вычисляем индекс последнего считанного элемента
  196.             const int size = offset + countIQ;
  197.  
  198.             //Считываем с offset по size
  199.             for(int i = offset; i < size; i++)
  200.             {
  201.                 inputBuffer[currentBufferSizeFFT].real(complexVector[i].real() * vectorWindowBlackmanHarris[currentBufferSizeFFT] / maxValueADC / sizeFFT);
  202.                 inputBuffer[currentBufferSizeFFT].imag(complexVector[i].imag() * vectorWindowBlackmanHarris[currentBufferSizeFFT] / maxValueADC / sizeFFT);
  203.  
  204.                 currentBufferSizeFFT++;
  205.             }
  206.  
  207.  
  208.             //Проверяем не накопилось ли FFT
  209.             if(currentBufferSizeFFT >= sizeFFT)
  210.             {
  211.                 //Делаем новое FFT
  212.                 makeFFT();
  213.  
  214.                 //Вычитаем из текущего размера FFT размер FFT
  215.                 currentBufferSizeFFT -= sizeFFT;
  216.             }
  217.         }
  218.     }
  219.     else
  220.     {
  221.         //Добавляем новые отчёты
  222.         for(int i = 0; i < countIQ; i++)
  223.         {
  224.             inputBuffer[currentBufferSizeFFT].real(complexVector[i].real() * vectorWindowBlackmanHarris[currentBufferSizeFFT] / maxValueADC / sizeFFT);
  225.             inputBuffer[currentBufferSizeFFT].imag(complexVector[i].imag() * vectorWindowBlackmanHarris[currentBufferSizeFFT] / maxValueADC / sizeFFT);
  226.  
  227.             currentBufferSizeFFT++;
  228.         }
  229.  
  230.  
  231.         //Проверяем не накопилось ли FFT
  232.         if(currentBufferSizeFFT >= sizeFFT)
  233.         {
  234.             //Делаем новое FFT
  235.             makeFFT();
  236.  
  237.             //Вычитаем из текущего размера FFT размер FFT
  238.             currentBufferSizeFFT -= sizeFFT;
  239.         }
  240.     }
  241. }
  242.  
Add Comment
Please, Sign In to add comment