0% found this document useful (0 votes)
11 views5 pages

XLTH

Uploaded by

dung.dt210202
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views5 pages

XLTH

Uploaded by

dung.dt210202
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

#include <stdio.

h>
#include <stdlib.h>
#include <math.h>
#include <portaudio.h>
#include <windows.h>
#include <string.h>
#include <fftw3.h>

#define SAMPLE_RATE 44100


#define FRAMES_PER_BUFFER 1024
#define OVERLAP_SIZE 512 // Size of overlap between blocks
#define FILTER_SIZE 101 // Must be odd for symmetric FIR filter
#define PI 3.141592653589793

// Global control variables for real-time adjustment


float bassGain = 1.0, midGain = 1.0, trebleGain = 1.0;
float bassFreq = 100, midFreq = 1000, trebleFreq = 8000;
float bandwidth = 0.2; // Bandwidth as a percentage

// Mutex for synchronizing parameter changes


CRITICAL_SECTION controlMutex;

// Generate a Hamming window


void hammingWindow(float *window, int size) {
for (int i = 0; i < size; i++) {
window[i] = 0.54 - 0.46 * cos(2 * PI * i / (size - 1));
}
}

// Generate a Blackman window


void blackmanWindow(float *window, int size) {
for (int i = 0; i < size; i++) {
window[i] = 0.42 - 0.5 * cos(2 * PI * i / (size - 1)) + 0.08 * cos(4 * PI *
i / (size - 1));
}
}

// Design a low-pass FIR filter


void designLowPassFilter(float *filter, int size, float cutoff, float sampleRate) {
float window[size];
hammingWindow(window, size);

int halfSize = size / 2;


float normCutoff = cutoff / sampleRate;

for (int i = 0; i < size; i++) {


int n = i - halfSize;
if (n == 0) {
filter[i] = 2.0 * normCutoff;
} else {
filter[i] = sin(2.0 * PI * normCutoff * n) / (PI * n);
}
filter[i] *= window[i];
}
}

// Design a band-pass FIR filter


void designBandPassFilter(float *filter, int size, float centerFreq, float
bandwidth, float sampleRate) {
float window[size];
blackmanWindow(window, size);

int halfSize = size / 2;


float normLowCut = (centerFreq * (1 - bandwidth / 2)) / sampleRate;
float normHighCut = (centerFreq * (1 + bandwidth / 2)) / sampleRate;

for (int i = 0; i < size; i++) {


int n = i - halfSize;
if (n == 0) {
filter[i] = 2.0 * (normHighCut - normLowCut);
} else {
filter[i] = (sin(2.0 * PI * normHighCut * n) - sin(2.0 * PI *
normLowCut * n)) / (PI * n);
}
filter[i] *= window[i];
}
}

// Apply FIR filters with overlap-add technique


void applyFIRFiltersOverlapAdd(float *input, float *output, unsigned long
framesPerBuffer, float sampleRate) {
static int filtersInitialized = 0;
static float *lowPassFilter, *bassFilter, *midFilter, *trebleFilter;
static float overlapBuffer[OVERLAP_SIZE];
static int overlapIndex = 0;

if (!filtersInitialized) {
// Allocate memory for filters
lowPassFilter = (float *)calloc(FILTER_SIZE, sizeof(float));
bassFilter = (float *)calloc(FILTER_SIZE, sizeof(float));
midFilter = (float *)calloc(FILTER_SIZE, sizeof(float));
trebleFilter = (float *)calloc(FILTER_SIZE, sizeof(float));

filtersInitialized = 1;
}

// Lock parameters for thread safety


EnterCriticalSection(&controlMutex);

// Recalculate filters if parameters have changed


designLowPassFilter(lowPassFilter, FILTER_SIZE, 20000, sampleRate);
designBandPassFilter(bassFilter, FILTER_SIZE, bassFreq, bandwidth, sampleRate);
designBandPassFilter(midFilter, FILTER_SIZE, midFreq, bandwidth, sampleRate);
designBandPassFilter(trebleFilter, FILTER_SIZE, trebleFreq, bandwidth,
sampleRate);

LeaveCriticalSection(&controlMutex);

// Process the input signal using the overlap-add technique


for (int i = 0; i < framesPerBuffer; i++) {
float lowPassedSignal[framesPerBuffer];

// Apply the low-pass filter to the input signal (as an example)


for (int j = 0; j < framesPerBuffer; j++) {
lowPassedSignal[j] = 0;
for (int k = 0; k < FILTER_SIZE; k++) {
if (j - k >= 0) {
lowPassedSignal[j] += input[j - k] * lowPassFilter[k];
}
}
}

// Apply the filters in the same manner (Bass, Mid, Treble)


float bassSignal = 0, midSignal = 0, trebleSignal = 0;

for (int j = 0; j < framesPerBuffer; j++) {


// Bass filter
bassSignal = 0;
for (int k = 0; k < FILTER_SIZE; k++) {
if (j - k >= 0) {
bassSignal += lowPassedSignal[j - k] * bassFilter[k];
}
}

// Mid filter
midSignal = 0;
for (int k = 0; k < FILTER_SIZE; k++) {
if (j - k >= 0) {
midSignal += lowPassedSignal[j - k] * midFilter[k];
}
}

// Treble filter
trebleSignal = 0;
for (int k = 0; k < FILTER_SIZE; k++) {
if (j - k >= 0) {
trebleSignal += lowPassedSignal[j - k] * trebleFilter[k];
}
}

// Combine filtered signals with gain


output[i] = bassGain * bassSignal + midGain * midSignal + trebleGain *
trebleSignal;
}

// Handle overlap (this part is simplified for this demonstration)


if (overlapIndex < OVERLAP_SIZE) {
overlapBuffer[overlapIndex] = output[i];
overlapIndex++;
} else {
// Add the overlapping part to the output buffer
for (int j = 0; j < OVERLAP_SIZE; j++) {
output[i - OVERLAP_SIZE + j] += overlapBuffer[j];
}
overlapBuffer[overlapIndex] = output[i];
overlapIndex = (overlapIndex + 1) % OVERLAP_SIZE;
}
}
}

// Audio processing callback with overlap-add technique


static int audioCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData) {
float *in = (float *)inputBuffer;
float *out = (float *)outputBuffer;

// Apply FIR filters using overlap-add technique


applyFIRFiltersOverlapAdd(in, out, framesPerBuffer, SAMPLE_RATE);

return paContinue;
}

// Thread for handling keyboard input


DWORD WINAPI keyboardThread(LPVOID arg) {
while (1) {
printf("\nAdjust Parameters:\n");
printf("1. Change Bass Gain\n");
printf("2. Change Mid Gain\n");
printf("3. Change Treble Gain\n");
printf("4. Change Bass Frequency\n");
printf("5. Change Mid Frequency\n");
printf("6. Change Treble Frequency\n");
printf("> ");

int choice;
float newGain;

scanf("%d", &choice);

EnterCriticalSection(&controlMutex);
switch (choice) {
case 1:
printf("Enter new Bass Gain: ");
scanf("%f", &newGain);
bassGain = newGain;
break;
case 2:
printf("Enter new Mid Gain: ");
scanf("%f", &newGain);
midGain = newGain;
break;
case 3:
printf("Enter new Treble Gain: ");
scanf("%f", &newGain);
trebleGain = newGain;
break;
case 4:
printf("Enter new Bass Frequency: ");
scanf("%f", &bassFreq);
break;
case 5:
printf("Enter new Mid Frequency: ");
scanf("%f", &midFreq);
break;
case 6:
printf("Enter new Treble Frequency: ");
scanf("%f", &trebleFreq);
break;
default:
printf("Invalid choice\n");
}
LeaveCriticalSection(&controlMutex);
}
return 0;
}

int main() {
PaError err;

// Initialize PortAudio
err = Pa_Initialize();
if (err != paNoError) {
fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
return 1;
}

// Open audio stream


PaStream *stream;
err = Pa_OpenDefaultStream(&stream,
1, // Input channels
1, // Output channels
paFloat32, // Sample format
SAMPLE_RATE,
FRAMES_PER_BUFFER,
audioCallback,
NULL);
if (err != paNoError) {
fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
return 1;
}

// Create and start keyboard input thread


InitializeCriticalSection(&controlMutex);
HANDLE hThread = CreateThread(NULL, 0, keyboardThread, NULL, 0, NULL);

// Start the audio stream


err = Pa_StartStream(stream);
if (err != paNoError) {
fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
return 1;
}

// Run until user decides to exit


printf("Press Enter to quit...\n");
getchar();

// Stop and close the stream


Pa_StopStream(stream);
Pa_CloseStream(stream);
Pa_Terminate();
DeleteCriticalSection(&controlMutex);
return 0;
}

You might also like