gsmopen: continue cleaning from alsa
This commit is contained in:
parent
49a4d2126b
commit
40a1fd8ef0
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue