Advertisement
smatskevich

Seminar4

Mar 6th, 2023
802
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.21 KB | None | 0 0
  1. #include <cmath>
  2. #include <cstdio>
  3. #include <iostream>
  4. #include <vector>
  5.  
  6. const double Pi = acos(-1);
  7.  
  8. struct Complex {
  9.   double Re = 0.;
  10.   double Im = 0.;
  11.  
  12.   Complex operator+(const Complex& right) const { return {Re + right.Re, Im + right.Im}; }
  13.   Complex operator*(const Complex& right) const { return {Re * right.Re - Im * right.Im, Re * right.Im + Im * right.Re}; }
  14.   Complex& operator+=(const Complex& right) { Re += right.Re; Im += right.Im; return *this; }
  15. };
  16.  
  17. Complex operator*(double left, const Complex& right) { return {left * right.Re, left * right.Im}; }
  18.  
  19. std::vector<Complex> DFT(short* data, size_t n) {
  20.   std::vector<Complex> wr(n);
  21.   for (size_t i = 0; i < n; ++i) {
  22.     wr[i].Re = cos(-2 * Pi * i / n);
  23.     wr[i].Im = sin(-2 * Pi * i / n);
  24.   }
  25.  
  26.   std::vector<Complex> dft(n);
  27.   for (size_t i = 0; i < n; ++i) {
  28.     for (size_t j = 0; j < n; ++j) {
  29.       dft[j] += data[i] * wr[(i * j) % n];
  30.     }
  31.   }
  32.   return dft;
  33. }
  34.  
  35. std::vector<Complex> Zip(short* data, size_t size) {
  36.   auto result = DFT(data, size);
  37.   size_t cutted = size * 50 / 100;
  38.   for (size_t i = cutted / 2; i < size - cutted / 2; ++i) result[i] = {0., 0.};
  39.   return result;
  40. }
  41.  
  42. std::vector<short> DFTReverse(const std::vector<Complex>& zipped) {
  43.   size_t n = zipped.size();
  44.   std::vector<Complex> w(n);
  45.   for (size_t i = 0; i < n; ++i) {
  46.     w[i].Re = cos(2 * Pi * i / n);
  47.     w[i].Im = sin(2 * Pi * i / n);
  48.   }
  49.  
  50.   std::vector<Complex> dft_rev(n);
  51.   double coef = 1. / n;
  52.   for (size_t i = 0; i < n; ++i) {
  53.     for (size_t j = 0; j < n; ++j) {
  54.       dft_rev[j] += coef * zipped[i] * w[(i * j) % n];
  55.     }
  56.   }
  57.   std::vector<short> restored(n);
  58.   for (size_t i = 0; i < n; ++i) {
  59.     restored[i] = static_cast<short>(dft_rev[i].Re);
  60.   }
  61.   return restored;
  62.  
  63.   return restored;
  64. }
  65.  
  66. // Структура, описывающая заголовок WAV файла.
  67. struct WAVHEADER {
  68.   // WAV-формат начинается с RIFF-заголовка:
  69.  
  70.   // Содержит символы "RIFF" в ASCII кодировке
  71.   // (0x52494646 в big-endian представлении)
  72.   char chunkId[4];
  73.   // 36 + subchunk2Size, или более точно:
  74.   // 4 + (8 + subchunk1Size) + (8 + subchunk2Size)
  75.   // Это оставшийся размер цепочки, начиная с этой позиции.
  76.   // Иначе говоря, это размер файла - 8, то есть,
  77.   // исключены поля chunkId и chunkSize.
  78.   unsigned int chunkSize;
  79.   // Содержит символы "WAVE"
  80.   // (0x57415645 в big-endian представлении)
  81.   char format[4];
  82.  
  83.   // Формат "WAVE" состоит из двух подцепочек: "fmt " и "data":
  84.   // Подцепочка "fmt " описывает формат звуковых данных:
  85.  
  86.   // Содержит символы "fmt "
  87.   // (0x666d7420 в big-endian представлении)
  88.   char subchunk1Id[4];
  89.   // 16 для формата PCM.
  90.   // Это оставшийся размер подцепочки, начиная с этой позиции.
  91.   unsigned int subchunk1Size;
  92.   // Аудио формат, полный список можно получить здесь http://audiocoding.ru/wav_formats.txt
  93.   // Для PCM = 1 (то есть, Линейное квантование).
  94.   // Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
  95.   unsigned short audioFormat;
  96.   // Количество каналов. Моно = 1, Стерео = 2 и т.д.
  97.   unsigned short numChannels;
  98.   // Частота дискретизации. 8000 Гц, 44100 Гц и т.д.
  99.   unsigned int sampleRate;
  100.   // sampleRate * numChannels * bitsPerSample/8
  101.   unsigned int byteRate;
  102.   // numChannels * bitsPerSample/8
  103.   // Количество байт для одного сэмпла, включая все каналы.
  104.   unsigned short blockAlign;
  105.   // Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
  106.   unsigned short bitsPerSample;
  107.   // Подцепочка "data" содержит аудио-данные и их размер.
  108.   // Содержит символы "data"
  109.   // (0x64617461 в big-endian представлении)
  110.   char subchunk2Id[4];
  111.   // numSamples * numChannels * bitsPerSample/8
  112.   // Количество байт в области данных.
  113.   unsigned int subchunk2Size;
  114.  
  115.   // Далее следуют непосредственно Wav данные.
  116. };
  117.  
  118. int main() {
  119.   FILE *file = fopen("/Users/mstepa/tasks/FFT/speech.wav", "r");
  120.   if (!file) {
  121.     std::cout << "Failed open file";
  122.     return 0;
  123.   }
  124.  
  125.   WAVHEADER header;
  126.   fread(&header, sizeof(WAVHEADER), 1, file);
  127.  
  128.   // Выводим полученные данные
  129.   std::cout << header.chunkId[0] << header.chunkId[1] << header.chunkId[2] << header.chunkId[3] << std::endl;
  130.   printf("Chunk size: %d\n", header.chunkSize);
  131.   std::cout << header.format[0] << header.format[1] << header.format[2] << header.format[3] << std::endl;
  132.   std::cout << header.subchunk1Id[0] << header.subchunk1Id[1] << header.subchunk1Id[2] << header.subchunk1Id[3] << std::endl;
  133.   printf("Subchunk1Size: %d\n", header.subchunk1Size);
  134.   printf("Audio format: %d\n", header.audioFormat);
  135.   printf("Channels: %d\n", header.numChannels);
  136.   printf("Sample rate: %d\n", header.sampleRate);
  137.   printf("Bits per sample: %d\n", header.bitsPerSample);
  138.   std::cout << header.subchunk2Id[0] << header.subchunk2Id[1] << header.subchunk2Id[2] << header.subchunk2Id[3] << std::endl;
  139.   printf("Subchunk2Size: %d\n", header.subchunk2Size);
  140.  
  141.   // Посчитаем длительность воспроизведения в секундах
  142.   double fDurationSeconds = 1. * header.subchunk2Size / (header.bitsPerSample / 8) / header.numChannels / header.sampleRate;
  143.   int iDurationMinutes = (int)floor(fDurationSeconds) / 60;
  144.   fDurationSeconds = fDurationSeconds - (iDurationMinutes * 60);
  145.   printf("Duration: %02d:%02.3f\n", iDurationMinutes, fDurationSeconds);
  146.  
  147.   char* data = new char[header.subchunk2Size];
  148.   fread(data, header.subchunk2Size, 1, file);
  149.  
  150.   std::cout << "Data is successfully loaded." << std::endl;
  151.  
  152.   std::cout << "Pi = " << Pi << std::endl;
  153.  
  154.   size_t n = header.subchunk2Size / 2;
  155.   short* source = reinterpret_cast<short*>(data);
  156.   auto zipped = Zip(source, n);
  157.   std::cout << "Zipped first 100:" << std::endl;
  158.   for (int i = 0; i < 100; ++i) std::cout << zipped[i].Re << " ";
  159.   std::cout << "\nOther every 100:" << std::endl;
  160.   for (int i = 100; i < zipped.size(); i += 100) std::cout << zipped[i].Re << " ";
  161.   std::cout << std::endl;
  162.  
  163.   std::vector<short> restored = DFTReverse(zipped);
  164.  
  165.   for (int i = 0; i < 100; ++i) std::cout << source[i] << " ";
  166.   std::cout << std::endl;
  167.   for (int i = 0; i < 100; ++i) std::cout << restored[i] << " ";
  168.  
  169.   for (int i = 0; i < n; ++i) source[i] = restored[i];
  170.   FILE* output_file = fopen("/Users/mstepa/tasks/FFT/speech_out.wav", "w");
  171.   if (!output_file) {
  172.     std::cout << "Failed to open output file" << std::endl;
  173.     return 0;
  174.   }
  175.   fwrite(&header, sizeof(header), 1, output_file);
  176.   fwrite(data, n * 2, 1, output_file);
  177.  
  178.   delete[] data;
  179.   fclose(file);
  180.   return 0;
  181. }
  182.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement