- merge with original master from jorgen
- minimize RAM usage of all components - use both IRAM and DRAM in player component so we can buffer up to 1s on modules without SPI RAM - support fragemented pcm chunks so we can use all available RAM if there isn't a big enough block available but still enough HEAP - reinclude all components from jorgen's master branch - add custom i2s driver to get a precise timing of initial sync - change wrong usage of esp_timer for latency measurement of snapcast protocol - add player component
This commit is contained in:
@@ -1,3 +1,2 @@
|
||||
idf_component_register(SRCS "MedianFilter.c"
|
||||
INCLUDE_DIRS "include")
|
||||
|
||||
INCLUDE_DIRS "include")
|
||||
|
||||
@@ -20,104 +20,101 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int MEDIANFILTER_Init(sMedianFilter_t *medianFilter)
|
||||
{
|
||||
if (medianFilter && medianFilter->medianBuffer &&
|
||||
(medianFilter->numNodes % 2) && (medianFilter->numNodes > 1))
|
||||
{
|
||||
//initialize buffer nodes
|
||||
for(unsigned int i = 0; i < medianFilter->numNodes; i++)
|
||||
{
|
||||
medianFilter->medianBuffer[i].value = 0;
|
||||
medianFilter->medianBuffer[i].nextAge = &medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
|
||||
medianFilter->medianBuffer[i].nextValue = &medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
|
||||
medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes].prevValue = &medianFilter->medianBuffer[i];
|
||||
}
|
||||
//initialize heads
|
||||
medianFilter->ageHead = medianFilter->medianBuffer;
|
||||
medianFilter->valueHead = medianFilter->medianBuffer;
|
||||
medianFilter->medianHead = &medianFilter->medianBuffer[medianFilter->numNodes / 2];
|
||||
|
||||
medianFilter->bufferCnt = 0;
|
||||
|
||||
return 0;
|
||||
int MEDIANFILTER_Init(sMedianFilter_t *medianFilter) {
|
||||
if (medianFilter && medianFilter->medianBuffer &&
|
||||
(medianFilter->numNodes % 2) && (medianFilter->numNodes > 1)) {
|
||||
// initialize buffer nodes
|
||||
for (unsigned int i = 0; i < medianFilter->numNodes; i++) {
|
||||
medianFilter->medianBuffer[i].value = 0;
|
||||
medianFilter->medianBuffer[i].nextAge =
|
||||
&medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
|
||||
medianFilter->medianBuffer[i].nextValue =
|
||||
&medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
|
||||
medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes].prevValue =
|
||||
&medianFilter->medianBuffer[i];
|
||||
}
|
||||
// initialize heads
|
||||
medianFilter->ageHead = medianFilter->medianBuffer;
|
||||
medianFilter->valueHead = medianFilter->medianBuffer;
|
||||
medianFilter->medianHead =
|
||||
&medianFilter->medianBuffer[medianFilter->numNodes / 2];
|
||||
|
||||
return -1;
|
||||
medianFilter->bufferCnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample)
|
||||
{
|
||||
unsigned int i;
|
||||
sMedianNode_t *newNode, *it;
|
||||
int64_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int64_t sample) {
|
||||
unsigned int i;
|
||||
sMedianNode_t *newNode, *it;
|
||||
|
||||
if(medianFilter->ageHead == medianFilter->valueHead)
|
||||
{ //if oldest node is also the smallest node, increment value head
|
||||
medianFilter->valueHead = medianFilter->valueHead->nextValue;
|
||||
if (medianFilter->ageHead ==
|
||||
medianFilter->valueHead) { // if oldest node is also the smallest node,
|
||||
// increment value head
|
||||
medianFilter->valueHead = medianFilter->valueHead->nextValue;
|
||||
}
|
||||
|
||||
if ((medianFilter->ageHead == medianFilter->medianHead) ||
|
||||
(medianFilter->ageHead->value >
|
||||
medianFilter->medianHead->value)) { // prepare for median correction
|
||||
medianFilter->medianHead = medianFilter->medianHead->prevValue;
|
||||
}
|
||||
|
||||
// replace age head with new sample
|
||||
newNode = medianFilter->ageHead;
|
||||
newNode->value = sample;
|
||||
|
||||
// remove age head from list
|
||||
medianFilter->ageHead->nextValue->prevValue =
|
||||
medianFilter->ageHead->prevValue;
|
||||
medianFilter->ageHead->prevValue->nextValue =
|
||||
medianFilter->ageHead->nextValue;
|
||||
// increment age head
|
||||
medianFilter->ageHead = medianFilter->ageHead->nextAge;
|
||||
|
||||
// find new node position
|
||||
it = medianFilter->valueHead; // set iterator as value head
|
||||
for (i = 0; i < medianFilter->numNodes - 1; i++) {
|
||||
if (sample < it->value) {
|
||||
if (i == 0) { // replace value head if new node is the smallest
|
||||
medianFilter->valueHead = newNode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
it = it->nextValue;
|
||||
}
|
||||
|
||||
if((medianFilter->ageHead == medianFilter->medianHead) ||
|
||||
(medianFilter->ageHead->value > medianFilter->medianHead->value))
|
||||
{ //prepare for median correction
|
||||
medianFilter->medianHead = medianFilter->medianHead->prevValue;
|
||||
}
|
||||
// insert new node in list
|
||||
it->prevValue->nextValue = newNode;
|
||||
newNode->prevValue = it->prevValue;
|
||||
it->prevValue = newNode;
|
||||
newNode->nextValue = it;
|
||||
|
||||
//replace age head with new sample
|
||||
newNode = medianFilter->ageHead;
|
||||
newNode->value = sample;
|
||||
if (medianFilter->bufferCnt < medianFilter->numNodes) {
|
||||
medianFilter->bufferCnt++;
|
||||
}
|
||||
|
||||
//remove age head from list
|
||||
medianFilter->ageHead->nextValue->prevValue = medianFilter->ageHead->prevValue;
|
||||
medianFilter->ageHead->prevValue->nextValue = medianFilter->ageHead->nextValue;
|
||||
//increment age head
|
||||
medianFilter->ageHead = medianFilter->ageHead->nextAge;
|
||||
// adjust median node
|
||||
if (i >= (medianFilter->numNodes / 2)) {
|
||||
medianFilter->medianHead = medianFilter->medianHead->nextValue;
|
||||
}
|
||||
|
||||
//find new node position
|
||||
it = medianFilter->valueHead; //set iterator as value head
|
||||
for(i = 0; i < medianFilter->numNodes - 1; i++)
|
||||
{
|
||||
if(sample < it->value)
|
||||
{
|
||||
if(i == 0)
|
||||
{ //replace value head if new node is the smallest
|
||||
medianFilter->valueHead = newNode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
it = it->nextValue;
|
||||
}
|
||||
|
||||
//insert new node in list
|
||||
it->prevValue->nextValue = newNode;
|
||||
newNode->prevValue = it->prevValue;
|
||||
it->prevValue = newNode;
|
||||
newNode->nextValue = it;
|
||||
|
||||
if (medianFilter->bufferCnt < medianFilter->numNodes) {
|
||||
medianFilter->bufferCnt++;
|
||||
}
|
||||
|
||||
//adjust median node
|
||||
if(i >= (medianFilter->numNodes / 2))
|
||||
{
|
||||
medianFilter->medianHead = medianFilter->medianHead->nextValue;
|
||||
}
|
||||
|
||||
return medianFilter->medianHead->value;
|
||||
return medianFilter->medianHead->value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
uint8_t MEDIANFILTER_isFull(sMedianFilter_t *medianFilter) {
|
||||
if (medianFilter->bufferCnt < medianFilter->numNodes) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
if (medianFilter->bufferCnt < medianFilter->numNodes) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,22 +18,20 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct sMedianNode
|
||||
{
|
||||
int64_t value; //sample value
|
||||
struct sMedianNode *nextAge; //pointer to next oldest value
|
||||
struct sMedianNode *nextValue; //pointer to next smallest value
|
||||
struct sMedianNode *prevValue; //pointer to previous smallest value
|
||||
typedef struct sMedianNode {
|
||||
int64_t value; // sample value
|
||||
struct sMedianNode *nextAge; // pointer to next oldest value
|
||||
struct sMedianNode *nextValue; // pointer to next smallest value
|
||||
struct sMedianNode *prevValue; // pointer to previous smallest value
|
||||
} sMedianNode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int numNodes; //median node buffer length
|
||||
sMedianNode_t *medianBuffer; //median node buffer
|
||||
sMedianNode_t *ageHead; //pointer to oldest value
|
||||
sMedianNode_t *valueHead; //pointer to smallest value
|
||||
sMedianNode_t *medianHead; //pointer to median value
|
||||
unsigned int bufferCnt;
|
||||
typedef struct {
|
||||
unsigned int numNodes; // median node buffer length
|
||||
sMedianNode_t *medianBuffer; // median node buffer
|
||||
sMedianNode_t *ageHead; // pointer to oldest value
|
||||
sMedianNode_t *valueHead; // pointer to smallest value
|
||||
sMedianNode_t *medianHead; // pointer to median value
|
||||
unsigned int bufferCnt;
|
||||
} sMedianFilter_t;
|
||||
|
||||
int MEDIANFILTER_Init(sMedianFilter_t *medianFilter);
|
||||
@@ -44,4 +42,4 @@ uint8_t MEDIANFILTER_isFull(sMedianFilter_t *medianFilter);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MEDIANFILTER_H_
|
||||
#endif // MEDIANFILTER_H_
|
||||
|
||||
Reference in New Issue
Block a user