some small speed further optimization to 24 bits SPDIF

This commit is contained in:
philippe44
2023-09-22 22:38:37 -07:00
parent 456f16fc79
commit b413780048
2 changed files with 22 additions and 32 deletions

View File

@@ -26,7 +26,7 @@
#include "cJSON.h" #include "cJSON.h"
#include "tools.h" #include "tools.h"
#define PSEUDO_IDLE_STACK_SIZE (6*1024) #define PSEUDO_IDLE_STACK_SIZE (8*1024)
#define MONITOR_TIMER (10*1000) #define MONITOR_TIMER (10*1000)
#define SCRATCH_SIZE 256 #define SCRATCH_SIZE 256

View File

@@ -93,9 +93,6 @@ static void (*pseudo_idle_chain)(uint32_t now);
#define CONFIG_AMP_GPIO_LEVEL 1 #define CONFIG_AMP_GPIO_LEVEL 1
#endif #endif
#define VUCP24 (0xCC)
#define VUCP24I (0x32)
extern struct outputstate output; extern struct outputstate output;
extern struct buffer *streambuf; extern struct buffer *streambuf;
extern struct buffer *outputbuf; extern struct buffer *outputbuf;
@@ -117,8 +114,6 @@ static frames_t oframes;
static struct { static struct {
bool enabled; bool enabled;
u8_t *buf; u8_t *buf;
size_t count;
u8_t vucp;
} spdif; } spdif;
static size_t dma_buf_frames; static size_t dma_buf_frames;
static TaskHandle_t output_i2s_task; static TaskHandle_t output_i2s_task;
@@ -134,7 +129,7 @@ static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32
static void output_thread_i2s(void *arg); static void output_thread_i2s(void *arg);
static void i2s_stats(uint32_t now); static void i2s_stats(uint32_t now);
static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count, u8_t *vucp); static void spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst);
static void (*jack_handler_chain)(bool inserted); static void (*jack_handler_chain)(bool inserted);
#define I2C_PORT 0 #define I2C_PORT 0
@@ -545,8 +540,6 @@ static void output_thread_i2s(void *arg) {
isI2SStarted = false; isI2SStarted = false;
i2s_stop(CONFIG_I2S_NUM); i2s_stop(CONFIG_I2S_NUM);
adac->power(ADAC_STANDBY); adac->power(ADAC_STANDBY);
spdif.count = 0;
spdif.vucp = VUCP24;
} }
usleep(100000); usleep(100000);
continue; continue;
@@ -593,6 +586,7 @@ static void output_thread_i2s(void *arg) {
i2s_zero_dma_buffer(CONFIG_I2S_NUM); i2s_zero_dma_buffer(CONFIG_I2S_NUM);
i2s_start(CONFIG_I2S_NUM); i2s_start(CONFIG_I2S_NUM);
adac->power(ADAC_ON); adac->power(ADAC_ON);
if (spdif.enabled) spdif_convert(NULL, 0, NULL);
} }
// this does not work well as set_sample_rates resets the fifos (and it's too early) // this does not work well as set_sample_rates resets the fifos (and it's too early)
@@ -622,7 +616,7 @@ static void output_thread_i2s(void *arg) {
// need IRAM for speed but can't allocate a FRAME_BLOCK * 16, so process by smaller chunks // need IRAM for speed but can't allocate a FRAME_BLOCK * 16, so process by smaller chunks
while (count < oframes) { while (count < oframes) {
size_t chunk = min(SPDIF_BLOCK, oframes - count); size_t chunk = min(SPDIF_BLOCK, oframes - count);
spdif_convert((ISAMPLE_T*) obuf + count * 2, chunk, (u32_t*) spdif.buf, &spdif.count, &spdif.vucp); spdif_convert((ISAMPLE_T*) obuf + count * 2, chunk, (u32_t*) spdif.buf);
i2s_write(CONFIG_I2S_NUM, spdif.buf, chunk * 16, &obytes, portMAX_DELAY); i2s_write(CONFIG_I2S_NUM, spdif.buf, chunk * 16, &obytes, portMAX_DELAY);
bytes += obytes / (16 / BYTES_PER_FRAME); bytes += obytes / (16 / BYTES_PER_FRAME);
count += chunk; count += chunk;
@@ -663,7 +657,7 @@ static void i2s_stats(uint32_t now) {
// then see if we need to act // then see if we need to act
if (output.state <= OUTPUT_STOPPED || now < last + STATS_PERIOD_MS) return; if (output.state <= OUTPUT_STOPPED || now < last + STATS_PERIOD_MS) return;
last = now; last = now;
LOG_INFO( "Output State: %d, current sample rate: %d, bytes per frame: %d", output.state, output.current_sample_rate, BYTES_PER_FRAME); LOG_INFO( "Output State: %d, current sample rate: %d, bytes per frame: %d", output.state, output.current_sample_rate, BYTES_PER_FRAME);
LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD1); LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD1);
LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD2); LOG_INFO( LINE_MIN_MAX_FORMAT_HEAD2);
@@ -687,11 +681,12 @@ static void i2s_stats(uint32_t now) {
/**************************************************************************************** /****************************************************************************************
* SPDIF support * SPDIF support
*/ */
#define PREAMBLE_B (0xE8) //11101000 #define PREAMBLE_B (0xE8) //11101000
#define PREAMBLE_M (0xE2) //11100010 #define PREAMBLE_M (0xE2) //11100010
#define PREAMBLE_W (0xE4) //11100100 #define PREAMBLE_W (0xE4) //11100100
static const u8_t VUCP24[2] = { 0xCC, 0x32 };
static const u16_t spdif_bmclookup[256] = { static const u16_t spdif_bmclookup[256] = {
0xcccc, 0xb333, 0xd333, 0xaccc, 0xcb33, 0xb4cc, 0xd4cc, 0xab33, 0xcccc, 0xb333, 0xd333, 0xaccc, 0xcb33, 0xb4cc, 0xd4cc, 0xab33,
0xcd33, 0xb2cc, 0xd2cc, 0xad33, 0xcacc, 0xb533, 0xd533, 0xaacc, 0xcd33, 0xb2cc, 0xd2cc, 0xad33, 0xcacc, 0xb533, 0xd533, 0xaacc,
@@ -740,14 +735,18 @@ static const u16_t spdif_bmclookup[256] = {
The I2S interface must output first the B/M/W preamble which means that second The I2S interface must output first the B/M/W preamble which means that second
32 bits words must be first and so must be marked right channel. 32 bits words must be first and so must be marked right channel.
*/ */
static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count, u8_t *vucp) { static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst) {
static u8_t vu, count;
register u16_t hi, lo; register u16_t hi, lo;
#if BYTES_PER_FRAME == 8 #if BYTES_PER_FRAME == 8
register u16_t aux; register u16_t aux;
#endif #endif
register u8_t vu = *vucp;
size_t cnt = *count; if (!src) {
count = 192;
vu = VUCP24[0];
}
while (frames--) { while (frames--) {
// start with left channel // start with left channel
#if BYTES_PER_FRAME == 4 #if BYTES_PER_FRAME == 4
@@ -755,9 +754,9 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, s
lo = spdif_bmclookup[(u8_t)*src++]; lo = spdif_bmclookup[(u8_t)*src++];
if (lo & 1) hi = ~hi; if (lo & 1) hi = ~hi;
if (++cnt > 191) { if (!count--) {
*dst++ = (vu << 24) | (PREAMBLE_B << 16) | 0xCCCC; *dst++ = (vu << 24) | (PREAMBLE_B << 16) | 0xCCCC;
cnt = 0; count = 192;
} else { } else {
*dst++ = (vu << 24) | (PREAMBLE_M << 16) | 0xCCCC; *dst++ = (vu << 24) | (PREAMBLE_M << 16) | 0xCCCC;
} }
@@ -768,16 +767,16 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, s
if (aux & 1) lo = ~lo; if (aux & 1) lo = ~lo;
if (lo & 1) hi = ~hi; if (lo & 1) hi = ~hi;
if (++cnt > 191) {
if (!count--) {
*dst++ = (vu << 24) | (PREAMBLE_B << 16) | aux; *dst++ = (vu << 24) | (PREAMBLE_B << 16) | aux;
cnt = 0; count = 192;
} else { } else {
*dst++ = (vu << 24) | (PREAMBLE_M << 16) | aux; *dst++ = (vu << 24) | (PREAMBLE_M << 16) | aux;
} }
#endif #endif
if (hi & 1) vu = VUCP24I; vu = VUCP24[hi & 1];
else vu = VUCP24;
*dst++ = ((u32_t)lo << 16) | hi; *dst++ = ((u32_t)lo << 16) | hi;
// then do right channel, no need to check PREAMBLE_B // then do right channel, no need to check PREAMBLE_B
@@ -797,16 +796,7 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, s
*dst++ = (vu << 24) | (PREAMBLE_W << 16) | aux; *dst++ = (vu << 24) | (PREAMBLE_W << 16) | aux;
#endif #endif
if (hi & 1) vu = VUCP24I; vu = VUCP24[hi & 1];
else vu = VUCP24;
*dst++ = ((u32_t)lo << 16) | hi; *dst++ = ((u32_t)lo << 16) | hi;
} }
*count = cnt;
*vucp = vu;
} }