312 lines
6.5 KiB
C
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;
|
|
}
|
|
/* --------------------------------------------------------------------- */
|