Modify MedianFilter to work with non-full buffer. Fix get_median. Remove unneeded code from http_task (#49)
This commit is contained in:
committed by
GitHub
Unverified
parent
ffc13174ca
commit
d3e20fe0eb
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 /
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
52
main/main.c
52
main/main.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user