Transcoding Explained


Put a DMR operator and a D-STAR operator on the same reflector and, left to themselves, they'll hear each other as noise. Their radios digitize speech with different, mutually unintelligible vocoders. To let them talk, something in the middle has to take the audio apart and rebuild it in the other mode's language. That's transcoding — and thanks to the licensing story behind AMBE, it's the reason a lot of reflectors have little USB sticks plugged into them. (If you haven't read AMBE and Codec2 yet, start there — it's the why behind everything below.)

These are notes on how an XLX or URF reflector may be transcoded: what the hardware actually buys, and why the two architectures answer that question in opposite ways.

Why you can't just forward the bits

The tempting shortcut is to imagine a gateway that simply relabels the packets — take a DMR stream, stamp it “D-STAR,” and send it on. It cannot work. The bits coming off a DMR radio are AMBE+2 parameters; a D-STAR radio expects the older AMBE generation; an M17 radio expects Codec2. These aren't dialects of one language, they're separate codebooks. Even the two AMBE modes aren't bit-compatible with each other — they're different vocoder generations describing the vocal tract in incompatible ways. Feed one mode's compressed stream into another mode's decoder and you get gibberish. The only thing every mode agrees on is uncompressed audio.

What transcoding actually does

So transcoding takes the long way around, on purpose. It fully decodes the incoming stream all the way back to plain digital audio — ordinary PCM samples, the same uncompressed representation your sound card uses — and then re-encodes that audio into the outgoing mode's vocoder. Uncompressed audio is the neutral hub language: every mode can be reached from it, and every mode can be decoded down to it. Decode to PCM, re-encode to the target. Do it fast enough that nobody notices the round trip, and the DMR user and the D-STAR user never know there was a translator standing between them.

DMR in AMBE+2 decode PCM audio the neutral hub encode D-STAR out AMBE …and the same hub also reaches M17, YSF, P25, NXDN, analog
Never a direct bit-swap: decode all the way to PCM, then re-encode for whoever's listening.

Where the hardware comes in

Here the AMBE licensing wall from the previous page bites. Decoding or encoding AMBE means using DVSI's vocoder, and for most of the last decade that has meant the chip — a dongle such as the ThumbDV or the DVstick 30, built on the single-channel AMBE3000, or the DVstick 33, built on the three-channel AMBE3003. Codec2, being open, needs no hardware at all: the M17 and analog sides run purely in software. So the shape of a bridge depends on what it connects. A DMR-to-M17 bridge is one AMBE decode plus one software Codec2 encode; a DMR-to-D-STAR bridge is an AMBE decode and an AMBE re-encode, both riding on the chip.

That was the whole story for years. It isn't quite the story now — software has taken back some of this ground, and the section further down says exactly how much. But the hardware path remains the default, and it's what nearly every transcoding reflector in the hobby is running today.

Where it runs

Transcoding tends to live in one of two homes. On the reflector: a multimode server such as urfd or xlxd can host a transcoder that gives every connected mode a common meeting point — decode everyone down to PCM, re-encode for each listener — so a call arriving on one mode goes back out correctly shaped on all the others. On a bridge: the DVSwitch suite — Analog_Bridge and MMDVM_Bridge, fed by AMBEserver talking to the dongle — stitches one mode to another between otherwise separate systems. Same principle either way; the difference is whether the translator sits at a hub everyone joins or on a link between two networks.

The transcoder doesn't have to live on the same machine as the reflector. XLX's transcoder daemon takes an address in its configuration, and 127.0.0.1 is only the co-located case — point it at another host and the two talk over UDP ports 10100 to 10199. That is what makes a cloud-hosted reflector with no USB port workable at all: the reflector runs where the bandwidth is, and the dongles hang off a small machine somewhere with a physical port.

Two ways to build a transcoder

Reflector-side transcoding then splits again, and this is the part that trips people up when they go shopping for dongles. XLX and URF are close relatives — urfd describes itself as a superset of XLX, with M17 added — but their transcoders work on opposite principles, and the difference decides how much hardware is worth owning.

XLX pools its transcoder. The daemon is ambed, and it holds a set of channels. When a stream needs converting it borrows a free channel and hands it back when the transmission ends. Nothing is reserved in advance. What the hardware buys you is simultaneous conversations, and they can happen anywhere on the reflector.

URF dedicates its transcoder. The daemon is tcd, and the transcoded modules are named in the config file and read at startup. Each one gets its own encoding and decoding instance on its own thread, holding its vocoder resources for the life of the process. What the hardware buys you is modules — and never more than three.

The practical difference shows up on a quiet afternoon. On an XLX reflector, capacity follows the traffic: if the only cross-mode QSO of the hour happens on module Q, it gets the transcoder. On a URF reflector, the three transcoded modules hold their resources whether anyone is using them or not, and a conversation on a fourth module gets nothing no matter how idle the hardware is.

A channel is not a module

This is the single most useful distinction on the page, and almost every confusion about sizing a transcoder comes from collapsing the two.

A module is a room — a place on the reflector where people meet. A channel is a conversation being converted right now. Idle rooms cost nothing on XLX; live conversions cost a channel each.

So a small XLX reflector can be in this position: every module transcoded, one conversation at a time. With two DVstick 30s you have two channels — one in each direction — and every module on the reflector is eligible to use them. If two cross-mode QSOs start at once, the first gets converted and the second doesn't. Nothing is wrong with the configuration; you've simply run out of channels, not out of modules.

URF inverts it. There, modules are the scarce thing and channels are spent on your behalf: each transcoded module permanently consumes one channel on each of the two devices, so six channels is exactly three modules and there is no way to trade an idle module's channels for a busy one's.

XLX (xlxd + ambed)URF (urfd + tcd)
What hardware buyssimultaneous conversationstranscoded modules
What runs out firstchannelsmodules
Modules that can transcodeevery module the build hasthree, named in advance
Decidedper transmissionat startup
Idle capacitygoes wherever traffic issits unused on quiet modules
More hardwarealways buys more conversationsbuys nothing past three modules

The number that causes the most trouble is three. It is a URF number. It has nothing to do with XLX, and no amount of hardware raises it on URF — a point worth holding onto if you read a URF write-up and then go shopping for an XLX reflector, or the reverse.

How many modules can XLX transcode?

The short answer: all of them. One transcoder serves the whole reflector, and a module costs nothing when it isn't converting. The ceiling is simply how many modules the reflector has — a compile-time setting, with a maximum of twenty-six.

Two details are worth knowing before you take “twenty-six” as read. The first is that the module count itself is a build choice: the original xlxd ships configured for ten modules, A through J, with the A–Z line present but commented out. A reflector offering the full alphabet was compiled that way deliberately.

The second is that the two common xlxd codebases differ here. On the original xlxd there is no per-module transcode setting at all — the concept doesn't exist, every module is eligible, and there is nothing to configure. The reworked xlxd adds one: a list of transcoded modules fixed at build time, which defaults to the whole alphabet but can be narrowed. A module left out of that list never contacts the transcoder. So if you run the reworked build and find some modules quietly not converting, that list is the first thing to check — and changing it means rebuilding, not editing a config file.

What the dongles actually buy

Here the marketing and the software part company, and it is worth being precise. A channel in ambed is a one-way pipe with a fixed input codec and output codec. Two channels therefore means one conversation in both directions — one D-STAR→DMR and one DMR→D-STAR, running at the same time — not two conversations. A second transmission in the same direction finds nothing free and passes through untranscoded.

Hardware (XLX / ambed)D-STAR→DMRDMR→D-STARTotal channels
1 × DVstick 300 — unusable alone
2 × DVstick 30112
1 × DVstick 33112
1 × 33 + 1 × 30224
2 × DVstick 33336
USB-30126612

Two rows in that table surprise people. A single AMBE3000 stick is useless on its own — ambed builds channels from opposite-codec pairs, so one stick never gets a partner. (Pair it with a DVstick 33 rather than another 30 and you get four channels, which is a perfectly good way to grow.) And a single DVstick 33 yields two channels, not three, even though the AMBE3003 chip genuinely has three. On a lone stick, ambed pins chip channel 0 to AMBE (D-STAR) and channel 1 to AMBE+2 (DMR and Fusion), builds its two channels from that pair, and leaves channel 2 configured for nothing at all — the source comment reads PKT_CHANNEL2 = UNUSED or HYBRID. Add a second device and that stranded channel finds a partner, which is why a pair of 33s gives six rather than four, and why the documentation says to use AMBE3000s in pairs. Both statements you'll read are true at their own layer: DVSI's chip does have three full-duplex channels, and ambed uses two of them unless you pair the device.

One practical note that costs people afternoons: don't put the dongles behind a USB hub. ambed's own documentation warns that hubs make behaviour unreliable, and it identifies devices by their USB descriptor string, so anything that muddies enumeration is worth avoiding.

“Fully transcoded” means coverage, not capacity

This is the place to unpack a phrase you'll meet constantly: a reflector advertising itself as “fully transcoded.” It is a claim about coverage, not capacity. It means the transcoder is attached and every module can convert between the supported modes — as opposed to a reflector with no transcoder, where users sharing a module are silently sorted into groups by codec and only ever hear their own kind. What it does not tell you is how many conversations can be converted at once. A reflector running a single DVstick 33 and one running a twelve-channel USB-3012 are both “fully transcoded,” and one of them handles six times the simultaneous cross-mode traffic. The phrase isn't dishonest — it just answers a different question from the one most people think they're asking, and the number that would answer theirs is almost never published.

How URF sizes it

URF's arithmetic is different again, because tcd insists on exactly two devices — one bound to D-STAR, the other to DMR and Fusion — and refuses to start otherwise. A transcoded module then consumes one channel on each. Not one channel to encode and another to decode, as it's often described: each channel is full-duplex and does both directions for its own codec family. One channel per codec family, two families, two channels per module.

Hardware (URF / tcd)Transcoded modulesNotes
2 × DVstick 301AMBE3000 devices are capped at a single module
2 × DVstick 333the ceiling
Larger devices3surplus channels go unused
One device, or three or moretcd will not start

The three-module limit is worth dwelling on, because the reason is more interesting than “somebody chose three.” A module's position in the configured list becomes its hardware channel number — first module to channel 0, second to channel 1, third to channel 2, on both devices at once. A three-channel chip therefore has room for exactly three modules, and the internal queue is sized to match. That is also why the limit tightens with smaller hardware: a pair of single-channel AMBE3000s leaves room for one module, not three. Buying a bigger dongle does not raise the ceiling, because tcd doesn't recognise the larger devices at all. Buying a third dongle stops the transcoder from starting.

Because that list is read at startup, changing which modules are transcoded means restarting the reflector — there is no way to move a transcoded module while it's running.

There is one exception to the two-device rule, and it is the most useful thing in this section for anyone building on a Raspberry Pi. Built with its software AMBE+2 option, tcd handles DMR and Fusion in software and needs only one DVSI device, for D-STAR. That halves the dongle budget. It does not raise the three-module ceiling — nothing does.

Which module do your users land on?

Choosing which modules to transcode only matters if your users can actually reach them, and on a URF reflector that varies by mode in a way worth understanding before you pick.

Most modes let the operator choose. D-STAR carries the module letter in the linking target. DMR uses the familiar private-call convention, 4001 for module A, 4002 for B, and so on up the alphabet. System Fusion is the neat one: a URF reflector acts as its own YSF master, presenting all twenty-six modules as rooms, so a Fusion user points a hotspot at the reflector once and then changes module from the radio by changing DG-ID — no reconnecting, no reconfiguring. Connect first, then steer with the DG-ID knob.

NXDN and P25 have no equivalent. Neither protocol carries anything a reflector could read as a module, so those users cannot choose at all. Instead the sysop chooses once, in the reflector's configuration, with a setting called AutoLinkModule — one module for NXDN, one for P25. Every NXDN user who connects lands on the NXDN module. Every P25 user lands on the P25 module. Neither can move, ever, and no amount of fiddling at the radio changes it.

It's worth being precise about why, because the obvious explanation is wrong. The radios are not the problem: NXDN transmits a RAN and P25 transmits a NAC, small access codes that ride in every frame and would serve perfectly well as module selectors — RAN has 64 values, NAC has 4096, and twenty-six modules fit comfortably in either. Nor is the reflector the problem. The gap is in the middle. Fusion works because MMDVM includes a gateway that reads DG-ID and routes on it, already installed on essentially every hotspot in service. For NXDN and P25 no such routing was ever written, so the codes go out over the air and nothing downstream does anything with them.

Which raises the obvious question: could it be built? Yes, and the design is almost embarrassingly simple. Assign a code to each module — module A is RAN 1 and NAC 0x001, module Z is RAN 26 and NAC 0x01A, one rule serving both modes — then have the reflector read the code off the incoming frame and route accordingly. That is very nearly the same trick Fusion already relies on, and the reflector end of it would be a small piece of work.

The obstacle isn't the reflector. It's that the code has to be read somewhere in the middle, and today nothing there is listening. Making it work would mean changing software on both ends — the reflector and the gateway on every hotspot that wanted to use it. That means a forked gateway build, maintained indefinitely, distributed to users, and working with exactly one reflector on earth until somebody else adopted the same convention. For a mode with a handful of active operators, that is an enormous amount of ongoing effort chasing a very small audience.

So the honest answer is that nobody wrote it because the arithmetic never worked, not because it's hard. The coding is modest; the maintenance and adoption are not. MMDVM is volunteer software, effort follows use, and ham NXDN and P25 activity is thin next to Fusion's enormous installed base. This particular itch has never been scratched hard enough, by enough people, to justify the upkeep.

There is a middle path, for anyone who wants to try. Both modes already address a numeric talkgroup, and typing a talkgroup is something their users already do — so mapping a block of talkgroup numbers to modules would achieve the same end using addressing that exists today, needing changes only at the reflector. Less elegant than borrowing RAN and NAC, considerably more likely to actually get used.

The practical consequence for anyone planning transcoded modules: point AutoLinkModule at a module you are actually transcoding. Bind NXDN or P25 to a module outside the transcoded set and those operators are marooned — audible only to others using their own vocoder, unable to move, and with nothing anywhere reporting a fault.

What still needs hardware

The old rule of thumb — any AMBE mode needs the chip — has quietly stopped being true, and the exception is narrower than most people expect.

Vocoder familyModesSoftware?
Codec2M17Yes — open source, no channel cost
AMBE+2DMR, Fusion, NXDNYes — via the MD-380 firmware vocoder
IMBEP25Yes — open implementation
AMBED-STARNo, in practice

The AMBE+2 software route is an unusual piece of engineering: the vocoder is lifted out of the firmware of a TYT MD-380 handheld and run under emulation. Two forms of it circulate, and conflating them causes a lot of confusion. The library that transcoders link against runs the firmware natively and therefore needs an ARM host — a Raspberry Pi 2, 3 or 4. The standalone emulator service, by contrast, emulates the ARM instructions and runs happily on an ordinary x86 server. Same firmware, two delivery mechanisms, and only one of them cares what processor you have.

That distinction has a direct consequence for URF: it is the ARM-linked library that lets tcd drop to a single dongle. Build it on an x86 host and you are back to two devices and full hardware vocoding.

D-STAR is the holdout, and the reason is documentation rather than law: the D-STAR AMBE patents expired in 2017, but the codec's coefficients were never published the way the TIA specifications for DMR were. Open implementations exist and decode intelligibly, but they still sound rougher than the chip. So a transcoder that includes D-STAR needs at least one dongle, and one that leaves D-STAR out can run with none at all — which is exactly why some builders now run a single dongle for the D-STAR side and let software handle everything else.

Choosing hardware

DVSI's ham-relevant devices form a short ladder: one channel (the ThumbDV and DVstick 30, on the AMBE3000), three channels (the DVstick 33, on the AMBE3003), and twelve (the USB-3012). There is no AMBE3006 chip and nothing between three and twelve in the chip family — a point of confusion worth clearing up, because the USB-3012 is a board carrying several chips, not a twelve-channel part. Transcoder software also recognises device types that were never DVSI products, which is why you'll see six-channel entries in older documentation.

Which rung is worth buying depends entirely on the architecture, not the budget. On an XLX reflector a twelve-channel device means twelve simultaneous conversations anywhere on the reflector, and every channel you add gets used. On a URF reflector the same device buys nothing beyond what two DVstick 33s already deliver — and in fact buys nothing at all, since tcd doesn't recognise it.

So the shortest useful summary: on XLX, buy for how busy you expect to be. On URF, buy two DVstick 33s and stop — or one, plus an ARM host, if you are willing to let software handle everything but D-STAR.

Where the sources disagree

Three contradictions are easy to trip over if you go checking these numbers, so they're worth naming rather than quietly picking a side.

The one honest cost

Transcoding is not free of consequence: every decode-and-re-encode is a fresh lossy pass through a vocoder, so a heavily transcoded path sounds slightly rougher than a native one. That's the price of admission for letting incompatible modes share a conversation, and for nearly everyone it's a bargain — a touch of vocoder texture in exchange for a DMR handheld and a D-STAR handheld and an M17 radio all sitting in the same net.

There is a quieter cost too, and it catches sysops rather than users. When a transcoder is busy, or a module isn't one of the transcoded ones, the QSO doesn't fail — it simply doesn't cross modes. Everyone using the speaker's own vocoder hears them perfectly. Everyone else gets a transmission that keys their radio up and delivers nothing: squelch opens, no audio, and no indication why.

It is worth knowing what does and doesn't get recorded. When ambed has no free channel the reflector does print a line about it — but as ordinary output rather than a flagged error, so it is easy to miss unless you go looking. A URF module that simply isn't in the transcoded set produces nothing at all: no message, no counter, no warning. Either way, the report that eventually reaches you is “the reflector was broken this afternoon.” Publishing which modules are transcoded, and roughly how many conversations the hardware can convert at once, heads off most of it.

The big idea

Transcoding never translates compressed bits directly. It decodes all the way down to plain audio — the one language every mode shares — then re-encodes for the destination. Because AMBE lived behind a licensed chip, that step has traditionally needed a hardware dongle; today only D-STAR genuinely still does. And how much hardware is worth owning is decided not by the size of your reflector but by which transcoder it runs: XLX is one transcoder that every module shares, so hardware buys simultaneous conversations. URF is three modules that own their channels outright, so hardware buys modules — and never more than three.


A noncommercial hobby reference compiled by N6JET, gathered from public sources and shared freely for anyone interested in amateur digital voice. · Version 1.4 · September 2026