Modify MedianFilter to work with non-full buffer. Fix get_median. Remove unneeded code from http_task (#49)

This commit is contained in:
luar123
2023-11-23 13:19:35 +01:00
committed by GitHub
Unverified
parent ffc13174ca
commit d3e20fe0eb
5 changed files with 68 additions and 81 deletions

View File

@@ -14,9 +14,7 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include "MedianFilter.h" #include "MedianFilter.h"
/** /**
* *
*/ */
@@ -25,7 +23,7 @@ int MEDIANFILTER_Init(sMedianFilter_t *medianFilter) {
(medianFilter->numNodes % 2) && (medianFilter->numNodes > 1)) { (medianFilter->numNodes % 2) && (medianFilter->numNodes > 1)) {
// initialize buffer nodes // initialize buffer nodes
for (unsigned int i = 0; i < medianFilter->numNodes; i++) { for (unsigned int i = 0; i < medianFilter->numNodes; i++) {
medianFilter->medianBuffer[i].value = 0; medianFilter->medianBuffer[i].value = INT64_MAX;
medianFilter->medianBuffer[i].nextAge = medianFilter->medianBuffer[i].nextAge =
&medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes]; &medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
medianFilter->medianBuffer[i].nextValue = medianFilter->medianBuffer[i].nextValue =
@@ -36,8 +34,7 @@ int MEDIANFILTER_Init(sMedianFilter_t *medianFilter) {
// initialize heads // initialize heads
medianFilter->ageHead = medianFilter->medianBuffer; medianFilter->ageHead = medianFilter->medianBuffer;
medianFilter->valueHead = medianFilter->medianBuffer; medianFilter->valueHead = medianFilter->medianBuffer;
medianFilter->medianHead = medianFilter->medianHead = medianFilter->medianBuffer;
&medianFilter->medianBuffer[medianFilter->numNodes / 2];
medianFilter->bufferCnt = 0; medianFilter->bufferCnt = 0;
@@ -53,6 +50,10 @@ int MEDIANFILTER_Init(sMedianFilter_t *medianFilter) {
int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample) { int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample) {
unsigned int i; unsigned int i;
sMedianNode_t *newNode, *it; sMedianNode_t *newNode, *it;
if (medianFilter->bufferCnt < medianFilter->numNodes) {
medianFilter->bufferCnt++;
}
// if oldest node is also the smallest node, // if oldest node is also the smallest node,
// increment value head // increment value head
@@ -60,8 +61,9 @@ int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample) {
medianFilter->valueHead = medianFilter->valueHead->nextValue; medianFilter->valueHead = medianFilter->valueHead->nextValue;
} }
if ((medianFilter->ageHead == medianFilter->medianHead) || if (((medianFilter->ageHead == medianFilter->medianHead) ||
(medianFilter->ageHead->value > medianFilter->medianHead->value)) { (medianFilter->ageHead->value > medianFilter->medianHead->value)) &&
(medianFilter->bufferCnt >= medianFilter->numNodes)) {
// prepare for median correction // prepare for median correction
medianFilter->medianHead = medianFilter->medianHead->prevValue; medianFilter->medianHead = medianFilter->medianHead->prevValue;
} }
@@ -80,15 +82,15 @@ int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample) {
// find new node position // find new node position
it = medianFilter->valueHead; // set iterator as value head it = medianFilter->valueHead; // set iterator as value head
for (i = 0; i < medianFilter->numNodes - 1; i++) { for (i = 0; i < medianFilter->bufferCnt - 1; i++) {
if (sample < it->value) { if (sample < it->value) {
if (i == 0) { // replace value head if new node is the smallest
medianFilter->valueHead = newNode;
}
break; break;
} }
it = it->nextValue; it = it->nextValue;
} }
if (i == 0) { // replace value head if new node is the smallest
medianFilter->valueHead = newNode;
}
// insert new node in list // insert new node in list
it->prevValue->nextValue = newNode; it->prevValue->nextValue = newNode;
@@ -96,12 +98,17 @@ int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample) {
it->prevValue = newNode; it->prevValue = newNode;
newNode->nextValue = it; newNode->nextValue = it;
if (medianFilter->bufferCnt < medianFilter->numNodes) {
medianFilter->bufferCnt++;
}
// adjust median node // adjust median node
if (i >= (medianFilter->numNodes / 2)) { if ((medianFilter->bufferCnt < medianFilter->numNodes)){
if (medianFilter->bufferCnt % 2 != 0 && medianFilter->bufferCnt != 1) {
medianFilter->medianHead = medianFilter->medianHead->prevValue;
}
if (((i > (medianFilter->bufferCnt / 2)) && (medianFilter->bufferCnt % 2 != 0)) ||
((i >= (medianFilter->bufferCnt / 2)) && (medianFilter->bufferCnt % 2 == 0))) {
medianFilter->medianHead = medianFilter->medianHead->nextValue;
}
}
else if (i >= (medianFilter->bufferCnt / 2) ) {
medianFilter->medianHead = medianFilter->medianHead->nextValue; medianFilter->medianHead = medianFilter->medianHead->nextValue;
} }
@@ -115,30 +122,31 @@ int64_t MEDIANFILTER_get_median(sMedianFilter_t *medianFilter, uint32_t n) {
int64_t avgMedian = 0; int64_t avgMedian = 0;
sMedianNode_t *it; sMedianNode_t *it;
int32_t i; int32_t i;
if (n >= medianFilter->bufferCnt) {
n = (((medianFilter->bufferCnt-1)<<1)>>1);
}
if ((n % 2) == 0) { // n should not include the center value
it = medianFilter->medianHead if ((n % 2) != 0) {
->prevValue; // set iterator as value head previous n--;
// first add previous values }
for (i = 0; i < n / 2; i++) {
avgMedian += it->value;
it = medianFilter->medianHead->prevValue;
}
it = it = medianFilter->medianHead->prevValue; // set iterator as value head previous
medianFilter->medianHead->nextValue; // set iterator as value head next // first add previous values
// second add next values for (i = 0; i < n / 2; i++) {
for (i = 0; i < n / 2; i++) { avgMedian += it->value;
avgMedian += it->value; it = it->prevValue;
it = medianFilter->medianHead->nextValue; }
}
it = medianFilter->medianHead->nextValue; // set iterator as value head next
// second add next values
for (i = 0; i < n / 2; i++) {
avgMedian += it->value;
it = it->nextValue;
} }
avgMedian += medianFilter->medianHead->value; avgMedian += medianFilter->medianHead->value;
avgMedian /= (n + 1);
if (n > 0) {
avgMedian /= (n + 1);
}
return avgMedian; return avgMedian;
} }
@@ -146,8 +154,11 @@ int64_t MEDIANFILTER_get_median(sMedianFilter_t *medianFilter, uint32_t n) {
/** /**
* *
*/ */
uint32_t MEDIANFILTER_isFull(sMedianFilter_t *medianFilter) { uint32_t MEDIANFILTER_isFull(sMedianFilter_t *medianFilter, uint32_t n) {
if (medianFilter->bufferCnt >= medianFilter->numNodes) { if (n < 1 || n > medianFilter->numNodes) {
n = medianFilter->numNodes;
}
if (medianFilter->bufferCnt >= n) {
return 1; return 1;
} else { } else {
return 0; return 0;

View File

@@ -37,7 +37,8 @@ typedef struct {
int MEDIANFILTER_Init(sMedianFilter_t *medianFilter); int MEDIANFILTER_Init(sMedianFilter_t *medianFilter);
int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample); int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample);
int64_t MEDIANFILTER_get_median(sMedianFilter_t *medianFilter, uint32_t n); int64_t MEDIANFILTER_get_median(sMedianFilter_t *medianFilter, uint32_t n);
uint32_t MEDIANFILTER_isFull(sMedianFilter_t *medianFilter); uint32_t MEDIANFILTER_isFull(sMedianFilter_t *medianFilter, uint32_t n);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -14,6 +14,7 @@
#define CHNK_CTRL_CNT 2 #define CHNK_CTRL_CNT 2
#define LATENCY_MEDIAN_FILTER_LEN 199 #define LATENCY_MEDIAN_FILTER_LEN 199
#define LATENCY_MEDIAN_FILTER_FULL 19
// set to 0 if you do not wish to be the median an average around actual // set to 0 if you do not wish to be the median an average around actual
// median average will be (LATENCY_MEDIAN_FILTER_LEN / // median average will be (LATENCY_MEDIAN_FILTER_LEN /

View File

@@ -365,7 +365,7 @@ int32_t player_latency_insert(int64_t newValue) {
medianValue = MEDIANFILTER_Insert(&latencyMedianFilter, newValue); medianValue = MEDIANFILTER_Insert(&latencyMedianFilter, newValue);
if (xSemaphoreTake(latencyBufSemaphoreHandle, pdMS_TO_TICKS(0)) == pdTRUE) { if (xSemaphoreTake(latencyBufSemaphoreHandle, pdMS_TO_TICKS(0)) == pdTRUE) {
if (MEDIANFILTER_isFull(&latencyMedianFilter)) { if (MEDIANFILTER_isFull(&latencyMedianFilter, LATENCY_MEDIAN_FILTER_FULL)) {
latencyBuffFull = true; latencyBuffFull = true;
// ESP_LOGI(TAG, "(full) latency median: %lldus", medianValue); // ESP_LOGI(TAG, "(full) latency median: %lldus", medianValue);
@@ -1417,7 +1417,7 @@ static void player_task(void *pvParameters) {
// resync hard if we are getting very late / early. // resync hard if we are getting very late / early.
// rest gets tuned in through apll speed control // rest gets tuned in through apll speed control
if ((msgWaiting == 0) || (MEDIANFILTER_isFull(&shortMedianFilter) && if ((msgWaiting == 0) || (MEDIANFILTER_isFull(&shortMedianFilter,0) &&
(abs(shortMedian) > hardResyncThreshold))) (abs(shortMedian) > hardResyncThreshold)))
// if (msgWaiting == 0) // if (msgWaiting == 0)
{ {
@@ -1467,7 +1467,7 @@ static void player_task(void *pvParameters) {
#if USE_SAMPLE_INSERTION // WIP: insert samples to adjust sync #if USE_SAMPLE_INSERTION // WIP: insert samples to adjust sync
if ((enableControlLoop == true) && if ((enableControlLoop == true) &&
(MEDIANFILTER_isFull(&shortMedianFilter))) { (MEDIANFILTER_isFull(&shortMedianFilter,0))) {
if (avg < -miniOffset) { // we are early if (avg < -miniOffset) { // we are early
dir = -1; dir = -1;
dir_insert_sample = -1; dir_insert_sample = -1;
@@ -1478,7 +1478,7 @@ static void player_task(void *pvParameters) {
} }
#else // use APLL to adjust sync #else // use APLL to adjust sync
if ((enableControlLoop == true) && if ((enableControlLoop == true) &&
(MEDIANFILTER_isFull(&shortMedianFilter))) { (MEDIANFILTER_isFull(&shortMedianFilter,0))) {
if ((shortMedian < -shortOffset) && (miniMedian < -miniOffset) && if ((shortMedian < -shortOffset) && (miniMedian < -miniOffset) &&
(avg < -miniOffset)) { // we are early (avg < -miniOffset)) { // we are early
dir = -1; dir = -1;

View File

@@ -778,21 +778,6 @@ static void http_get_task(void *pvParameters) {
timeout = FAST_SYNC_LATENCY_BUF; timeout = FAST_SYNC_LATENCY_BUF;
esp_timer_stop(timeSyncMessageTimer); esp_timer_stop(timeSyncMessageTimer);
if (received_header == true) {
if (!esp_timer_is_active(timeSyncMessageTimer)) {
esp_timer_start_periodic(timeSyncMessageTimer, timeout);
}
bool is_full = false;
latency_buffer_full(&is_full, portMAX_DELAY);
if ((is_full == true) && (timeout < NORMAL_SYNC_LATENCY_BUF)) {
if (esp_timer_is_active(timeSyncMessageTimer)) {
esp_timer_stop(timeSyncMessageTimer);
}
esp_timer_start_periodic(timeSyncMessageTimer, timeout);
}
}
if (opusDecoder != NULL) { if (opusDecoder != NULL) {
opus_decoder_destroy(opusDecoder); opus_decoder_destroy(opusDecoder);
@@ -2210,18 +2195,6 @@ static void http_get_task(void *pvParameters) {
esp_timer_start_periodic(timeSyncMessageTimer, esp_timer_start_periodic(timeSyncMessageTimer,
timeout); timeout);
} }
bool is_full = false;
latency_buffer_full(&is_full, portMAX_DELAY);
if ((is_full == true) &&
(timeout < NORMAL_SYNC_LATENCY_BUF)) {
if (esp_timer_is_active(timeSyncMessageTimer)) {
esp_timer_stop(timeSyncMessageTimer);
}
esp_timer_start_periodic(timeSyncMessageTimer,
timeout);
}
} }
break; break;
@@ -2636,18 +2609,6 @@ static void http_get_task(void *pvParameters) {
esp_timer_start_periodic(timeSyncMessageTimer, esp_timer_start_periodic(timeSyncMessageTimer,
timeout); timeout);
} }
bool is_full = false;
latency_buffer_full(&is_full, portMAX_DELAY);
if ((is_full == true) &&
(timeout < NORMAL_SYNC_LATENCY_BUF)) {
if (esp_timer_is_active(timeSyncMessageTimer)) {
esp_timer_stop(timeSyncMessageTimer);
}
esp_timer_start_periodic(timeSyncMessageTimer,
timeout);
}
} }
} }
@@ -2677,6 +2638,19 @@ static void http_get_task(void *pvParameters) {
esp_timer_stop(timeSyncMessageTimer); esp_timer_stop(timeSyncMessageTimer);
} }
esp_timer_start_periodic(timeSyncMessageTimer,
timeout);
}
else if ((is_full == false) &&
(timeout > FAST_SYNC_LATENCY_BUF)){
timeout = FAST_SYNC_LATENCY_BUF;
ESP_LOGI(TAG, "latency buffer not full");
if (esp_timer_is_active(timeSyncMessageTimer)) {
esp_timer_stop(timeSyncMessageTimer);
}
esp_timer_start_periodic(timeSyncMessageTimer, esp_timer_start_periodic(timeSyncMessageTimer,
timeout); timeout);
} }