nrf5340 stereo output using external codec on SDK 2.6.1

I am trying to make my gateway send stereo data to the headset where it will be played on an external codec. I want this to be a single stereo stream.

I had this working in SDK 2.5.1 but can't seem to get it working with SDK 2.6.1.

The gateway is an unmodified nrf5340 audio DK using the standard board files.

The headset is also an nrf5430 audio DK with an external codec wired up. It uses a Zephyr board file to keep the codec interface line high (codec LED is orange). The headset code does not use the cirrus_cs47l63 driver (#def'd out with CONFIG_HW_CODEC_CIRRUS_LOGIC), my external codec is being configured externally.

I've added STEREO_CIS_HEADSET to my KConfig and set it in prj.conf along with:

CONFIG_STEREO_CIS_HEADSET=y
CONFIG_STREAM_BIDIRECTIONAL=y
CONFIG_TRANSPORT_CIS=y
CONFIG_AUDIO_SOURCE_I2S=y

In unicast_server\Kconfig.defaults, I modified LC3_DEC_CHAN_MAX:

config LC3_DEC_CHAN_MAX
    default 2 if STEREO_CIS_HEADSET
    default 1


In audio_system.c, audio_headset_configure, I added

#endif /* (CONFIG_STREAM_BIDIRECTIONAL) */

	if (IS_ENABLED(CONFIG_STEREO_CIS_HEADSET)) {
		sw_codec_cfg.decoder.num_ch = 2;
		sw_codec_cfg.decoder.channel_mode = SW_CODEC_STEREO;
	} else {
		sw_codec_cfg.decoder.num_ch = 1;
		sw_codec_cfg.decoder.channel_mode = SW_CODEC_MONO;
	}

In bt_le_audio_tx.c, bt_le_audio_tx_send, I modified

	if (streams_to_tx > SRC_STREAM_COUNT) {
		return -ENOMEM;
	}
	if (IS_ENABLED(CONFIG_STEREO_CIS_HEADSET)) {
		data_size_pr_stream = enc_audio.size;
	} else {
		if ((enc_audio.num_ch == 1) || (enc_audio.num_ch == streams_to_tx)) {
			data_size_pr_stream = enc_audio.size / enc_audio.num_ch;
		} else {
			LOG_ERR("Num encoded channels must be 1 or equal to num streams");
			return -EINVAL;
		}
	}

which led to runtime errors in the gateway about "The encoded data size does not match the SDU size"
where data_size_pr_stream was 120, LE_AUDIO_SDU_SIZE_OCTETS(bitrate) was 60, and bitrate was 48000.

I commended out the error, further down in the same function:

//        if (data_size_pr_stream != LE_AUDIO_SDU_SIZE_OCTETS(bitrate)) {
//            LOG_ERR("The encoded data size does not match the SDU size");
//            return -EINVAL;
//        }


In unicast_client.c, at the top, I added

static struct bt_audio_codec_qos lc3_preset_sink_stereo_qos = BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(
	LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_BT_AUDIO_BITRATE_UNICAST_SINK) * 2,
	CONFIG_BT_AUDIO_RETRANSMITS, CONFIG_BT_AUDIO_MAX_TRANSPORT_LATENCY_MS,
	CONFIG_BT_AUDIO_PRESENTATION_DELAY_US);

and then later in the same file, in unicast_client_enable I added the pointer to lc3_preset_sink_stereo_qos:

		if ((i % 2) == 0) {
			if (IS_ENABLED(CONFIG_STEREO_CIS_HEADSET)) {
				group_stream_params[i].qos = &lc3_preset_sink_stereo_qos;
			} else {
				group_stream_params[i].qos = &lc3_preset_sink.qos;
			}
			group_stream_params[i].stream = &headsets[headset_iterator].sink_stream;

In unicast_server.c, near the top, I added the two channels support:

static struct bt_audio_codec_cap lc3_codec_sink = BT_AUDIO_CODEC_CAP_LC3(
	BT_AUDIO_CODEC_CAPABILIY_FREQ,
	(BT_AUDIO_CODEC_LC3_DURATION_10 | BT_AUDIO_CODEC_LC3_DURATION_PREFER_10),
#if CONFIG_STEREO_CIS_HEADSET
	BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(2),
#else
	BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 
#endif /* CONFIG_STEREO_CIS_HEADSET */
	LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MIN),
	LE_AUDIO_SDU_SIZE_OCTETS(CONFIG_LC3_BITRATE_MAX), 1u, AVAILABLE_SINK_CONTEXT);

I made no changes to the child image. 

Using a logic analyzer on my headset-to-codec I2S connection I can see that only one channel of data is being sent from the gateway tones mode. (Once tones works, I will hook the gateway up to USB and get stereo audio from my computer.)

As I said, I had this working in 2.5.1 based on reading past forum posts but can't get it in 2.6.1. Advice would be greatly appreciated.

Thank you very much,
ECW

Parents Reply Children
  • Hi,

    Please find below some suggestions from our developers.
    It is possible to send both left and right data in a single ISO stream by stacking both left and right data in the same SDU. After encoding on the sender side, the data would be combined. Data would later be split on the receiving side. The downside of this is that it is rather uncommon and packets over the air might get too large potentially causing retransmissions due to CRC errors.
    If the packets in the same CIG/BIG are sent with the same SDU reference, the receiving side would also perceive it like that. If you have one peripheral receiving 2 CISes, you should receive the same timestamp as long as they are in the same CIG. If the streams are sent with the same timestamp, then they should be in sync. You can send Left and Right in separate CISes to the same peripheral. On the receiving side, you can check if timestamps are the same and if they are that means that the streams are in sync (as they should be). If the timestamps happen to be different then this would need to be handled by the application. 

    Best regards,
    Dejan

Related