ASL USB Audio notes

Having been looking closely at many aspects of audio within the app_rpt code, particularly with regards to ensuring more consistent levels (and no clipping/distortion) for all users, I am noticing some interesting things in the app_rpt code. I thought I would start documenting some things here as I investigate further.

The first thing that should be noted is that pretty much all nodes I’m aware of use C-Media CM1xx ICs. This of course refers to real nodes - not phone or PC apps such as DVSM or iaxRpt. But in the class of real nodes, whether they be repeaters, Pi-hat (SA818) nodes, mobile radio nodes, or radio-less nodes, probably 99% of anything built in the past 10 years is using either a C-Media CM119A, CM108AH, CM108B or CM119B.

The CM1xx A/AH versions replaced the original (no suffix) CM108/119 ICs over 10 years ago, and those then went EOL according to C-Media several years ago to be replaced with the B suffix versions, which have significantly different specs, which no one I know of has yet fully characterized and confirmed through testing. (The A ICs are still available though, which is another story.)

The App_rpt code however essentially treats everything as a (15-year old) CM108/119, with a few twists. The original 108 and 119 were essentially identical, the only major difference (as far as ASL is concerned) being that the 119 has 4 more GPIOs.

The A versions made some minor changes but from what I can tell the specs did not significantly change. The ADC on all 6 variants has an input range of 2.88Vpp. The DAC output ranges vary considerably however, as shown below:

The changes in the B versions were much more significant. The crystal was removed, presumably with the internal PLL extracting 12MHz clock from the USB bus, but I was not able to confirm that with C-Media. The LF response is reduced by about 6dB < 100Hz. The ADC SNR and THD was significantly improved. And the gain settings are quite different:

ADC:
Orig: 0 - 22.5 dB range in 16 steps, with +20dB boost option
A/AH: 0 - 23.9 dB range in 16 steps, with +22.5dB boost option
B: -12 - 23 dB range in 36 steps, with 12 or 22 dB boost option

Which with boost off should translate to:
Orig: 0 - 22.5 dB range in 16 steps
A/AH: 0 - 23.9 dB range in 16 steps
B: 0 - 35 dB range in 36 steps

DAC:
Orig, A/AH: -45 - 0 dB range in 38 steps
B: -37 - 0 dB range in 38 steps

There are discrepancies on A&B datasheets between the gain ranges and steps shown on the block diagram vs. the specs tables. So the only way to confirm the above would be to test on an A & B version and confirm what actual voltages come out of the DAC for a full-scale input at various gain step settings, and similarly what happens with a known voltage on the ADC input with different gain settings.

Based on testing I’ve been doing on some ANR100 radio-less nodes, one with a CM108AH and the other with a CM108B, I notice the B needs significantly higher level settings. I use rxmix of 100 and txmix of 500 on the AH, but need rxmix of 750 and txmix of 800 on the B. (Both with rxboost=off). That’s a huge difference, particularly between 100 to 750 for rxmixset. I’m running about 1.4Vpp into ADC which should only need 6dB of boost to be at the ADC rated input range of 2.88Vpp. The specs above would imply the B has more gain in both directions than the A’s, but my measurements seem to show the opposite. The 108B DAC is rated at 941mVrms out vs. 1.25Vrms for the AH at 10KΩ but that’s only a 2.5dB difference.

A big question is are the B’s suitable for use in nodes and URIs. Their reduced ADC response below 100Hz could be an issue for apps using usbradio to CTCSS decode of lower PL tones, but that doesn’t apply to most small personal nodes or radio-less nodes. There has been speculation that the B’s might not have as good of clock/sample timing stability or temperature range but I’ve seen no confirmation of that. The lower gain of the B’s could be an issue in some apps but most apps don’t need a ton of gain and support for lower gains can be better in some cases. Lastly the B’s are widely available, in current production, and have 10dB better ADC noise specs.

The next variable is ASL itself, which has defines for all these variants, but really doesn’t do much differently between them, and has some clear inconsistencies. It looks like some efforts were made to put in some scaling for CM119B vs. A but the values are the same (1000) and thus no scaling is actually done (see C119B_ADJUSTMENT).

Then there is this bit of code in chan_simpleusb.c where it outputs audio to the USB interface:

				/* Adjust the audio level for CM119 A/B devices */
				if (o->devtype != C108_PRODUCT_ID) {
					register int v;

					sp = (short *) o->simpleusb_write_buf;
					for (i = 0; i < FRAME_SIZE; i++) {
						v = *sp;
						v += v >> 3;	/* add *.125 giving * 1.125 */
						v -= *sp >> 5;	/* subtract *.03125 giving * 1.09375 */
						if (v > 32765.0) {
							v = 32765.0;
						} else if (v < -32765.0) {
							v = -32765.0;
						}
						*sp++ = v;
					}
				}

And this in chan_usbradio.c where it reads USB audio:

/* Decrease the audio level for CM119 A/B devices */
if (o->devtype != C108_PRODUCT_ID) {
	register short *sp = (short *) (o->usbradio_read_buf + o->readpos);
	register float v;
	register int i;

	for (i = 0; i < res / 2; i++) {
		v = ((float) *sp) * 0.800;
		*sp++ = (int) v;
	}
}

And this where it writes USB audio:

/* For the CM108 adjust the audio level */
if (o->devtype != C108_PRODUCT_ID) {
	register short *sp = (short *) o->usbradio_write_buf;
	register float v;
	register int i;

	for (i = 0; i < sizeof(o->usbradio_write_buf) / 2; i++) {
		v = ((float) *sp) * 1.10;
		if (v > 32765.0) {
			v = 32765.0;
		} else if (v < -32765.0) {
			v = -32765.0;
		}
		*sp++ = (int) v;
	}
}

This above 3 code excerpts are all conditioned on != C108_PRODUCT_ID, which will always be true on any node made in at least the past 10 years. This appears to be a major issue that could result in perfectly good incoming IAX audio being digitally clipped before being output to the DAC. Usbradio is scaling all Tx audio going to the DAC by 110%, while at the same time attenuating all incoming audio by 20%, increasing the likelihood of digital clipping on Tx audio, wasting 20% of available dynamic range on incoming audio, and eating up CPU cycles to do floating point scaling on every sample, apparently as a hack to match levels to an IC that has been out of production for over 10 years. Simpleusb does pretty much the same thing but scaling in a more CPU efficient way to 109.375% on Tx audio but then not doing any scaling of Rx audio.

Update: Did some testing today with both simpleusb and usbradio drivers and confirmed these code sections above are completely unnecessary and should be removed asap. At that point there may be some significant work to properly characterize these various ICs and see if there might be a good way to get their gains to be more consistent by adjusting the mixer settings rather then by scaling the incoming and outgoing audio streams. Ideally the rx and tx mix settings could be in dBV instead of arbitrary (unitless) numbers, and ASL would then figure the exact mixer settings required to achieve those actual input and levels on each CM1xxx variant.

1 Like

Thank you.
We observed the inconsistencies but have not deciphered the issues like you.

I have often wondered why the C119 was the only practical way to do ASL?
I realize there are wide ranges of signals, perhaps requiring significant code variations. But as someone recently remarked, is it not possible to use other in/out? The suggestion as I recall was old laptops, etc.

The Raspberry Pi today is so much more powerful than the early machines. Just a thought. Is it possible to offload the processing from the CM119 to the Pi? Then the world is your oyster, as the old saying goes. There are myriad techniques on the Pi. Perhaps, just gives the hooks to the Pi and let others work with developing apps, boards, etc.

ASL3 is so fabulous compared to the first versions I used.

I appreciate all your effort and the team’s work on the fantastic new tool.

The CM1xxx ICs have useful features including an internal mixer and GPIOs and with the cost being only ~$2 there just hasn’t been much reason to support other ICs. The mixer does come in quite handy because you can adjust levels easily with no need to touch any hardware or trim pots. Audio chips/drivers could vary greatly between Pi 0/2/3/4/5/hats/etc., would not likely be of use on x64 platforms, and likely would not include GPIOs or mixers, thereby requiring use of a separate RPi GPIO driver and more inconsistency with x64. Also RPi stopped making sense as a platform years ago when their prices become double that of miniPC options that have more features and are almost as small. Maybe someday RPi prices will come back down to Earth or they will release a “Pi Zero 3” with more than 512MB (?!) of RAM, but until then there are numerous models of miniPC that work much better. So in summary it’s just simpler to plug in a $3 CM1xx fob into an RPi USB port than try to support inconsistent audio/GPIO HW.

Thanks. I appreciate your response.

I agree the fob for straight audio makes sense. I have a handful that I played wit. But the PTT function still requires a hack. That would be beneficial from another route, either a hardware or software solution from the computer / RPi. It could be a Pi Gpio pin ( like the early ASL parallel port) or the passing of a simple handshake code, such as setting one if the Vars.

Just thinking of ways to expand applicability, simply.

Appreciate all your work.

Just opened a bug report on the above mentioned issue - Simpleusb and Usbradio drivers are introducing digital clipping into all Tx audio · Issue #399 · AllStarLink/app_rpt · GitHub

Having been a EE and audio engineer for 30 years I am amazed that these hacks ever made it into the ASL code 10 years ago and that it went unnoticed until now. If anyone has any questions on this LMK.

In the meantime my UCI120 product is moving along well. Just got the first proto boards back and working 2 days ago. See the product page at AllScan - Products - AllScan UCI120 USB Communications Interface and a few quick demo videos: Link

Been looking for this for some time. excellent work.
Would you be making a board only (meaning populated board) option when you make this available?
what about price range?
Maybe a future dual node version?
Mike N3IDS

I have built 6 nodes in the past month and had to disable the Auto Gain Control using alsamixer and then store it using alsactl store. It was constantly changing levels.

I dont know if there is a better way to disable that but its stabilized my nodes.

Hi Mike, yes the UCI120 will be available as the assembled board without the enclosure and with the mic jack, LEDs and volume knob included but not soldered on. Should be ready to ship these in about 2 weeks. Below are some pics of the enclosure, just got the front and back panels in today, and in your case you would not need the enclosure, but the back panel jacks and controls will be populated on the PCB so if you were going to mount inside some other enclosure such as a comms speaker or phone patch I would suggest have the back of the PCB mounted at the back or in such a way to make it easy to access the back of the board.

We are redoing the LEDs to be standard old-school 5mm LEDs that will be on a separate small board, rather than the LED diffusers and SMT LEDs as shown above. So the LEDs will end up looking more like this mockup:

And thus the small LED and mic jack board will be able to easily mount anywhere on any enclosure with just a header extension cable between that and the main PCB.


And to N5ZR, how were you using alsamixer and AGC with ASL? I’ve only used Usbradio and Simpleusb drivers which talk direct to the CM1xx and don’t have anything to do with alsa. Is the AGC function you’re referring to part of Linux Alsa package? Have you tried the Asterisk AGC function?

How did AGC happen in the first place? I’ve never encountered that on any system ever.

Alsa is installed on the appliance. Maybe you don’t build those? Does not negate the fact that its there and not “muted”.

Well it seems to come back(unmute) after changes in radio-tune and simpleusb-tune so my efforts are for not.

Never mind then.

Is there room to squeeze a rasp zero 2 in there? maybe an ethernet adapt… might have to put on an external antenna for wifi
really looks professional!!
I’m like a kid just before christmas.
Mike

If the Pi Alsa driver is interfering with ASLs use of the CM1xx IC I would suggest maybe uninstalling Alsa, or opening a bug report on the app-rpt github page.

You could probably fit a Pi Zero 2 in the enclosure but I would definitely not recommend it for a number reasons: no ventilation, wifi signals would be blocked, you’d have to add notches in the back panel for the power/ethernet/usb cables, a layer of insulation would have to be added to prevent shorting anything on the PCBs, Pi’s have no power switch or easy way to do a controlled shutdown, EMI/RFI could be introduced inside the enclosure, and last but not least I don’t see how a Pi zero 2 with only 512MB RAM can be a reliable long-term ASL3 platform ie. without going into disk swap and trashing the SDCard after not too long (if someone can explain technically how that wouldn’t be an issue I’d like to hear it).
BTW I ordered a miniPC for evaluation yesterday that is only 3" x 3" x 1.75" which should complement the size of the UCI120 very well, and it’s about 50 times more powerful than a Pi Zero - https://www.amazon.com/dp/B0B75PT2RY