Low-Pass High-Pass Bandpass Bandstop: Laborator 4

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

Nume: Axinte Vlad-Andrei

Master: GMRV

Laborator 4

Exercitiu 1:

Low-pass
High-pass
Bandpass
Bandstop
Exercitiu 2:

Ordinul 3
Ordinul 9
Ordinul 11
Ordinul 31
Exercitiu 3:

Violin

Ideal
band
pass

Ideal
band
stop
Ideal
high
pass

Low
pass
COD:
struct WAV_HEADER {
// Header RIFF
char chunkID[4];
unsigned long chunkSize;
char format[4];

// Subchunk fmt
char subChunk1ID[4];
unsigned long subChunk1Size;
unsigned short audioFormat;
unsigned short numChannels;
unsigned long sampleRate;
unsigned long byteRate;
unsigned short blockAlign;
unsigned short bitsPerSample;

// Subchunk data
char subChunk2ID[4];
unsigned long subChunk2Size;
};

WAV_HEADER readBasicHeader(const char* path)


{
WAV_HEADER header{};

// Open .wav
fopen_s(&file_ptr, path, "rb");

// Read header
if (file_ptr != 0)
fread(&header, sizeof(header), 1, file_ptr);

fclose(file_ptr);

return header;
}

std::vector<short> getWavSamples(WAV_HEADER header, const char* filePath)


{
// Open .wav
fopen_s(&file_ptr, filePath, "rb");

// Number o samples
int sampleCount = (header.subChunk2Size * 8) / (header.numChannels *
header.bitsPerSample);
int bytesPerSample = header.bitsPerSample / 8;

// Store sample values


std::vector<short> samples(sampleCount);

// Fill vector data


size_t elemsRead = fread(samples.data(), sizeof(short), sampleCount, file_ptr);

// Close file
if (file_ptr != 0)
fclose(file_ptr);

return samples;
}

void writeWavFile(const char* path,


WAV_HEADER header,
std::vector<short> samples,
float samplingRate)
{
// Create file
fopen_s(&file_ptr, path, "wb");

// Create header
WAV_HEADER wav_header = header;

// Recalculate header values


wav_header.subChunk2Size = samples.size() * channelCount * bitsPerSample / 8;
wav_header.chunkSize = 36 + wav_header.subChunk2Size;
wav_header.subChunk1Size = 16; // PCM
wav_header.audioFormat = 1; // PCM
wav_header.numChannels = channelCount;
wav_header.sampleRate = samplingRate;
wav_header.byteRate = samplingRate * channelCount * bitsPerSample / 8;
wav_header.blockAlign = channelCount * bitsPerSample / 8;
wav_header.bitsPerSample = bitsPerSample;

// Write header to .wav file


fwrite(&wav_header, sizeof(wav_header), 1, file_ptr);
fwrite(samples.data(), sizeof(short), samples.size(), file_ptr);

fclose(file_ptr);
}

std::vector<std::complex<float>> DFT(std::vector<short> samples)


{
std::vector<std::complex<float>> dftTransform;
std::vector<float> magnitudeVector(samples.size());
std::vector<float> phaseVector(samples.size());

// Number of samples
float N = samples.size();

for (int k = 0; k < N; ++k)


{
float re{}, im{};

// Calculate DFT
for (int n = 0; n < N; ++n)
{
float angle = 2 * M_PI * k * n / N;

re += samples[n] * cos(angle);
im -= samples[n] * sin(angle);
}

// Calculate magnitude
magnitudeVector[k] = sqrt(re * re + im * im);

if (re == 0)
phaseVector[k] = atan(0);
else
phaseVector[k] = atan(im / re);

dftTransform.push_back(std::complex<float>(re, im));
}

return dftTransform;
}

std::vector<short> IDFT(std::vector<std::complex<float>> dftTransform)


{
std::vector<short> samplesIDFT;

// Get sample count


float N = dftTransform.size();

float divN = 1 / N;

for (int n = 0; n < N; ++n)


{
float re{};
float im{};

// Calcualte IDFT
for (int k = 0; k < N; ++k)
{
float angle = 2 * M_PI * k * n / N;

re += divN * dftTransform[k].real() * cos(angle);


im += divN * dftTransform[k].imag() * sin(angle);
}

// Fill vector
samplesIDFT.push_back(re + im);
}

// Reverse IDFT
std::reverse(samplesIDFT.begin(), samplesIDFT.end());

return samplesIDFT;
}

int CalculateAdjustedCutoffFreq(float cutoffFreq, int sampleCount, int samplingRate)


{
return cutoffFreq * sampleCount / samplingRate;
}

std::vector<short> HI_LO_PassIdealFilter(std::vector<std::complex<float>> dft, float


cutoffFreq, float samplingRate, FilterType fType)
{
// Adjust cutoff frequency
int adjustedCutoffFreq = CalculateAdjustedCutoffFreq(cutoffFreq, dft.size(),
samplingRate);
std::vector<int> freqResponse(dft.size());
std::vector<std::complex<float>> filtered_dft;

for (int i = 0; i < dft.size(); i++)


{
// Generate low or high-pass frequency
if (i < adjustedCutoffFreq || i >(dft.size() - adjustedCutoffFreq))
{
if (fType == LowPass)
freqResponse[i] = 1;
else
freqResponse[i] = 0;
}
else
{
if (fType == LowPass)
freqResponse[i] = 0;
else
freqResponse[i] = 1;
}

// Apply filter to dft vector


filtered_dft.push_back(std::complex<float>(dft[i].real() * freqResponse[i],
dft[i].imag() * freqResponse[i]));
}

return IDFT(filtered_dft);
}

std::vector<short> Band_PASS_STOP_IdealFilter(std::vector<std::complex<float>> dft, float


freq1, float freq2, float samplingRate, FilterType fType)
{
// Adjust cutoff frequency
int adjustedCutoffFreq_1 = CalculateAdjustedCutoffFreq(freq1, dft.size(),
samplingRate);
int adjustedCutoffFreq_2 = CalculateAdjustedCutoffFreq(freq2, dft.size(),
samplingRate);

std::vector<int> freqResponse(dft.size());
std::vector<std::complex<float>> filtered_dft;

for (int i = 0; i < dft.size(); i++)


{
// Generate band-pass or band-stop frequency response function
if ((i > adjustedCutoffFreq_1&& i < adjustedCutoffFreq_2) || (i > dft.size()
- adjustedCutoffFreq_2 && i < dft.size() - adjustedCutoffFreq_1))
{
if (fType == BandPass)
freqResponse[i] = 1;
else
freqResponse[i] = 0;
}
else
{
if (fType == BandPass)
freqResponse[i] = 0;
else
freqResponse[i] = 1;
}

// Apply filter to dft vector


filtered_dft.push_back(std::complex<float>(dft[i].real() * freqResponse[i],
dft[i].imag() * freqResponse[i]));
}

return IDFT(filtered_dft);
}

std::vector<float> GenerateLowPassFIR(
// fc = cutoff frequency
// N = order of filter
int N,
float fc,
float samplingRate)
{
std::vector<float> lp_filter(N, 0);

// Normalize fc and omega_c


fc = fc / samplingRate;
float omega_c = 2 * M_PI * fc;
int middle = N / 2;

// Create low-pass filter


for (int i = -N / 2; i <= N / 2; i++)
{
if (i == 0)
lp_filter[middle] = 2 * fc;
else
lp_filter[i + middle] = sin(omega_c * i) / (M_PI * i);
}

// Hanning
for (int i = 0; i < N; i++)
lp_filter[i] *= 0.5 * (1 - cos((2 * M_PI * i) / N));

// Write in file
std::ofstream out_file(window_path);
std::ostream_iterator<float> output_iterator(out_file, "\n");
std::copy(lp_filter.begin(), lp_filter.end(), output_iterator);

return lp_filter;
}

std::vector<short> CalculateTimeConvolution(std::vector<short> samples,


std::vector<float> lp_filter)
{
// y[n] = x[n] o h[n] = sum(-inf, inf) [ x[k] * h[n - k] ]
// y[n] - convolution vector output
// x[n] - samples input
// h[n] - impulse response input
// o - convolution operand

// y[n] = x[n] o h[n] sum(0, sampleCount) [ x[k] * h[n - k] ]


std::vector<short> convolutionRes;

// For number of samples


for (int n = 0; n < samples.size(); n++)
{
convolutionRes.push_back(0);

// For number of elements in kernel


for (int k = 0; k < lp_filter.size(); k++)
{
// Avoid negative indexes
if (n >= k)
// Apply multiplication
convolutionRes[n] += (float)samples[n - k] * lp_filter[k];
}
}

return convolutionRes;
}

You might also like