diff --git a/Convolution/README.md b/Convolution/README.md new file mode 100644 index 0000000000..3e26587a56 --- /dev/null +++ b/Convolution/README.md @@ -0,0 +1,50 @@ +# Convolution + +## Understanding Convolution + +### What Is Convolution? +Convolution is simple, but how it works looks a little tricky but not something you would never understand. +An application with which most of us are familiar will make it easy,Imagine you have a recording of someone +speaking,but there’s background noise — maybe static or hum from a fan. +If you plot the audio signal, it’s just a long 1D waveform (amplitude vs. time). The unwanted noise appears +as rapid, random fluctuations on top of the smooth speech waveform. + +To reduce this noise, we can apply a low-pass filter — a small sequence of numbers (a kernel) that emphasizes +slow changes (speech patterns) and suppresses fast, noisy changes. + +Here’s what happens during convolution: + +You slide this filter across the audio signal. + +At each step, you multiply the overlapping values and sum them up. + +The resulting output is a smoothed version of the signal, where random high-frequency noise has been reduced. + +Mathematically, the convolution operation combines nearby samples in a way that averages out the unwanted +fluctuations while keeping the overall structure intact. +That’s why convolution is widely used in digital signal processing — to filter out noise, enhance features, or +detect specific patterns (like beats or speech cues). +This is an example for the one dimenstional convolution we will try to implement the basic implementation which looks +mathematically daunting but it's cakewalk if you understand the implementation + +### Project setup +The C code I provided will walk you through the implementation +feel free to clone this repository and try to code this up by yourself +``` +git clone https://github.com/depuc/Convolution.git +``` +set up your Python environment (if required): +``` +python3 -m venv venv +source venv/bin/activate +``` +Then install the required packages +``` +pip install -r requirements.txt +``` +once everything is setup you can directly run the compiled binary +``` +conv +``` +Tweak the code, try out floating numbers get creative. + diff --git a/Convolution/conv b/Convolution/conv new file mode 100755 index 0000000000..d255f34988 Binary files /dev/null and b/Convolution/conv differ diff --git a/Convolution/requirements.txt b/Convolution/requirements.txt new file mode 100644 index 0000000000..aa094d9f64 --- /dev/null +++ b/Convolution/requirements.txt @@ -0,0 +1,2 @@ +numpy +matplotlib diff --git a/Convolution/src/convolve.c b/Convolution/src/convolve.c new file mode 100644 index 0000000000..f7d3e25d49 --- /dev/null +++ b/Convolution/src/convolve.c @@ -0,0 +1,154 @@ +#include +#include + +void input_array(int *arr, int size){ + + for(int i = 0; i < size; i++){ + + scanf("%d", &arr[i]); + + } + + return; + +} + +void print_array(int *arr, int size,const char* str) { + + printf("%s : ", str); + + for(int i = 0; i < size; i++){ + + printf("%d ", arr[i]); + } + + printf("\n"); + + return; + +} + +void convolve(int *filter, int *input, int *output, int M, int N){ + + for(int n = 0; n < M+N-1; n++){ + for(int k = 0; k < M;k++){ + if( (n-k >= 0) && (n-k) < N){ + + output[n] += filter[k]*input[n-k]; + } + } + } + + return; + +} + +void file_writer(FILE *file_pointer, int *array, int size){ + + for(int i = 0; i < size; i++){ + fprintf(file_pointer,"%d ",array[i]); + } + + fprintf(file_pointer,"\n"); + + return; + +} + +void write_to_file(const char* filename, int *filter, int* input, int* output,int M,int N,int Y){ + + FILE *file_pointer = fopen(filename, "w"); + + if(file_pointer == NULL){ + + printf("Error: could not open the file %s for writing",filename); + return; + + } + + file_writer(file_pointer,input,N); + file_writer(file_pointer,filter,M); + file_writer(file_pointer,output,Y); + + fclose(file_pointer); + +} + +void draw_line(void){ + + printf("=============================\n"); + +} + +int main(){ + + int M,N; + + printf("ENTER INPUT SIZE-> "); + scanf("%d", &N); + + printf("ENTER FILTER SIZE-> "); + scanf("%d", &M); + + draw_line(); + + int Y = M+N-1; + + int *filter = (int *)malloc(M*sizeof(int)); + int *input = (int *)malloc(N*sizeof(int)); + int *output = (int *)calloc(Y, sizeof(int)); + + if (filter == NULL || input == NULL || output == NULL) { + printf("Memory allocation failed!\n"); + return 1; + } + + printf("ENTER INPUT-> "); + input_array(input, N); + + printf("ENTER FILTER-> "); + input_array(filter,M); + + convolve(filter,input,output,M,N); + + draw_line(); + + print_array(input,N, "INPUT ARRAY->"); + print_array(filter,M, "FILTER ARRAY->"); + + draw_line(); + + print_array(output,M+N-1, "CONVOLVED ARRAY->"); + + draw_line(); + + char decision; + printf("Plot your output? [y/n]: "); + + scanf(" %c",&decision); + + if(decision == 'y' || decision == 'Y'){ + + write_to_file("data.txt",filter,input,output,M,N,Y); + free(filter); + free(input); + free(output); + system("python3 ./src/plotter.py"); + return 0; + + } + + else{ + + free(filter); + free(input); + free(output); + return 0; + + } + + return 0; + +} + + diff --git a/Convolution/src/plotter.py b/Convolution/src/plotter.py new file mode 100644 index 0000000000..6e79f2b484 --- /dev/null +++ b/Convolution/src/plotter.py @@ -0,0 +1,53 @@ +import numpy as np +import matplotlib.pyplot as plt +import sys +import os +from matplotlib.ticker import MaxNLocator + +FILENAME = "data.txt" + +def plot_convolution_data(): + """Reads the data file and plots the convolution results.""" + plt.style.use('dark_background') + plt.rcParams["font.family"] = "sans-serif" + + try: + with open(FILENAME, 'r') as f: + lines = f.readlines() + if len(lines) < 3: + print(f"Python Error: '{FILENAME}' does not contain three lines.") + sys.exit(1) + + input_signal = np.array([int(x) for x in lines[0].strip().split()]) + filter_kernel = np.array([int(x) for x in lines[1].strip().split()]) + output_signal = np.array([int(x) for x in lines[2].strip().split()]) + + except FileNotFoundError: + print(f"Python Error: Could not find '{FILENAME}'.") + sys.exit(1) + except Exception as e: + print(f"Python Error: An error occurred while reading the file: {e}") + sys.exit(1) + + fig, axs = plt.subplots(3, 1, figsize=(10, 8), tight_layout=True) + fig.suptitle('Convolution Results', fontsize=18) + + # Plot Input Signal + axs[0].stem(input_signal) + axs[0].set_title(f'Input Signal (Size: {len(input_signal)})') + axs[0].xaxis.set_major_locator(MaxNLocator(integer=True)) + + # Plot Filter Kernel + axs[1].stem(filter_kernel) + axs[1].set_title(f'Filter Kernel (Size: {len(filter_kernel)})') + axs[1].xaxis.set_major_locator(MaxNLocator(integer=True)) + + # Plot Output (Convolved) Signal + axs[2].stem(output_signal) + axs[2].set_title(f'Output Signal (Size: {len(output_signal)})') + axs[2].xaxis.set_major_locator(MaxNLocator(integer=True)) + os.remove('data.txt') + plt.show() + +if __name__ == "__main__": + plot_convolution_data()