Add files.h and optimisation of QAM
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,4 @@
|
||||
*.wav
|
||||
*.txt
|
||||
*.png
|
||||
*.jpg
|
||||
|
||||
86
QAM/qam.c
86
QAM/qam.c
@ -1,8 +1,11 @@
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <complex.h>
|
||||
#include "../WAV/wav.h"
|
||||
#include "../files/files.h"
|
||||
#include <string.h>
|
||||
|
||||
#define A 10000
|
||||
|
||||
@ -17,6 +20,8 @@ struct qam_system_s {
|
||||
};
|
||||
typedef struct qam_system_s qam_system;
|
||||
|
||||
// Initialisation de la constellation (double tableau de taille sqrt(M)),
|
||||
// ToDo : changer à un tableau à 1 dimension pour éviter de calculer sqrt(M)
|
||||
void init_constellation (qam_system* qam) {
|
||||
int sm = (int)sqrt(qam->M);
|
||||
qam->constellation = (double complex**)malloc(sizeof(double complex*) * sm);
|
||||
@ -37,7 +42,7 @@ void init_constellation (qam_system* qam) {
|
||||
}
|
||||
|
||||
// Changer le tableau de bits en boolen ou alors la represenation binaire et shifter pour extraire les bits (pas bien si M plus grand)
|
||||
void bits_to_symbols (qam_system* qam, int* bits, int nb_bits, double complex* symbols) {
|
||||
void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double complex* symbols) {
|
||||
int nb_symbols = nb_bits / qam->k;
|
||||
int sm = sqrt(qam->M);
|
||||
for (int k = 0; k < nb_symbols; k++) {
|
||||
@ -51,7 +56,8 @@ void bits_to_symbols (qam_system* qam, int* bits, int nb_bits, double complex* s
|
||||
}
|
||||
}
|
||||
|
||||
void modulate (qam_system* qam,double complex* symbols, int nb_symbols, double complex* s) {
|
||||
// Modulation qam
|
||||
void modulate (qam_system* qam, double complex* symbols, int nb_symbols, double complex* s) {
|
||||
for (int k = 0; k < nb_symbols; k++) {
|
||||
double complex iq = symbols[k];
|
||||
for (int n = 0; n < qam->N; n++) {
|
||||
@ -60,7 +66,8 @@ void modulate (qam_system* qam,double complex* symbols, int nb_symbols, double c
|
||||
}
|
||||
}
|
||||
|
||||
void demodulate(qam_system* qam, double complex* s, int nb_symbols, int* bits_hat, double sigma) {
|
||||
// Demodulation qam
|
||||
void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bits_hat, double sigma) {
|
||||
for (int k = 0; k < nb_symbols; k++) {
|
||||
double complex r = 0;
|
||||
for (int n = 0; n < qam->N; n++) {
|
||||
@ -69,7 +76,9 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, int* bits_ha
|
||||
r /= qam->N;
|
||||
|
||||
// Distance euclidien de Ir et Qr pour avoir le point le plus proche de la constellation
|
||||
|
||||
int sm = (int)sqrt(qam->M);
|
||||
/* TEMPS INFINI
|
||||
double min_d = INFINITY;
|
||||
int i_cl, j_cl = 0;
|
||||
for (int i = 0; i < sm; i++) {
|
||||
@ -82,14 +91,27 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, int* bits_ha
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
double norm_factor = sqrt((double)(qam->M - 1) / 3.0);
|
||||
double Ir = creal(r) * norm_factor / A;
|
||||
double Qr = cimag(r) * norm_factor / A;
|
||||
|
||||
int id = i_cl * sm + j_cl;
|
||||
int i = (int)round((Ir + (sm - 1)) / 2.0);
|
||||
int j = (int)round((Qr + (sm - 1)) / 2.0);
|
||||
|
||||
i = (i < 0) ? 0 : ((i >= sm) ? sm - 1 : i);
|
||||
j = (j < 0) ? 0 : ((j >= sm) ? sm - 1 : j);
|
||||
|
||||
int id = i * sm + j;
|
||||
|
||||
//int id = i_cl * sm + j_cl;
|
||||
for (int b = 0; b < qam->k; b++) {
|
||||
bits_hat[k * qam->k + (qam->k - 1 - b)] = (id >> b) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Libération de la mémoire
|
||||
void free_constellation(qam_system *qam) {
|
||||
int sm = (int)sqrt(qam->M);
|
||||
for (int i = 0; i < sm; i++)
|
||||
@ -97,7 +119,12 @@ void free_constellation(qam_system *qam) {
|
||||
free(qam->constellation);
|
||||
}
|
||||
|
||||
int main () {
|
||||
int main (int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Utilisation: %s <fichier_entree>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
qam_system qam;
|
||||
qam.M = 256;
|
||||
qam.k = (int)log2((double)(qam.M));
|
||||
@ -108,40 +135,55 @@ int main () {
|
||||
init_constellation(&qam);
|
||||
|
||||
// Nombre de bit multiple de k sinon remplir de zero jusqu'a ce que ce le soit
|
||||
int bits[16] = {1,0,1,1, 0,1,1,0, 1,1,0,0, 0,0,0,1};
|
||||
int nb_bits = 16;
|
||||
int nb_symbols = 16 / qam.k;
|
||||
//int bits[16] = {1,0,1,1, 0,1,1,0, 1,1,0,0, 0,0,0,1};
|
||||
//int nb_bits = 16;
|
||||
//int nb_symbols = 16 / qam.k;
|
||||
|
||||
printf("Lecture du fichier\n");
|
||||
// Lecture du fichier et conversion en bits
|
||||
const char *input_filename = argv[1];
|
||||
bit_array input_bits = file_to_bits(input_filename);
|
||||
size_t nb_symbols = input_bits.nb_bits / qam.k;
|
||||
|
||||
double complex symbols[nb_symbols];
|
||||
bits_to_symbols(&qam, bits, nb_bits, symbols);
|
||||
printf("Mise en forme des symboles\n");
|
||||
// Mise en forme des symboles
|
||||
double complex *symbols = malloc(sizeof(double complex) * nb_symbols);
|
||||
bits_to_symbols(&qam, input_bits.bits, input_bits.nb_bits, symbols);
|
||||
|
||||
printf("Modulation\n");
|
||||
// Modulation QAM
|
||||
int total_samples = qam.N * nb_symbols;
|
||||
double complex* s = (double complex*)malloc(sizeof(double complex) * total_samples);
|
||||
modulate(&qam, symbols, nb_symbols, s);
|
||||
|
||||
int bits_hat[nb_bits];
|
||||
demodulate(&qam, s, nb_symbols, bits_hat, 0.0);
|
||||
printf("Demodulation\n");
|
||||
|
||||
for (int i = 0; i < nb_bits; i++)
|
||||
printf("%d", bits[i]);
|
||||
printf("\n");
|
||||
// Demodulation QAM
|
||||
bit_array output_bits;
|
||||
output_bits.nb_bits = input_bits.nb_bits;
|
||||
output_bits.bits = (uint8_t*)malloc(output_bits.nb_bits);
|
||||
demodulate(&qam, s, nb_symbols, output_bits.bits, 0.0);
|
||||
|
||||
for (int i = 0; i < nb_bits; i++)
|
||||
printf("%d", bits_hat[i]);
|
||||
printf("\n");
|
||||
printf("Ecriture...\n");
|
||||
// Ecriture du fichier de Demodulation
|
||||
char *output_filename = make_output_filename(input_filename);
|
||||
bits_to_file(output_filename, &output_bits);
|
||||
|
||||
|
||||
// Affichage du signal dans un .wav
|
||||
double* si = (double*)malloc(sizeof(double) * total_samples);
|
||||
|
||||
for (int i = 0; i < total_samples; i++) {
|
||||
si[i] = cimag(s[i]);
|
||||
}
|
||||
|
||||
write_wav("s.wav", si, total_samples);
|
||||
|
||||
free_constellation(&qam);
|
||||
// Libération mémoire
|
||||
free_bit_array(&input_bits);
|
||||
free_bit_array(&output_bits);
|
||||
free(symbols);
|
||||
free(s);
|
||||
free(si);
|
||||
free_constellation(&qam);
|
||||
free(output_filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
47499
QAM/sin.txt
47499
QAM/sin.txt
File diff suppressed because it is too large
Load Diff
104
files/files.c
Normal file
104
files/files.c
Normal file
@ -0,0 +1,104 @@
|
||||
#include "files.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Lire un fichier binaire et en faire un tableau de bits (0/1)
|
||||
bit_array file_to_bits(const char *filename) {
|
||||
bit_array arr = {0};
|
||||
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f) {
|
||||
perror("fopen");
|
||||
return arr;
|
||||
}
|
||||
|
||||
// Taille fichier
|
||||
fseek(f, 0, SEEK_END);
|
||||
long file_size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
if (file_size <= 0) {
|
||||
fclose(f);
|
||||
return arr;
|
||||
}
|
||||
|
||||
// Lire tous les octets
|
||||
uint8_t *raw = (uint8_t*)malloc(file_size);
|
||||
if (!raw) {
|
||||
fclose(f);
|
||||
return arr;
|
||||
}
|
||||
fread(raw, 1, file_size, f);
|
||||
fclose(f);
|
||||
|
||||
// Convertir en bits (0/1 dans uint8_t)
|
||||
arr.nb_bits = (size_t)file_size * 8;
|
||||
arr.bits = (uint8_t*)malloc(arr.nb_bits);
|
||||
if (!arr.bits) {
|
||||
free(raw);
|
||||
arr.nb_bits = 0;
|
||||
return arr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (size_t)file_size; i++) {
|
||||
for (int b = 0; b < 8; b++) {
|
||||
arr.bits[i * 8 + b] = (raw[i] >> b) & 1u;
|
||||
}
|
||||
}
|
||||
|
||||
free(raw);
|
||||
return arr;
|
||||
}
|
||||
|
||||
// Transformer un tableau de bits (0/1) en fichier binaire
|
||||
int bits_to_file(const char *filename, const bit_array *arr) {
|
||||
if (!arr || !arr->bits) return -1;
|
||||
|
||||
size_t nb_bytes = (arr->nb_bits + 7) / 8;
|
||||
uint8_t *raw = (uint8_t*)calloc(nb_bytes, 1);
|
||||
if (!raw) return -1;
|
||||
|
||||
for (size_t i = 0; i < arr->nb_bits; i++) {
|
||||
if (arr->bits[i]) {
|
||||
raw[i / 8] |= (1u << (i % 8));
|
||||
}
|
||||
}
|
||||
|
||||
FILE *f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
perror("fopen");
|
||||
free(raw);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fwrite(raw, 1, nb_bytes, f);
|
||||
fclose(f);
|
||||
free(raw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Génère un nom du type "output.<ext>" où <ext> est l'extension du fichier d'entrée
|
||||
char* make_output_filename(const char *input_filename) {
|
||||
const char *dot = strrchr(input_filename, '.');
|
||||
const char *ext = dot ? dot + 1 : "bin";
|
||||
|
||||
// Construire "output.<ext>"
|
||||
size_t len = strlen(ext) + strlen("output.") + 1;
|
||||
char *out = (char*)malloc(len);
|
||||
if (!out) return NULL;
|
||||
|
||||
snprintf(out, len, "output.%s", ext);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// Libérer la mémoire
|
||||
void free_bit_array(bit_array *arr) {
|
||||
if (arr && arr->bits) {
|
||||
free(arr->bits);
|
||||
arr->bits = NULL;
|
||||
arr->nb_bits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
21
files/files.h
Normal file
21
files/files.h
Normal file
@ -0,0 +1,21 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// Conteneur de bits (0/1 stockés dans uint8_t)
|
||||
typedef struct {
|
||||
uint8_t *bits; // tableau de 0/1
|
||||
size_t nb_bits; // nombre total de bits
|
||||
} bit_array;
|
||||
|
||||
// Lire un fichier binaire et le transformer en tableau de bits (0/1)
|
||||
bit_array file_to_bits(const char *filename);
|
||||
|
||||
// Transformer un tableau de bits (0/1) en fichier binaire
|
||||
int bits_to_file(const char *filename, const bit_array *arr);
|
||||
|
||||
// Génère un nom du type "output.<ext>" où <ext> est l'extension du fichier d'entrée
|
||||
char* make_output_filename(const char *input_filename);
|
||||
|
||||
// Libérer la mémoire du bit_array
|
||||
void free_bit_array(bit_array *arr);
|
||||
Reference in New Issue
Block a user