[svn-commits] dcb: trunk r451 - in /trunk: chan_mobile.c configs/mobile.conf.sample

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sun Sep 23 03:28:41 CDT 2007


Author: dcb
Date: Sun Sep 23 03:28:40 2007
New Revision: 451

URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=451
Log:
* Added support for detecting misalined sco audio data from the bluetooth adapter.
  See alignmentdetection=yes in configs/mobile.conf.sample.

Modified:
    trunk/chan_mobile.c
    trunk/configs/mobile.conf.sample

Modified: trunk/chan_mobile.c
URL: http://svn.digium.com/view/asterisk-addons/trunk/chan_mobile.c?view=diff&rev=451&r1=450&r2=451
==============================================================================
--- trunk/chan_mobile.c (original)
+++ trunk/chan_mobile.c Sun Sep 23 03:28:40 2007
@@ -119,6 +119,7 @@
 	char id[31];					/* the 'name' from mobile.conf */
 	bdaddr_t addr;					/* adddress of adapter */
 	unsigned int inuse:1;				/* are we in use ? */
+	unsigned int alignment_detection:1;		/* do alignment detection on this adpater? */
 	int sco_socket;
 	AST_LIST_ENTRY(adapter_pvt) entry;
 };
@@ -157,6 +158,10 @@
 	unsigned int no_callsetup:1;
 	unsigned int has_sms:1;
 	unsigned int sent_answer:1;
+	unsigned int do_alignment_detection:1;
+	unsigned int alignment_detection_triggered:1;
+	short alignment_samples[4];
+	int alignment_count;
 	char sms_txt[160];
 	struct ast_dsp *dsp;
 	struct ast_frame *dsp_fr;
@@ -219,6 +224,8 @@
 static int mbl_write(struct ast_channel *ast, struct ast_frame *frame);
 static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int mbl_devicestate(void *data);
+
+static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen);
 
 static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel);
 static int rfcomm_write(struct mbl_pvt *pvt, char *buf);
@@ -491,6 +498,12 @@
 	pvt->io_save_len = 0;
 	pvt->sent_answer = 0;
 	pvt->skip_frames = 0;
+	pvt->alignment_count = 0;
+	pvt->alignment_detection_triggered = 0;
+	if (pvt->adapter->alignment_detection)
+		pvt->do_alignment_detection = 1;
+	else
+		pvt->do_alignment_detection = 0;
 		
 	chn = ast_channel_alloc(1, state, cid_num, pvt->id, 0, 0, pvt->context, 0, "Mobile/%s-%04lx", pvt->id, ast_random() & 0xffff);
 	if (chn) {
@@ -777,6 +790,8 @@
 		memcpy(pvt->io_save_buf + pvt->io_save_len, frame->data, io_need);
 		sco_write(pvt->sco_socket, pvt->io_save_buf, DEVICE_FRAME_SIZE);
 		if ((r = sco_read(pvt->sco_socket, buf, DEVICE_FRAME_SIZE))) {
+			if (pvt->do_alignment_detection)
+				do_alignment_detection(pvt, buf, r);
 			sco_write(pvt->io_pipe[1], buf, r);
 		}
 	}
@@ -787,6 +802,8 @@
 	for (i=0; i<num_frames; i++) {
 		sco_write(pvt->sco_socket, pfr, DEVICE_FRAME_SIZE);
 		if ((r = sco_read(pvt->sco_socket, buf, DEVICE_FRAME_SIZE))) {
+			if (pvt->do_alignment_detection)
+				do_alignment_detection(pvt, buf, r);
 			sco_write(pvt->io_pipe[1], buf, r);
 		}
 		pfr += DEVICE_FRAME_SIZE;
@@ -839,6 +856,72 @@
 	}
 
 	return res;
+
+}
+
+/*
+
+	Callback helpers
+
+*/
+
+/*
+
+	do_alignment_detection()
+
+	This routine attempts to detect where we get misaligned sco audio data from the bluetooth adaptor.
+
+	Its enabled by alignmentdetect=yes under the adapter entry in mobile.conf
+
+	Some adapters suffer a problem where occasionally they will byte shift the audio stream one byte to the right.
+	The result is static or white noise on the inbound (from the adapter) leg of the call.
+	This is characterised by a sudden jump in magnitude of the value of the 16 bit samples.
+
+	Here we look at the first 4 48 byte frames. We average the absolute values of each sample in the frame,
+	then average the sum of the averages of frames 1, 2, and 3.
+	Frame zero is usually zero.
+	If the end result > 100, and it usually is if we have the problem, set a flag and compensate by shifting the bytes
+	for each subsequent frame during the call.
+
+	If the result is <= 100 then clear the flag so we dont come back in here...
+
+	This seems to work OK....
+
+*/
+
+static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen)
+{
+
+	int i;
+	short a, *s;
+	char *p;
+
+	if (pvt->alignment_detection_triggered) {
+		for (i=buflen, p=buf+buflen-1; i>0; i--, p--)
+			*p = *(p-1);
+		*(p+1) = 0;
+		return;
+	}
+
+	if (pvt->alignment_count < 4) {
+		s = (short *)buf;
+		for (i=0, a=0; i<buflen/2; i++) {
+			a += *s++;
+			a /= i+1;
+		}
+		pvt->alignment_samples[pvt->alignment_count++] = a;
+		return;
+	}
+
+	ast_debug(1, "Alignment Detection result is [%-d %-d %-d %-d]\n", pvt->alignment_samples[0], pvt->alignment_samples[1], pvt->alignment_samples[2], pvt->alignment_samples[3]);
+
+	a = abs(pvt->alignment_samples[1]) + abs(pvt->alignment_samples[2]) + abs(pvt->alignment_samples[3]);
+	a /= 3;
+	if (a > 100) {
+		pvt->alignment_detection_triggered = 1;
+		ast_debug(1, "Alignment Detection Triggered.\n");
+	} else
+		pvt->do_alignment_detection = 0;
 
 }
 
@@ -1752,7 +1835,7 @@
 	struct ast_config *cfg = NULL;
 	char *cat = NULL;
 	struct ast_variable *var;
-	const char *id, *address, *useadapter, *port, *context, *type, *skip, *group, *master, *nocallsetup;
+	const char *id, *address, *useadapter, *port, *context, *type, *skip, *group, *master, *nocallsetup, *aligndetect;
 	struct mbl_pvt *pvt;
 	struct adapter_pvt *adapter;
 	uint16_t vs;
@@ -1776,12 +1859,18 @@
 			id = ast_variable_retrieve(cfg, cat, "id");
 			address = ast_variable_retrieve(cfg, cat, "address");
 			master = ast_variable_retrieve(cfg, cat, "forcemaster");
+			aligndetect = ast_variable_retrieve(cfg, cat, "alignmentdetection");
 			ast_debug(1, "Loading adapter %s %s.\n", id, address);
 			if (!ast_strlen_zero(id) && !ast_strlen_zero(address)) {
 				if ((adapter = ast_malloc(sizeof(struct adapter_pvt)))) {
 					ast_copy_string(adapter->id, id, sizeof(adapter->id));
 					str2ba(address, &adapter->addr);
 					adapter->inuse = 0;
+					adapter->alignment_detection = 0;
+					if (!ast_strlen_zero(aligndetect)) {
+						if (*aligndetect == 'Y' || *aligndetect == 'y')
+							adapter->alignment_detection = 1;
+					}
 					adapter->dev_id = hci_devid(address);
 					adapter->hci_socket = hci_open_dev(adapter->dev_id);
 					if (adapter->dev_id < 0 || adapter->hci_socket < 0) {

Modified: trunk/configs/mobile.conf.sample
URL: http://svn.digium.com/view/asterisk-addons/trunk/configs/mobile.conf.sample?view=diff&rev=451&r1=450&r2=451
==============================================================================
--- trunk/configs/mobile.conf.sample (original)
+++ trunk/configs/mobile.conf.sample Sun Sep 23 03:28:40 2007
@@ -15,6 +15,9 @@
 id=blue
 address=00:09:DD:60:01:A3
 ;forcemaster=yes	; attempt to force adapter into master mode. default is no.
+;alignmentdetection=yes ; enable this if you sometimes get 'white noise' on asterisk side of the call
+			; its a bug in the bluetooth adapter firmware, enabling this will compensate for it.
+			; default is no.
 
 [adapter]
 id=dlink




More information about the svn-commits mailing list