Implement automatic gain control
This commit is contained in:
@@ -32,6 +32,16 @@
|
|||||||
|
|
||||||
#define CHISTSIZE 512
|
#define CHISTSIZE 512
|
||||||
|
|
||||||
|
#define SHISTSIZE 200
|
||||||
|
|
||||||
|
#define CLIPDELTA (20)
|
||||||
|
#define SMAXMIN (24576)
|
||||||
|
#define SMAXMAX (31129)
|
||||||
|
#define DOWNDELTA (3)
|
||||||
|
#define UPDELTA (1)
|
||||||
|
#define VOLMIN (1)
|
||||||
|
#define VOLMAX (255)
|
||||||
|
|
||||||
double outputslist[NOUTPUTS] = {
|
double outputslist[NOUTPUTS] = {
|
||||||
1, 3, 7, 15, 31, 63, 127, 255, 511, 1023
|
1, 3, 7, 15, 31, 63, 127, 255, 511, 1023
|
||||||
};
|
};
|
||||||
@@ -67,14 +77,17 @@ int minp, maxp;
|
|||||||
double lastsum[NOUTPUTS];
|
double lastsum[NOUTPUTS];
|
||||||
double history[NOUTPUTS][HISTSIZE];
|
double history[NOUTPUTS][HISTSIZE];
|
||||||
double chistory[NOUTPUTS][CHISTSIZE];
|
double chistory[NOUTPUTS][CHISTSIZE];
|
||||||
|
int shistory[SHISTSIZE];
|
||||||
int histptr;
|
int histptr;
|
||||||
int chistptr;
|
int chistptr;
|
||||||
|
int shistptr;
|
||||||
char buffer[BUFSIZE];
|
char buffer[BUFSIZE];
|
||||||
char *bufptr;
|
char *bufptr;
|
||||||
int bufleft;
|
int bufleft;
|
||||||
double phase;
|
double phase;
|
||||||
double confidence;
|
double confidence;
|
||||||
int audio_initialised = 0;
|
int audio_initialised = 0;
|
||||||
|
int volume;
|
||||||
|
|
||||||
#define HISTORY(i, x) (history[i][((histptr+(x) >= HISTSIZE) ? histptr+(x)-HISTSIZE : histptr+(x))])
|
#define HISTORY(i, x) (history[i][((histptr+(x) >= HISTSIZE) ? histptr+(x)-HISTSIZE : histptr+(x))])
|
||||||
|
|
||||||
@@ -96,6 +109,16 @@ int audio_initialised = 0;
|
|||||||
chistptr = 0; \
|
chistptr = 0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define SHISTORY(x) (shistory[((shistptr+(x) >= SHISTSIZE) ? shistptr+(x)-SHISTSIZE : shistptr+(x))])
|
||||||
|
|
||||||
|
#define SHISTWRITE(x) shistory[shistptr] = (x)
|
||||||
|
|
||||||
|
#define SHISTNEXT do { \
|
||||||
|
shistptr++; \
|
||||||
|
if (shistptr >= SHISTSIZE) \
|
||||||
|
shistptr = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define SUMSQ(a, b) ((a) * (a) + (b) * (b))
|
#define SUMSQ(a, b) ((a) * (a) + (b) * (b))
|
||||||
#define MAGSQ(i) SUMSQ(freqs[2*(i)], freqs[2*(i)+1])
|
#define MAGSQ(i) SUMSQ(freqs[2*(i)], freqs[2*(i)+1])
|
||||||
|
|
||||||
@@ -131,7 +154,7 @@ int beatdetect_init(void)
|
|||||||
info.record.channels = 1;
|
info.record.channels = 1;
|
||||||
info.record.precision = 16;
|
info.record.precision = 16;
|
||||||
info.record.encoding = AUDIO_ENCODING_SLINEAR;
|
info.record.encoding = AUDIO_ENCODING_SLINEAR;
|
||||||
info.record.gain = oinfo.record.gain;
|
volume = info.record.gain = oinfo.record.gain;
|
||||||
info.record.port = oinfo.record.port;
|
info.record.port = oinfo.record.port;
|
||||||
info.record.balance = oinfo.record.balance;
|
info.record.balance = oinfo.record.balance;
|
||||||
|
|
||||||
@@ -160,6 +183,24 @@ int beatdetect_init(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void beatdetect_volume(int vol)
|
||||||
|
{
|
||||||
|
audio_info_t info;
|
||||||
|
|
||||||
|
if (audiofd < 0)
|
||||||
|
return;
|
||||||
|
if (ioctl(audiofd, AUDIO_GETINFO, &info) < 0) {
|
||||||
|
printf("ERROR: can't get audio info\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info.record.gain = vol;
|
||||||
|
/* printf("Set record gain to %d\n", vol); */
|
||||||
|
if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0) {
|
||||||
|
printf("ERROR: can't set audio info\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int beatdetect_read(void)
|
int beatdetect_read(void)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -168,6 +209,8 @@ int beatdetect_read(void)
|
|||||||
int i, j, n, p;
|
int i, j, n, p;
|
||||||
int rv;
|
int rv;
|
||||||
int clip;
|
int clip;
|
||||||
|
int smax, smaxh;
|
||||||
|
int changevol;
|
||||||
double localsum[NOUTPUTS];
|
double localsum[NOUTPUTS];
|
||||||
fft_type *freqs;
|
fft_type *freqs;
|
||||||
int count;
|
int count;
|
||||||
@@ -179,6 +222,7 @@ int beatdetect_read(void)
|
|||||||
double cmax;
|
double cmax;
|
||||||
int mi, mj, mp;
|
int mi, mj, mp;
|
||||||
int cmi, cmj, cmp;
|
int cmi, cmj, cmp;
|
||||||
|
int ovolume;
|
||||||
|
|
||||||
if (!audio_initialised)
|
if (!audio_initialised)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -216,14 +260,55 @@ int beatdetect_read(void)
|
|||||||
fft_data_signed16((int16_t *)buffer);
|
fft_data_signed16((int16_t *)buffer);
|
||||||
|
|
||||||
clip = 0;
|
clip = 0;
|
||||||
|
smax = 0;
|
||||||
|
|
||||||
/* Check for clip and compute rms */
|
/* Check for clip and compute rms */
|
||||||
for (i = 0; i < BUFSIZE/2; i++) {
|
for (i = 0; i < BUFSIZE/2; i++) {
|
||||||
int sample = ((int16_t *)buffer)[i];
|
int sample = ((int16_t *)buffer)[i];
|
||||||
|
if (abs(sample) > smax)
|
||||||
|
smax = abs(sample);
|
||||||
if ((sample == INT16_MAX) || (sample == (-1 - INT16_MAX)))
|
if ((sample == INT16_MAX) || (sample == (-1 - INT16_MAX)))
|
||||||
clip = 1;
|
clip = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHISTWRITE(smax);
|
||||||
|
SHISTNEXT;
|
||||||
|
|
||||||
|
smaxh = 0;
|
||||||
|
changevol = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < SHISTSIZE; i++) {
|
||||||
|
if (SHISTORY(i) > smaxh)
|
||||||
|
smaxh = SHISTORY(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ideal smax range is between 75% and 95% of full signal */
|
||||||
|
|
||||||
|
ovolume = volume;
|
||||||
|
|
||||||
|
if (clip) {
|
||||||
|
volume = volume - CLIPDELTA;
|
||||||
|
changevol = 1;
|
||||||
|
} else {
|
||||||
|
if (smax > SMAXMAX) {
|
||||||
|
volume = volume - DOWNDELTA;
|
||||||
|
changevol = 1;
|
||||||
|
}
|
||||||
|
if (smaxh < SMAXMIN) {
|
||||||
|
volume = volume + UPDELTA;
|
||||||
|
changevol = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changevol) {
|
||||||
|
if (volume < VOLMIN)
|
||||||
|
volume = 1;
|
||||||
|
if (volume > VOLMAX)
|
||||||
|
volume = VOLMAX;
|
||||||
|
if (volume != ovolume)
|
||||||
|
beatdetect_volume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
fft_window();
|
fft_window();
|
||||||
fft_compute();
|
fft_compute();
|
||||||
freqs = fft_getresult();
|
freqs = fft_getresult();
|
||||||
|
|||||||
Reference in New Issue
Block a user