Fichiers audio, journal, annales

This commit is contained in:
Adrien Guatto
2025-11-04 18:33:00 +01:00
parent abf505668e
commit 88595d288f
21 changed files with 1326 additions and 0 deletions

198
cours/audio/vcd_lib.c Normal file
View File

@@ -0,0 +1,198 @@
#include "vcd_lib.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "buffer.h"
size_t vcd_sizeof_signal_type(vcd_signal_type_t type) {
switch (type) {
case VCD_SIGNAL_TYPE_BOOL:
return sizeof(int);
case VCD_SIGNAL_TYPE_INT:
return sizeof(int);
case VCD_SIGNAL_TYPE_FLOAT:
return sizeof(float);
}
}
typedef struct vcd_signal {
char *name;
vcd_signal_type_t type;
buffer_t *samples;
} vcd_signal_t;
vcd_signal_t *vcd_signal_alloc(const char *name,
vcd_signal_type_t type,
size_t initial_buffer_size) {
vcd_signal_t *res = malloc_checked(sizeof *res);
res->name = strdup_checked(name);
res->type = type;
res->samples =
buffer_alloc(initial_buffer_size * vcd_sizeof_signal_type(type));
return res;
}
void vcd_signal_free(vcd_signal_t *signal) {
assert (signal);
buffer_free(signal->samples);
free(signal->name);
free(signal);
}
void vcd_add_samples(vcd_signal_t *signal, void *samples, size_t count) {
assert (signal);
assert (samples);
buffer_write(signal->samples,
samples,
count * vcd_sizeof_signal_type(signal->type));
}
const char *vcd_time_unit_repr(vcd_time_unit_t u) {
const char *table[] = { "s", "ms", "us", "ns", "ps", "fs" };
assert (VCD_TIME_UNIT_S <= u && u <= VCD_TIME_UNIT_FS);
return table[u];
}
typedef struct vcd_file {
char *filename;
buffer_t *signals;
vcd_time_unit_t time_unit;
size_t time_unit_factor;
} vcd_file_t;
vcd_file_t *vcd_file_alloc(const char *filename,
vcd_time_unit_t time_unit,
size_t time_unit_factor) {
assert (filename);
vcd_file_t *vcd = malloc_checked(sizeof *vcd);
vcd->filename = strdup_checked(filename);
vcd->time_unit = time_unit;
vcd->time_unit_factor = time_unit_factor;
vcd->signals = buffer_alloc(10 * sizeof(vcd_signal_t));
return vcd;
}
void vcd_file_free(vcd_file_t *vcd) {
assert (vcd);
/* Free buffers. */
buffer_foreach (vcd_signal_t *, psig, vcd->signals)
vcd_signal_free(*psig);
buffer_free(vcd->signals);
free(vcd->filename);
free(vcd);
}
vcd_signal_t *vcd_file_lookup_signal(const vcd_file_t *vcd, const char *name) {
assert (vcd);
assert (name);
vcd_signal_t *res = NULL;
buffer_foreach (vcd_signal_t *, psig, vcd->signals) {
if (strcmp((*psig)->name, name) == 0) {
res = *psig;
break;
}
}
return res;
}
bool vcd_file_add_signal(const vcd_file_t *vcd, vcd_signal_t *signal) {
assert (vcd);
assert (signal);
if (vcd_file_lookup_signal(vcd, signal->name))
return false;
buffer_write(vcd->signals, &signal, sizeof signal);
return true;
}
bool vcd_file_write(vcd_file_t *vcd) {
FILE *f = fopen(vcd->filename, "w");
if (!f)
return false;
time_t current_time;
time(&current_time);
fprintf(f, "$version Generated by vcd.c $end\n");
fprintf(f, "$date %s $end\n", ctime(&current_time));
fprintf(f, "$timescale %zu %s $end\n",
vcd->time_unit_factor,
vcd_time_unit_repr(vcd->time_unit));
/* Dump signal declarations. */
fprintf(f, "$scope module Top $end\n");
buffer_foreach (vcd_signal_t *, psig, vcd->signals) {
fprintf(f, "$var ");
switch ((*psig)->type) {
case VCD_SIGNAL_TYPE_BOOL:
fprintf(f, "wire 1");
break;
case VCD_SIGNAL_TYPE_INT:
fprintf(f, "integer %zu", 8 * sizeof(int));
break;
case VCD_SIGNAL_TYPE_FLOAT:
fprintf(f, "real 32");
break;
}
fprintf(f, " %p %s $end\n", (*psig), (*psig)->name);
}
fprintf(f, "$upscope $end\n");
fprintf(f, "$enddefinitions\n");
/* Dump samples. */
fprintf(f, "$dumpvars\n");
/* We maintain a pointer to the current sample in each buffer. */
size_t signal_count = vcd->signals->occupancy / sizeof(vcd_signal_t *);
unsigned char **psamples = calloc(signal_count, sizeof(unsigned char *));
assert (psamples);
for (size_t i = 0; i < signal_count; i++)
psamples[i] = ((vcd_signal_t **)vcd->signals->data)[i]->samples->data;
/* We dump */
bool active = true;
for (size_t step = 0; active; step++) {
fprintf(f, "#%zu\n", step);
active = false;
for (size_t i = 0; i < signal_count; i++) {
vcd_signal_t *sig = ((vcd_signal_t **)vcd->signals->data)[i];
if (psamples[i] < sig->samples->data + sig->samples->occupancy) {
active = true;
switch (sig->type) {
case VCD_SIGNAL_TYPE_BOOL:
fprintf(f, "%d%p\n", (*(int *)psamples[i] ? 1 : 0), sig);
psamples[i] += sizeof(int);
break;
case VCD_SIGNAL_TYPE_INT:
fprintf(f, "r%d %p\n", *(int *)psamples, sig);
psamples[i] += sizeof(int);
break;
case VCD_SIGNAL_TYPE_FLOAT:
fprintf(f, "r%.16g %p\n", *(float *)psamples, sig);
psamples[i] += sizeof(float);
break;
}
}
}
}
free(psamples);
fclose(f);
return true;
}