DD2-monitor/Beep/process.c
2021-04-13 19:14:08 +02:00

312 lines
6.5 KiB
C

/*
* AlguaBeep
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <pthread.h>
#include <curses.h>
#include <ao/ao.h>
#include "process.h"
#include "funcs.h"
/* --------------------------------------------------------------------- */
#define IMG_W 32
#define NB_SLICES 32
#define TBUFFER IMG_W*NB_SLICES
extern int verbosity;
short samples[TBUFFER*2];
static ao_device *device;
static ao_sample_format format;
static double debut;
/* --------------------------------------------------------------------- */
int init_process(int K)
{
// int foo;
int default_driver;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %d )\n", __func__, K);
#endif
ao_initialize();
default_driver = ao_default_driver_id();
#if DEBUG_LEVEL
fprintf(stderr, "%s : ao default driver #%d\n", __func__, default_driver);
#endif
memset(&format, 0, sizeof(format));
format.bits = 16;
format.channels = 2;
format.rate = 44100;
format.byte_format = AO_FMT_LITTLE;
device = ao_open_live(default_driver, &format, NULL);
if (device == NULL) {
fprintf(stderr, "Error opening AO device.\n");
return -1;
}
memset(samples, 0, sizeof(samples));
return 0;
}
/* --------------------------------------------------------------------- */
/* recherche de zones
*/
typedef struct {
int x, y;
double v;
} Datum;
static int cmp_datums(const void *a, const void *b)
{
Datum *pa = (Datum *)a;
Datum *pb = (Datum *)b;
return pa->v < pb->v;
}
static void pr_idx(int idx, int stand)
{
char chaine[100];
if (stand) standout();
sprintf(chaine, "[%03d]", idx);
addstr(chaine);
if (stand) standend();
}
static double i2freq(int i)
{
i = 333+i*42; /* please explain */
if (0==i) abort();
return 30.0* (1.0 / (double)i); /* please explain */
}
static int generate_samples(short *where, int size, Datum *datas)
{
int loop;
short value;
double vol;
char chaine[100];
#if DEBUG_LEVEL > 1
fprintf(stderr, ">>> %s ( %p %d %p )\n", __func__,
where, size, datas);
#endif
for (loop=0; loop<size; loop++) {
/* LEFT */
vol = 10000.0 * pow(datas[0].v / 256.0, 2.0);
value = (short)(sin((double)loop*i2freq(datas[0].y)) * vol);
*where++ = value;
/* RIGHT */
vol = 10000.0 * pow(datas[1].v / 256.0, 2.0);
value = (short)(sin((double)loop*i2freq(datas[1].y)) * vol);
*where++ = value;
}
sprintf(chaine, "sample %6.3f = %7d", vol, value);
mvaddstr(35, 0, chaine);
return 0;
}
/* --------------------------------------------------------------------- */
int charcuteur(unsigned char *datas, int w, int h, int K)
{
int bigR, bigC, idx;
int nbR, nbC;
double value;
Rect rect;
Datum vals[5000];
char chaine[100];
#define W 80 /* size of rectangular AOIs */
#define H 40
#define SL 4 /* position of display */
#define SC 2
#define DL 1 /* displacement factor */
#define DC 5
idx = 0;
rect.h = H; rect.w = W;
nbR = h / H; nbC = w / W;
#if DEBUG_LEVEL
sprintf(chaine, "%s %4d %4d %3d %3d\n", __func__, w, h, nbC, nbR);
mvaddstr(2, 0, chaine);
#endif
for (bigR=0; bigR<nbR; bigR++) {
rect.y = bigR * H;
for (bigC=0; bigC<nbC; bigC++) {
rect.x = bigC * W;
value = niveau_zone(datas, w, h, &rect);
vals[idx].x = bigC; vals[idx].y = bigR;
vals[idx].v = value;
sprintf(chaine, "%4.0f", value);
mvaddstr(SL+1+bigR*DL, SC+bigC*DC, chaine);
idx++;
#if DEBUG_LEVEL
fprintf(stderr, "%s %6d %6d %6d\n", __func__, bigR, bigC, idx);
#endif
}
}
qsort(vals, nbR*nbC, sizeof(Datum), cmp_datums);
for (idx=0; idx<16; idx++) {
sprintf(chaine, "%2d %2d %6.2f", vals[idx].x, vals[idx].y,
vals[idx].v);
mvaddstr(5+idx, 130, chaine);
}
/* *** sound generator ***/
generate_samples(samples, TBUFFER, vals);
/* marquer les points les plus brillants */
standout();
sprintf(chaine, "%4.0f", vals[0].v);
mvaddstr(SL+1+vals[0].y*DL, SC+vals[0].x*DC, chaine);
sprintf(chaine, "%4.0f", vals[1].v);
mvaddstr(SL+1+vals[1].y*DL, SC+vals[1].x*DC, chaine);
standend(); move(0, 0); refresh();
return -1;
}
/* --------------------------------------------------------------------- */
/*
* extraction de ligne - to be continued
*/
/* --------------------------------------------------------------------- */
/*
* entry point from the main loop
*/
int process(unsigned char *datas, int w, int h, int K)
{
short *ptr, value;
int sl, foo, minv, maxv;
unsigned int idata;
double kv;
double v_left, v_right;
Rect z_left, z_right;
char ligne[200];
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p %dx%d %d )\n", __func__, datas, w, h, K);
#endif
minv = maxv = 0;
kv = (double)K;
z_left.x = 50; z_left.y = 30;
z_left.w = 500; z_left.h = 100;
v_left = kv * pow((niveau_zone(datas, w, h, &z_left) / 256.0), 2.0);
z_right.x = 50; z_right.y = 300;
z_right.w = 500; z_right.h = 100;
v_right = kv * pow((niveau_zone(datas, w, h, &z_right) / 256.0), 2.0);
sprintf(ligne, "values %10.3f %10.3f", v_left, v_right);
mvaddstr(1, 43, ligne);
refresh();
ptr = samples;
for (sl=0; sl<NB_SLICES; sl++) {
for (foo=0; foo<IMG_W; foo+=2)
{
/* calcul position dans l'image */
idata = (foo*3) + (w*3*100);
value = (short)(v_left * ((double)datas[idata+1]-127.0));
if (value < minv) minv = value;
else if (value > maxv) maxv = value;
*ptr++ = value;
value = (short)(v_right * ((double)datas[idata+2]-127.0));
if (value < minv) minv = value;
else if (value > maxv) maxv = value;
*ptr++ = value;
}
}
// puts("");
if (verbosity) {
sprintf(ligne, " min %6d max %6d\n", minv, maxv);
mvaddstr(11, 3, ligne);
refresh();
}
return 0;
}
/* --------------------------------------------------------------------- */
void * thr_action(void *ptr)
{
long idx;
// int foo;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %p )\n", __func__, ptr);
fprintf(stderr, " value is %d\n", *(int *)ptr);
#endif
while(1) {
if (verbosity > 1) {
fprintf(stderr, "%s t=%.3g\n", __func__, dtime() - debut);
}
for (idx=0; idx<100; idx++) {
ao_play(device, (char *)samples, TBUFFER*2);
}
}
return NULL;
}
/* --------------------------------------------------------------------- */
int lancement_thread_son(int k)
{
static pthread_t thread;
static int pid;
int foo;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %d )\n", __func__, k);
#endif
debut = dtime();
/* lancement du thread de rendu sonore */
pid = getpid();
foo = pthread_create(&thread, NULL, thr_action, &pid);
fprintf(stderr, "thread creation -> %d\n", foo);
if (foo) {
fprintf(stderr, "epic fail in %s:%s\n", __FILE__, __func__);
exit(1);
}
return 0;
}
/* --------------------------------------------------------------------- */