B. Sinyal Suara
Audio diartikan sebagai suara atau reproduksi suara. Gelombang suara adalah
gelombang yang dihasilkan dari sebuah benda yang bergetar. Gambarannya adalah
senar gitar yang dipetik, gitar akan bergetar dan getaran ini merambat di udara, atau
air, atau material lainnya. Satu-satunya tempat dimana suara tak dapat merambat
adalah ruangan hampa udara. Gelombang suara ini memiliki lembah dan bukit, satu
buah lembah dan bukit akan menghasilkan satu siklus atau periode. Siklus ini
berlangsung berulang-ulang, yang membawa pada konsep frekuensi. Jelasnya,
frekuensi adalah jumlah dari siklus yang terjadi dalam satu detik. Satuan dari
frekuensi adalah Hertz atau disingkat Hz.
Telinga manusia dapat mendengar bunyi antara 20 Hz hingga 20 KHz (20.000
Hz) sesuai dengan batasan sinyal suara. Karena pada dasarnya sinyal suara adalah
sinyal yang dapat diterima oleh telinga manusia. Angka 20 Hz sebagai frekuensi
suara terendah yang dapat didengar, sedangkan 20 KHz merupakan frekuensi
tertinggi yang dapat didengar.
Dimana s(f) adalah sinyal dalam domain frekuensi (frequency domain), s(t)
adalah sinyal dalam domain waktu (time domain), dan adalah konstanta dari
nilai sebuah sinyal, f adalah frekuensi dan t adalah waktu. FFT (Fast Fourier
Transform) merupakan salah satu metode untuk transformasi sinyal suara dalam
domain waktu menjadi sinyal dalam domain frekuensi, artinya proses perekaman
suara disimpan dalam bentuk digital berupa gelombang spectrum suara yang
berbasis frekuensi sehingga lebih mudah dalam menganalisa spectrum frekuensi
suara yang telah direkam.
E. File Wav
File audio ini diciptakan oleh Microsoft. File ini menjadi standar file audio dalam
Personal Computer(PC) baik untuk sistem operasi, game, maupun file suara lain
yang kualitas suaranya setara dengan CD. File ini memiliki ukuran yang cukup
besar, karena suara yang disimpan dalam format ini tidak mengalami proses
kompresi (raw data). Meski buatan Microsoft, bukan berarti file ini tidak dapat
dijalankan oleh sistem operasi selain Windows. Setidaknya, Linux dan Macintosh
juga dapat menjalankan file ini. Beikut ini diagram canonical file wav.
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <random>
#include <vector>
#include <fstream>
#include <sstream>
#include <string>
#include "FftComplex.h"
using std::complex;
using std::cout;
using std::endl;
using std::vector;
using namespace std;
//Wav Header
struct wav_header_t
{
char chunkID[4]; //"RIFF" = 0x46464952
unsigned long chunkSize; //28 [+ sizeof(wExtraFormatBytes) +
wExtraFormatBytes] + sum(sizeof(chunk.id) + sizeof(chunk.size) + chunk.size)
char format[4]; //"WAVE" = 0x45564157
char subchunk1ID[4]; //"fmt " = 0x20746D66
unsigned long subchunk1Size; //16 [+ sizeof(wExtraFormatBytes) +
wExtraFormatBytes]
unsigned short audioFormat;
unsigned short numChannels;
unsigned long sampleRate;
unsigned long byteRate;
unsigned short blockAlign;
unsigned short bitsPerSample;
//[WORD wExtraFormatBytes;]
//[Extra format bytes]
};
//Chunks
struct chunk_t
{
char ID[4]; //"data" = 0x61746164
unsigned long size; //Chunk data bytes
};
vector<double> data_20ms;
string initFile;
int main() {
/*
//// Test power-of-2 size FFTs
//for (int i = 0; i <= 12; i++)
// testFft(1 << i);
vector<complex<double>> dataInFFT;
//dataInFFT = read1DDouble("dataSampling.csv", false);
for (auto& row : data_20ms) {
complex<double> y= (complex<double>)row;
dataInFFT.push_back(y);
}
//proses FFT
cout << "\n\nproses FFT...\n";
Fft::transform(dataInFFT);
//smoothing
cout << "Smoothing...\n";
fout.open("outputFFTSmoothing_" + initFile + ".csv", ios::out);
vector<double> dtSmooth;
//smoothing
cout << "Smoothing...\n";
fout.open("outputFFTSmoothing_" + initFile + ".csv", ios::out);
vector<double> dtSmooth;
dtSmooth.clear();
for (int i = 0; i < dtReal.size(); i++) {
double jPrev, jNow, jNext;
if (i == 0) {
jPrev = 0; jNow = dtReal[i]; jNext = dtReal[i + 1];
}
else if (i == (dtReal.size() - 1)) {
jPrev = dtReal[i - 1]; jNow = dtReal[i]; jNext = 0;
}
else {
jPrev = dtReal[i - 1]; jNow = dtReal[i]; jNext =
dtReal[i + 1];
}
//Reading file
chunk_t chunk;
printf("id\t" "size\n");
//go to data chunk
while (true)
{
fread(&chunk, sizeof(chunk), 1, fin);
printf("%c%c%c%c\t" "%li\n", chunk.ID[0], chunk.ID[1], chunk.ID[2],
chunk.ID[3], chunk.size);
if (*(unsigned int*)&chunk.ID == 0x61746164)
break;
//skip chunk data bytes
fseek(fin, chunk.size, SEEK_CUR);
cout << "ok \n";
}
//Number of samples
int sample_size = header.bitsPerSample / 8;
int samples_count = chunk.size * 8 / header.bitsPerSample;
printf("Samples count = %i\n", samples_count);
//Reading data
for (int i = 0; i < samples_count; i++)
{
fread(&value[i], sample_size, 1, fin);
}
if (showLoadedData) {
cout << "complete loaded data" << endl << endl;
for (auto& val : vec)
cout << val << " ";
cout << endl;
}
return vec;
}
B. FftComplex.cpp
/* C. FftComplex.h
* Free FFT and convolution (C++)
*
* Copyright (c) 2019 Project Nayuki. (MIT License)
* https://www.nayuki.io/page/free-small-fft-in-multiple-languages
*
#define _USE_MATH_DEFINES
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include "FftComplex.h"
using std::complex;
using std::size_t;
using std::vector;
// Private function prototypes
static size_t reverseBits(size_t x, int n);
// Trignometric table
vector<complex<double> > expTable(n / 2);
for (size_t i = 0; i < n / 2; i++)
expTable[i] = std::polar(1.0, -2 * M_PI * i / n);
// Trignometric table
vector<complex<double> > expTable(n);
for (size_t i = 0; i < n; i++) {
unsigned long long temp = static_cast<unsigned long long>(i)* i;
temp %= static_cast<unsigned long long>(n) * 2;
double angle = M_PI * temp / n;
expTable[i] = std::polar(1.0, -angle);
}
// Postprocessing
for (size_t i = 0; i < n; i++)
vec[i] = cv[i] * expTable[i];
}
void Fft::convolve(
const vector<complex<double> >& xvec,
const vector<complex<double> >& yvec,
vector<complex<double> >& outvec) {
size_t n = xvec.size();
if (n != yvec.size() || n != outvec.size())
throw std::domain_error("Mismatched lengths");
vector<complex<double> > xv = xvec;
vector<complex<double> > yv = yvec;
transform(xv);
transform(yv);
for (size_t i = 0; i < n; i++)
xv[i] *= yv[i];
inverseTransform(xv);
for (size_t i = 0; i < n; i++) // Scaling (because this FFT implementation omits
it)
outvec[i] = xv[i] / static_cast<double>(n);
}
#pragma once
#include <complex>
#include <vector>
namespace Fft {
/*
* Computes the discrete Fourier transform (DFT) of the given complex
vector, storing the result back into the vector.
* The vector can have any length. This is a wrapper function.
*/
void transform(std::vector<std::complex<double> >& vec);
/*
* Computes the inverse discrete Fourier transform (IDFT) of the given
complex vector, storing the result back into the vector.
* The vector can have any length. This is a wrapper function. This transform
does not perform scaling, so the inverse is not a true inverse.
*/
void inverseTransform(std::vector<std::complex<double> >& vec);
/*
* Computes the discrete Fourier transform (DFT) of the given complex
vector, storing the result back into the vector.
* The vector's length must be a power of 2. Uses the Cooley-Tukey
decimation-in-time radix-2 algorithm.
*/
void transformRadix2(std::vector<std::complex<double> >& vec);
/*
* Computes the discrete Fourier transform (DFT) of the given complex
vector, storing the result back into the vector.
* The vector can have any length. This requires the convolution function,
which in turn requires the radix-2 FFT function.
* Uses Bluestein's chirp z-transform algorithm.
*/
void transformBluestein(std::vector<std::complex<double> >& vec);
/*
* Computes the circular convolution of the given complex vectors. Each
vector's length must be the same.
*/
void convolve(
const std::vector<std::complex<double> >& vecx,
const std::vector<std::complex<double> >& vecy,
std::vector<std::complex<double> >& vecout);
6000
4000
2000
0
12 324 636 948 126015721884219625082820313234443756406843804692500453165628
-2000
-4000
-6000
500
0
2 24 46 68 90 112134156178200222244266288310332354376398420442464486508
-500
-1000
-1500
Gambar 10. Sinyal hasil FFT dan hasil cuplik 20ms dari tengah
20000
15000
10000
5000
0
2 26 50 74 98 122 146 170 194 218 242 266 290 314 338 362 386 410 434 458 482 506
-5000
-10000
-15000
Gambar diatas adalah gambar sinyal suara raw dari huruf I. kemudian jika dilakukan
FFT dan diambil 20ms dari tengah maka hasilnya adalah sbb:
500
0
2 24 46 68 90 112134156178200222244266288310332354376398420442464486508
-500
-1000
-1500
Gambar 12. Sinyal hasil FFT dan hasil cuplik 20ms dari tengah
Kemudian jika dilakukan smoothing maka akan sbb:
10000
5000
0
2 26 50 74 98 122 146 170 194 218 242 266 290 314 338 362 386 410 434 458 482 506
-5000
-10000
-15000
6000
4000
2000
0
10 280 550 820 10901360163019002170244027102980325035203790406043304600
-2000
-4000
-6000
Gambar diatas adalah gambar sinyal suara raw dari huruf U. kemudian jika
dilakukan FFT dan diambil 20ms dari tengah maka hasilnya adalah sbb:
6000
4000
2000
0
2 24 46 68 90 112134156178200222244266288310332354376398420442464486508
-2000
-4000
-6000
Gambar 13. Sinyal hasil FFT dan hasil cuplik 20ms dari tengah
Jika dilakukann smoothing maka akan sbb:
150000
100000
50000
0
2 26 50 74 98 122 146 170 194 218 242 266 290 314 338 362 386 410 434 458 482 506
-50000
-100000
-150000
-200000
Gambar diatas adalah gambar sinyal suara raw dari huruf E. kemudian jika
dilakukan FFT dan diambil 20ms dari tengah maka hasilnya adalah sbb:
1500
1000
500
0
2 24 46 68 90 112134156178200222244266288310332354376398420442464486508
-500
-1000
-1500
Gambar 16. Sinyal hasil FFT dan hasil cuplik 20ms dari tengah
Jika dilakukann smoothing maka akan sbb:
60000
40000
20000
0
2 26 50 74 98 122 146 170 194 218 242 266 290 314 338 362 386 410 434 458 482 506
-20000
-40000
5000
0
54 1998 3942 5886 7830 9774 1171813662156061755019494214382338225326
-5000
-10000
-15000
Gambar diatas adalah gambar sinyal suara raw dari huruf O. kemudian jika
dilakukan FFT dan diambil 20ms dari tengah maka hasilnya adalah sbb:
1000
500
0
2 24 46 68 90 112134156178200222244266288310332354376398420442464486508
-500
-1000
-1500
-2000
Gambar 19. Sinyal hasil FFT dan hasil cuplik 20ms dari tengah
Jika dilakukann smoothing maka akan sbb:
40000
20000
0
2 26 50 74 98 122 146 170 194 218 242 266 290 314 338 362 386 410 434 458 482 506
-20000
-40000
-60000
-80000