Modified: freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c (14660 => 14661)
--- freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c 2009-08-28 12:20:41 UTC (rev 14660)
+++ freeswitch/branches/gmaruzz/mod_celliax/celliax_protocol.c 2009-08-28 12:25:39 UTC (rev 14661)
@@ -4447,6 +4447,7 @@
memset(sizbuf2, 0, sizeof(sizbuf2));
if (tech_pvt->alsa_play_is_mono) {
+ ERRORA("data=%p, datalen=%d, sizbuf=%p, len/2=%d\n", SKYPIAX_P_LOG, (void *)data, datalen, (void *)sizbuf, len/2);
res = snd_pcm_writei(tech_pvt->alsap, sizbuf, len / 2);
} else {
int a = 0;
@@ -4577,4 +4578,216 @@
return 0;
}
+/*! \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;
+ snd_pcm_sframes_t delayp2;
+ //ERRORA("data=%p, datalen=%d\n", SKYPIAX_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", SKYPIAX_P_LOG);
+ res = -1;
+ } else {
+ memcpy(sizbuf + sizpos, data, 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_SKYPE
+ ("You've got an ALSA write XRUN in the past (celliax 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",
+ SKYPIAX_P_LOG, tech_pvt->alsa_periods_in_buffer);
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ ERRORA("audio play prepare failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ } else {
+ res = snd_pcm_format_set_silence(celliax_format, silencebuf, len / 2);
+ if (res < 0) {
+ DEBUGA_SKYPE("Silence error %s\n", SKYPIAX_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_SKYPE("Write returned a different quantity: %d\n", SKYPIAX_P_LOG, res);
+ res = -1;
+ } else if (res < 0) {
+ DEBUGA_SKYPE("Write error %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ res = -1;
+ }
+ }
+ }
+
+ }
+
+ res = snd_pcm_delay(tech_pvt->alsap, &delayp1);
+ if (res < 0) {
+ DEBUGA_SKYPE("Error %d on snd_pcm_delay: \"%s\"\n", SKYPIAX_P_LOG, res,
+ snd_strerror(res));
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ DEBUGA_SKYPE("snd_pcm_prepare failed: '%s'\n", SKYPIAX_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_SKYPE("Error %d on snd_pcm_avail_update: \"%s\"\n", SKYPIAX_P_LOG,
+ (int) delayp2, snd_strerror(delayp2));
+
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ DEBUGA_SKYPE("snd_pcm_prepare failed: '%s'\n", SKYPIAX_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_SKYPE
+ ("snd_pcm_prepare failed while trying to prevent an ALSA write XRUN: %s, delayp1=%d, delayp2=%d\n",
+ SKYPIAX_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(celliax_format, silencebuf, len / 2);
+ if (res < 0) {
+ DEBUGA_SKYPE("Silence error %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ res = -1;
+ }
+ res = snd_pcm_writei(tech_pvt->alsap, silencebuf, len / 2);
+ if (res < 0) {
+ DEBUGA_SKYPE("Write error %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ res = -1;
+ } else if (res != len / 2) {
+ DEBUGA_SKYPE("Write returned a different quantity: %d\n", SKYPIAX_P_LOG, res);
+ res = -1;
+ }
+ }
+
+ DEBUGA_SKYPE
+ ("PREVENTING an ALSA write XRUN (celliax 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",
+ SKYPIAX_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_SKYPE
+ ("ALSA write EPIPE (XRUN) (celliax 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",
+ SKYPIAX_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", SKYPIAX_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", SKYPIAX_P_LOG);
+ } else if (res == -EAGAIN) {
+ res = 0;
+ } else if (res < 0) {
+ ERRORA("Error %d on audio write: \"%s\"\n", SKYPIAX_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_SKYPE("reset audio play\n", SKYPIAX_P_LOG);
+ res = snd_pcm_wait(tech_pvt->alsap, 1000);
+ if (res < 0) {
+ ERRORA("audio play wait failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ res = snd_pcm_drop(tech_pvt->alsap);
+ if (res) {
+ ERRORA("audio play drop failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ res = snd_pcm_prepare(tech_pvt->alsap);
+ if (res) {
+ ERRORA("audio play prepare failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ res = snd_pcm_wait(tech_pvt->alsap, 1000);
+ if (res < 0) {
+ ERRORA("audio play wait failed: %s\n", SKYPIAX_P_LOG, snd_strerror(res));
+ }
+ time(&tech_pvt->audio_play_reset_timestamp);
+ }
+ }
+ res = 0;
+ if (res > 0)
+ res = 0;
+ return res;
+}
+
+
Modified: freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c (14660 => 14661)
--- freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c 2009-08-28 12:20:41 UTC (rev 14660)
+++ freeswitch/branches/gmaruzz/mod_celliax/mod_celliax.c 2009-08-28 12:25:39 UTC (rev 14661)
@@ -649,7 +649,6 @@
-usleep(2000);
int samples;
if ((samples = snd_pcm_readi(tech_pvt->alsac, tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_packet)) > 0) {
@@ -661,10 +660,11 @@
*frame = &tech_pvt->read_frame;
//status = SWITCH_STATUS_SUCCESS;
+ }
switch_set_flag(tech_pvt, TFLAG_VOICE);
- }
+usleep(17000);
@@ -704,7 +704,7 @@
switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
}
#endif
- WARNINGA("HERE\n", SKYPIAX_P_LOG);
+ //WARNINGA("HERE\n", SKYPIAX_P_LOG);
return SWITCH_STATUS_SUCCESS;
}
@@ -753,9 +753,11 @@
sent = frame->datalen;
- ERRORA("PLAY \n", SKYPIAX_P_LOG);
- snd_pcm_writei(tech_pvt->alsap, (short *) frame->data, (int) (frame->datalen / 2));
+ //ERRORA("PLAY \n", SKYPIAX_P_LOG);
+ //snd_pcm_writei(tech_pvt->alsap, (short *) frame->data, (int) (frame->datalen / 2));
+ alsa_write(tech_pvt, frame->data, (int) (frame->datalen));
+
#ifdef NOTDEF //FIXME
#ifdef WIN32
switch_file_write(tech_pvt->audioskypepipe[1], frame->data, &sent);
@@ -1382,8 +1384,8 @@
globals.SKYPIAX_INTERFACES[interface_id].alsa_periods_in_buffer = 4;
globals.SKYPIAX_INTERFACES[interface_id].celliax_sound_rate = 8000;
- switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].alsacname , "plughw:0");
- switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].alsapname , "plughw:0");
+ switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].alsacname , "plughw:1");
+ switch_set_string(globals.SKYPIAX_INTERFACES[interface_id].alsapname , "plughw:1");