@@ -66,6 +66,9 @@ LOG_MODULE_REGISTER(audio_datapath, CONFIG_AUDIO_DATAPATH_LOG_LEVEL);
6666#define DRIFT_COMP_WAITING_CNT (DRIFT_MEAS_PERIOD_US / BLK_PERIOD_US)
6767/* How much data to be collected before moving on with presentation compensation */
6868#define PRES_COMP_NUM_DATA_PTS (DRIFT_MEAS_PERIOD_US / CONFIG_AUDIO_FRAME_DURATION_US)
69+ /* How many microseconds two timestamps can be apart before they are considered non-consecutive */
70+ #define CONSECUTIVE_TS_LIMIT_US \
71+ (CONFIG_AUDIO_FRAME_DURATION_US + (CONFIG_AUDIO_FRAME_DURATION_US / 2))
6972
7073/* Audio clock - nRF5340 Analog Phase-Locked Loop (APLL) */
7174#define APLL_FREQ_MIN HFCLKAUDIO_12_165_MHZ
@@ -895,6 +898,13 @@ void audio_datapath_pres_delay_us_get(uint32_t *delay_us)
895898
896899void audio_datapath_stream_out (struct net_buf * audio_frame )
897900{
901+ /* Upon first received audio frame, the delta will be invalid (as there is no previous value
902+ * to compare it to). Hence, this function only prints LOG_ERR if there are consecutive
903+ * errors.
904+ */
905+ static uint32_t consec_invalid_ts_deltas ;
906+ bool sdu_ref_not_consecutive = false;
907+
898908 if (!ctrl_blk .stream_started ) {
899909 LOG_WRN ("Stream not started" );
900910 return ;
@@ -908,38 +918,62 @@ void audio_datapath_stream_out(struct net_buf *audio_frame)
908918 struct audio_metadata * meta = net_buf_user_data (audio_frame );
909919
910920 if (meta -> ref_ts_us == ctrl_blk .prev_pres_sdu_ref_us && meta -> ref_ts_us != 0 ) {
911- LOG_WRN ("Duplicate sdu_ref_us (%d) - Dropping audio frame" , meta -> ref_ts_us );
921+ LOG_ERR ("Duplicate sdu_ref_us (%d) - Dropping audio frame" , meta -> ref_ts_us );
912922 return ;
913923 }
914924
915- bool sdu_ref_not_consecutive = false ;
925+ uint32_t sdu_ref_delta_us = meta -> ref_ts_us - ctrl_blk . prev_pres_sdu_ref_us ;
916926
917- if (ctrl_blk .prev_pres_sdu_ref_us ) {
918- uint32_t sdu_ref_delta_us = meta -> ref_ts_us - ctrl_blk .prev_pres_sdu_ref_us ;
919-
920- /* Check if the delta is from two consecutive frames */
921- if (sdu_ref_delta_us <
922- (CONFIG_AUDIO_FRAME_DURATION_US + (CONFIG_AUDIO_FRAME_DURATION_US / 2 ))) {
923- /* Check for invalid delta */
924- if ((sdu_ref_delta_us >
925- (CONFIG_AUDIO_FRAME_DURATION_US + SDU_REF_CH_DELTA_MAX_US )) ||
926- (sdu_ref_delta_us <
927- (CONFIG_AUDIO_FRAME_DURATION_US - SDU_REF_CH_DELTA_MAX_US ))) {
928- LOG_DBG ("Invalid sdu_ref_us delta (%d) - Estimating sdu_ref_us" ,
929- sdu_ref_delta_us );
930-
931- /* Estimate sdu_ref_us */
932- meta -> ref_ts_us = ctrl_blk .prev_pres_sdu_ref_us +
933- CONFIG_AUDIO_FRAME_DURATION_US ;
934- }
927+ if (meta -> ref_ts_us == 0 && ctrl_blk .prev_pres_sdu_ref_us == 0 ) {
928+ /* Timestamp not received yet */
929+ ctrl_blk .prev_pres_sdu_ref_us = meta -> ref_ts_us ;
930+ sdu_ref_not_consecutive = true;
931+
932+ } else if (sdu_ref_delta_us > CONSECUTIVE_TS_LIMIT_US ) {
933+ /* If the new timestamp is not consecutive wrt. the previous timestamp */
934+ if (consec_invalid_ts_deltas ) {
935+ LOG_ERR ("sdu_ref_us not from consecutive frames (delta: %d us)" ,
936+ sdu_ref_delta_us );
935937 } else {
936- LOG_INF ("sdu_ref_us not from consecutive frames (diff : %d us)" ,
938+ LOG_DBG ("sdu_ref_us not from consecutive frames (delta : %d us)" ,
937939 sdu_ref_delta_us );
938- sdu_ref_not_consecutive = true;
939940 }
940- }
941941
942- ctrl_blk .prev_pres_sdu_ref_us = meta -> ref_ts_us ;
942+ sdu_ref_not_consecutive = true;
943+ ctrl_blk .prev_pres_sdu_ref_us = meta -> ref_ts_us ;
944+ consec_invalid_ts_deltas ++ ;
945+
946+ } else if (!IN_RANGE (sdu_ref_delta_us ,
947+ CONFIG_AUDIO_FRAME_DURATION_US - SDU_REF_CH_DELTA_MAX_US ,
948+ CONFIG_AUDIO_FRAME_DURATION_US + SDU_REF_CH_DELTA_MAX_US )) {
949+ /* If timestamp is consecutive but has invalid delta: Estimate the timestamp */
950+ if (consec_invalid_ts_deltas ) {
951+ LOG_ERR ("Invalid sdu_ref_us delta (%d) meta->ref_ts_us %d us. "
952+ "Estimating." ,
953+ sdu_ref_delta_us , meta -> ref_ts_us );
954+ } else {
955+ LOG_DBG ("Invalid sdu_ref_us delta (%d) meta->ref_ts_us %d us. "
956+ "Estimating." ,
957+ sdu_ref_delta_us , meta -> ref_ts_us );
958+ }
959+
960+ /* Estimate ref_ts_us.
961+ * If the SDU ref was estimated, we don't update the previous reference with
962+ * the estimated value. This is to avoid an infinite loop of estimations.
963+ */
964+ uint32_t ref_ts_temp_us = meta -> ref_ts_us ;
965+
966+ meta -> ref_ts_us = ctrl_blk .prev_pres_sdu_ref_us + CONFIG_AUDIO_FRAME_DURATION_US ;
967+ ctrl_blk .prev_pres_sdu_ref_us = ref_ts_temp_us ;
968+
969+ consec_invalid_ts_deltas ++ ;
970+ } else {
971+ /* The new timestamp is valid. It is consecutive and
972+ * within the expected range compared to the last timestamp.
973+ */
974+ ctrl_blk .prev_pres_sdu_ref_us = meta -> ref_ts_us ;
975+ consec_invalid_ts_deltas = 0 ;
976+ }
943977
944978 /*** Presentation compensation ***/
945979 if (ctrl_blk .pres_comp .enabled ) {
0 commit comments