gsmopen: continue cleaning from alsa

This commit is contained in:
Giovanni Maruzzelli 2012-04-06 22:15:46 +02:00
parent 49a4d2126b
commit 40a1fd8ef0
1 changed files with 0 additions and 342 deletions

View File

@ -2480,348 +2480,6 @@ int gsmopen_senddigit(private_t *tech_pvt, char digit)
return 0;
}
#ifdef GSMOPEN_ALSA
/*! \brief Write audio frames to interface */
int alsa_write(private_t *tech_pvt, short *data, int datalen)
{
static char sizbuf[8000];
static char sizbuf2[16000];
static char silencebuf[8000];
static int sizpos = 0;
int len = sizpos;
int pos;
int res = 0;
time_t now_timestamp;
/* size_t frames = 0; */
snd_pcm_state_t state;
snd_pcm_sframes_t delayp1 = 0;
snd_pcm_sframes_t delayp2 = 0;
if (tech_pvt->no_sound == 1) {
return res;
}
memset(sizbuf, 255, sizeof(sizbuf));
memset(sizbuf2, 255, sizeof(sizbuf));
memset(silencebuf, 255, sizeof(sizbuf));
//ERRORA("data=%p, datalen=%d\n", GSMOPEN_P_LOG, (void *)data, datalen);
/* We have to digest the frame in 160-byte portions */
if (datalen > sizeof(sizbuf) - sizpos) {
ERRORA("Frame too large\n", GSMOPEN_P_LOG);
res = -1;
} else {
memcpy(sizbuf + sizpos, data, datalen);
memset(data, 255, datalen);
len += datalen;
pos = 0;
#ifdef ALSA_MONITOR
alsa_monitor_write(sizbuf, len);
#endif
state = snd_pcm_state(tech_pvt->alsap);
if (state == SND_PCM_STATE_XRUN) {
int i;
DEBUGA_GSMOPEN
("You've got an ALSA write XRUN in the past (gsmopen can't fill the soundcard buffer fast enough). If this happens often (not after silence or after a pause in the speech, that's OK), and appear to damage the sound quality, first check if you have some IRQ problem, maybe sharing the soundcard IRQ with a broken or heavy loaded ethernet or graphic card. Then consider to increase the alsa_periods_in_buffer (now is set to %d) for this interface in the config file\n",
GSMOPEN_P_LOG, tech_pvt->alsa_periods_in_buffer);
res = snd_pcm_prepare(tech_pvt->alsap);
if (res) {
ERRORA("audio play prepare failed: %s\n", GSMOPEN_P_LOG, snd_strerror(res));
} else {
res = snd_pcm_format_set_silence(gsmopen_format, silencebuf, len / 2);
if (res < 0) {
DEBUGA_GSMOPEN("Silence error %s\n", GSMOPEN_P_LOG, snd_strerror(res));
res = -1;
}
for (i = 0; i < (tech_pvt->alsa_periods_in_buffer - 1); i++) {
res = snd_pcm_writei(tech_pvt->alsap, silencebuf, len / 2);
if (res != len / 2) {
DEBUGA_GSMOPEN("Write returned a different quantity: %d\n", GSMOPEN_P_LOG, res);
res = -1;
} else if (res < 0) {
DEBUGA_GSMOPEN("Write error %s\n", GSMOPEN_P_LOG, snd_strerror(res));
res = -1;
}
}
}
}
res = snd_pcm_delay(tech_pvt->alsap, &delayp1);
if (res < 0) {
DEBUGA_GSMOPEN("Error %d on snd_pcm_delay: \"%s\"\n", GSMOPEN_P_LOG, res, snd_strerror(res));
res = snd_pcm_prepare(tech_pvt->alsap);
if (res) {
DEBUGA_GSMOPEN("snd_pcm_prepare failed: '%s'\n", GSMOPEN_P_LOG, snd_strerror(res));
}
res = snd_pcm_delay(tech_pvt->alsap, &delayp1);
}
delayp2 = snd_pcm_avail_update(tech_pvt->alsap);
if (delayp2 < 0) {
DEBUGA_GSMOPEN("Error %d on snd_pcm_avail_update: \"%s\"\n", GSMOPEN_P_LOG, (int) delayp2, snd_strerror(delayp2));
res = snd_pcm_prepare(tech_pvt->alsap);
if (res) {
DEBUGA_GSMOPEN("snd_pcm_prepare failed: '%s'\n", GSMOPEN_P_LOG, snd_strerror(res));
}
delayp2 = snd_pcm_avail_update(tech_pvt->alsap);
}
if ( /* delayp1 != 0 && delayp1 != 160 */
delayp1 < 160 || delayp2 > tech_pvt->alsa_buffer_size) {
res = snd_pcm_prepare(tech_pvt->alsap);
if (res) {
DEBUGA_GSMOPEN
("snd_pcm_prepare failed while trying to prevent an ALSA write XRUN: %s, delayp1=%d, delayp2=%d\n",
GSMOPEN_P_LOG, snd_strerror(res), (int) delayp1, (int) delayp2);
} else {
int i;
for (i = 0; i < (tech_pvt->alsa_periods_in_buffer - 1); i++) {
res = snd_pcm_format_set_silence(gsmopen_format, silencebuf, len / 2);
if (res < 0) {
DEBUGA_GSMOPEN("Silence error %s\n", GSMOPEN_P_LOG, snd_strerror(res));
res = -1;
}
res = snd_pcm_writei(tech_pvt->alsap, silencebuf, len / 2);
if (res < 0) {
DEBUGA_GSMOPEN("Write error %s\n", GSMOPEN_P_LOG, snd_strerror(res));
res = -1;
} else if (res != len / 2) {
DEBUGA_GSMOPEN("Write returned a different quantity: %d\n", GSMOPEN_P_LOG, res);
res = -1;
}
}
DEBUGA_GSMOPEN
("PREVENTING an ALSA write XRUN (gsmopen can't fill the soundcard buffer fast enough). If this happens often (not after silence or after a pause in the speech, that's OK), and appear to damage the sound quality, first check if you have some IRQ problem, maybe sharing the soundcard IRQ with a broken or heavy loaded ethernet or graphic card. Then consider to increase the alsa_periods_in_buffer (now is set to %d) for this interface in the config file. delayp1=%d, delayp2=%d\n",
GSMOPEN_P_LOG, tech_pvt->alsa_periods_in_buffer, (int) delayp1, (int) delayp2);
}
}
memset(sizbuf2, 0, sizeof(sizbuf2));
if (tech_pvt->alsa_play_is_mono) {
res = snd_pcm_writei(tech_pvt->alsap, sizbuf, len / 2);
} else {
int a = 0;
int i = 0;
for (i = 0; i < 8000;) {
sizbuf2[a] = sizbuf[i];
a++;
i++;
sizbuf2[a] = sizbuf[i];
a++;
i--;
sizbuf2[a] = sizbuf[i]; // comment out this line to use only left
a++;
i++;
sizbuf2[a] = sizbuf[i]; // comment out this line to use only left
a++;
i++;
}
res = snd_pcm_writei(tech_pvt->alsap, sizbuf2, len);
}
if (res == -EPIPE) {
DEBUGA_GSMOPEN
("ALSA write EPIPE (XRUN) (gsmopen can't fill the soundcard buffer fast enough). If this happens often (not after silence or after a pause in the speech, that's OK), and appear to damage the sound quality, first check if you have some IRQ problem, maybe sharing the soundcard IRQ with a broken or heavy loaded ethernet or graphic card. Then consider to increase the alsa_periods_in_buffer (now is set to %d) for this interface in the config file. delayp1=%d, delayp2=%d\n",
GSMOPEN_P_LOG, tech_pvt->alsa_periods_in_buffer, (int) delayp1, (int) delayp2);
res = snd_pcm_prepare(tech_pvt->alsap);
if (res) {
ERRORA("audio play prepare failed: %s\n", GSMOPEN_P_LOG, snd_strerror(res));
} else {
if (tech_pvt->alsa_play_is_mono) {
res = snd_pcm_writei(tech_pvt->alsap, sizbuf, len / 2);
} else {
int a = 0;
int i = 0;
for (i = 0; i < 8000;) {
sizbuf2[a] = sizbuf[i];
a++;
i++;
sizbuf2[a] = sizbuf[i];
a++;
i--;
sizbuf2[a] = sizbuf[i];
a++;
i++;
sizbuf2[a] = sizbuf[i];
a++;
i++;
}
res = snd_pcm_writei(tech_pvt->alsap, sizbuf2, len);
}
}
} else {
if (res == -ESTRPIPE) {
ERRORA("You've got some big problems\n", GSMOPEN_P_LOG);
} else if (res == -EAGAIN) {
DEBUGA_GSMOPEN("Momentarily busy\n", GSMOPEN_P_LOG);
res = 0;
} else if (res < 0) {
ERRORA("Error %d on audio write: \"%s\"\n", GSMOPEN_P_LOG, res, snd_strerror(res));
}
}
}
if (tech_pvt->audio_play_reset_period) {
time(&now_timestamp);
if ((now_timestamp - tech_pvt->audio_play_reset_timestamp) > tech_pvt->audio_play_reset_period) {
if (option_debug)
DEBUGA_GSMOPEN("reset audio play\n", GSMOPEN_P_LOG);
res = snd_pcm_wait(tech_pvt->alsap, 1000);
if (res < 0) {
ERRORA("audio play wait failed: %s\n", GSMOPEN_P_LOG, snd_strerror(res));
}
res = snd_pcm_drop(tech_pvt->alsap);
if (res) {
ERRORA("audio play drop failed: %s\n", GSMOPEN_P_LOG, snd_strerror(res));
}
res = snd_pcm_prepare(tech_pvt->alsap);
if (res) {
ERRORA("audio play prepare failed: %s\n", GSMOPEN_P_LOG, snd_strerror(res));
}
res = snd_pcm_wait(tech_pvt->alsap, 1000);
if (res < 0) {
ERRORA("audio play wait failed: %s\n", GSMOPEN_P_LOG, snd_strerror(res));
}
time(&tech_pvt->audio_play_reset_timestamp);
}
}
//res = 0;
//if (res > 0)
//res = 0;
return res;
}
#define AST_FRIENDLY_OFFSET 0
int alsa_read(private_t *tech_pvt, short *data, int datalen)
{
//static struct ast_frame f;
static short __buf[GSMOPEN_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
static short __buf2[(GSMOPEN_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2) * 2];
short *buf;
short *buf2;
static int readpos = 0;
//static int left = GSMOPEN_FRAME_SIZE;
static int left;
snd_pcm_state_t state;
int r = 0;
int off = 0;
int error = 0;
//time_t now_timestamp;
//DEBUGA_GSMOPEN("buf=%p, datalen=%d, left=%d\n", GSMOPEN_P_LOG, (void *)buf, datalen, left);
//memset(&f, 0, sizeof(struct ast_frame)); //giova
if (tech_pvt->no_sound == 1) {
return r;
}
left = datalen;
state = snd_pcm_state(tech_pvt->alsac);
if (state != SND_PCM_STATE_RUNNING) {
DEBUGA_GSMOPEN("ALSA read state is not SND_PCM_STATE_RUNNING\n", GSMOPEN_P_LOG);
if (state != SND_PCM_STATE_PREPARED) {
error = snd_pcm_prepare(tech_pvt->alsac);
if (error) {
ERRORA("snd_pcm_prepare failed, %s\n", GSMOPEN_P_LOG, snd_strerror(error));
return r;
}
DEBUGA_GSMOPEN("prepared!\n", GSMOPEN_P_LOG);
}
gsmopen_sleep(1000);
error = snd_pcm_start(tech_pvt->alsac);
if (error) {
ERRORA("snd_pcm_start failed, %s\n", GSMOPEN_P_LOG, snd_strerror(error));
return r;
}
DEBUGA_GSMOPEN("started!\n", GSMOPEN_P_LOG);
gsmopen_sleep(1000);
}
buf = __buf + AST_FRIENDLY_OFFSET / 2;
buf2 = __buf2 + ((AST_FRIENDLY_OFFSET / 2) * 2);
if (tech_pvt->alsa_capture_is_mono) {
r = snd_pcm_readi(tech_pvt->alsac, buf + readpos, left);
//DEBUGA_GSMOPEN("r=%d, buf=%p, buf+readpos=%p, datalen=%d, left=%d\n", GSMOPEN_P_LOG, r, (void *)buf, (void *)(buf + readpos), datalen, left);
} else {
int a = 0;
int i = 0;
r = snd_pcm_readi(tech_pvt->alsac, buf2 + (readpos * 2), left);
for (i = 0; i < (GSMOPEN_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2) * 2;) {
__buf[a] = (__buf2[i] + __buf2[i + 1]) / 2; //comment out this line to use only left
//__buf[a] = __buf2[i]; // enable this line to use only left
a++;
i++;
i++;
}
}
if (r == -EPIPE) {
DEBUGA_GSMOPEN("ALSA XRUN on read\n", GSMOPEN_P_LOG);
return r;
} else if (r == -ESTRPIPE) {
ERRORA("-ESTRPIPE\n", GSMOPEN_P_LOG);
return r;
} else if (r == -EAGAIN) {
int count = 0;
while (r == -EAGAIN) {
gsmopen_sleep(10000);
DEBUGA_GSMOPEN("%d ALSA read -EAGAIN, the soundcard is not ready to be read by gsmopen\n", GSMOPEN_P_LOG, count);
count++;
if (tech_pvt->alsa_capture_is_mono) {
r = snd_pcm_readi(tech_pvt->alsac, buf + readpos, left);
} else {
int a = 0;
int i = 0;
r = snd_pcm_readi(tech_pvt->alsac, buf2 + (readpos * 2), left);
for (i = 0; i < (GSMOPEN_FRAME_SIZE + AST_FRIENDLY_OFFSET / 2) * 2;) {
__buf[a] = (__buf2[i] + __buf2[i + 1]) / 2;
a++;
i++;
i++;
}
}
}
} else if (r < 0) {
WARNINGA("ALSA Read error: %s\n", GSMOPEN_P_LOG, snd_strerror(r));
} else if (r >= 0) {
//DEBUGA_GSMOPEN("read: r=%d, readpos=%d, left=%d, off=%d\n", GSMOPEN_P_LOG, r, readpos, left, off);
off -= r; //what is the meaning of this? a leftover, probably
}
/* Update positions */
readpos += r;
left -= r;
if (readpos >= GSMOPEN_FRAME_SIZE) {
int i;
/* A real frame */
readpos = 0;
left = GSMOPEN_FRAME_SIZE;
for (i = 0; i < r; i++)
data[i] = buf[i];
}
return r;
}
#endif // GSMOPEN_ALSA
int gsmopen_sendsms(private_t *tech_pvt, char *dest, char *text)
{