mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-15 05:08:26 +00:00
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;
|
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)
|
int gsmopen_sendsms(private_t *tech_pvt, char *dest, char *text)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user