- clean up code

- add pre commit using GNU style
- remove some minor issues regarding the use of global variables and such
This commit is contained in:
Carlos
2021-08-27 10:31:30 +02:00
Unverified
parent e799aaac25
commit 0ea47690fa
10 changed files with 4141 additions and 3219 deletions

23
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,23 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/codespell-project/codespell
rev: v1.16.0
hooks:
- id: codespell
- repo: https://github.com/pocc/pre-commit-hooks
rev: v1.1.1
hooks:
- id: clang-format
args: [-i, --style=GNU]
# args: [-i, --style=Google]
# - id: clang-tidy
# args: [-checks=clang-diagnostic-return-type]
# - id: uncrustify
# - id: cppcheck
# args: [--enable=all]

File diff suppressed because it is too large Load Diff

View File

@@ -14,13 +14,11 @@
#include "dsps_biquad_gen.h"
#include "esp_log.h"
//#include "websocket_if.h"
#include "board_pins_config.h"
#include "driver/dac.h"
#include "driver/i2s.h"
#include "dsp_processor.h"
#include "hal/i2s_hal.h"
//#include "adc1_i2s_private.h"
#include "board_pins_config.h"
#ifdef CONFIG_USE_BIQUAD_ASM
#define BIQUAD dsps_biquad_f32_ae32
@@ -30,226 +28,212 @@
static const char *TAG = "dspProc";
//static const uint8_t chunkDurationMs = CONFIG_WIRE_CHUNK_DURATION_MS;
//static const uint32_t sampleRate = CONFIG_PCM_SAMPLE_RATE;
//static const uint8_t channels = CONFIG_CHANNELS;
//static const uint8_t bitsPerSample = CONFIG_BITS_PER_SAMPLE;
// TODO: allocate these buffers dynamically from heap
static float *sbuffer0 = NULL;//[1024];
//static float sbuffer1[1024];
//static float sbuffer2[1024];
static float *sbufout0 = NULL;//[1024];
//static float sbufout1[1024];
//static float sbufout2[1024];
static float *sbuftmp0 = NULL;//[1024];
//static uint8_t dsp_audio[4 * 1024];
//static uint8_t dsp_audio1[4 * 1024];
extern uint8_t muteCH[4];
static float *sbuffer0 = NULL;
static float *sbufout0 = NULL;
static float *sbuftmp0 = NULL;
static uint32_t currentSamplerate = 0;
static uint32_t currentChunkDurationMs = 0;
ptype_t bq[8];
static ptype_t bq[8];
int dsp_processor(char *audio, size_t chunk_size, dspFlows_t dspFlow) {
int
dsp_processor (char *audio, size_t chunk_size, dspFlows_t dspFlow)
{
double dynamic_vol = 1.0;
int16_t len = chunk_size / 4;
int16_t valint;
uint16_t i;
// ESP_LOGI(TAG,
// "got data %p, %d, %u", audio, chunk_size, dspFlow);
if ((sbuffer0 == NULL) || (sbufout0 == NULL) || (sbuftmp0 == NULL))
{
ESP_LOGE (TAG, "No Memory allocated for dsp_processor %p %p %p",
sbuffer0, sbufout0, sbuftmp0);
if ((sbuffer0 == NULL) || (sbufout0 == NULL) || (sbuftmp0 == NULL)) {
ESP_LOGE(
TAG,
"No Memory allocated for dsp_processor %p %p %p", sbuffer0, sbufout0, sbuftmp0);
return -1;
}
return -1;
}
/*
for (uint16_t i = 0; i < len; i++) {
sbuffer0[i] =
dynamic_vol * 0.5 *
((float)((int16_t)(audio[i * 4 + 1] << 8) + audio[i * 4 + 0])) / 32768;
sbuffer1[i] =
dynamic_vol * 0.5 *
((float)((int16_t)(audio[i * 4 + 3] << 8) + audio[i * 4 + 2])) / 32768;
sbuffer2[i] = ((sbuffer0[i] / 2) + (sbuffer1[i] / 2));
}
*/
switch (dspFlow) {
case dspfStereo: {
// for (i = 0; i < len; i++) {
// audio[i * 4 + 0] = (muteCH[0] == 1) ? 0 : audio[i * 4 + 0];
// audio[i * 4 + 1] = (muteCH[0] == 1) ? 0 : audio[i * 4 + 1];
// audio[i * 4 + 2] = (muteCH[1] == 1) ? 0 : audio[i * 4 + 2];
// audio[i * 4 + 3] = (muteCH[1] == 1) ? 0 : audio[i * 4 + 3];
// }
// mute is done through audio_hal_set_mute()
} break;
case dspfBassBoost: { // CH0 low shelf 6dB @ 400Hz
// channel 0
for (i = 0; i < len; i++) {
sbuffer0[i] =
dynamic_vol * 0.5 *
((float)((int16_t)(audio[i * 4 + 1] << 8) + audio[i * 4 + 0])) / 32768;
switch (dspFlow)
{
case dspfStereo:
{
}
BIQUAD(sbuffer0, sbufout0, len, bq[6].coeffs, bq[6].w);
break;
for (i = 0; i < len; i++) {
valint = (int16_t)(sbufout0[i] * 32768);
case dspfBassBoost:
{ // CH0 low shelf 6dB @ 400Hz
// channel 0
for (i = 0; i < len; i++)
{
sbuffer0[i] = dynamic_vol * 0.5
* ((float)((int16_t) (audio[i * 4 + 1] << 8)
+ audio[i * 4 + 0]))
/ 32768;
}
BIQUAD (sbuffer0, sbufout0, len, bq[6].coeffs, bq[6].w);
audio[i * 4 + 0] = (valint & 0x00ff);
audio[i * 4 + 1] = ((valint & 0xff00) >> 8);
for (i = 0; i < len; i++)
{
valint = (int16_t) (sbufout0[i] * 32768);
audio[i * 4 + 0] = (valint & 0x00ff);
audio[i * 4 + 1] = ((valint & 0xff00) >> 8);
}
// channel 1
for (i = 0; i < len; i++)
{
sbuffer0[i] = dynamic_vol * 0.5
* ((float)((int16_t) (audio[i * 4 + 3] << 8)
+ audio[i * 4 + 2]))
/ 32768;
}
BIQUAD (sbuffer0, sbufout0, len, bq[7].coeffs, bq[7].w);
for (i = 0; i < len; i++)
{
valint = (int16_t) (sbufout0[i] * 32768);
audio[i * 4 + 2] = (valint & 0x00ff);
audio[i * 4 + 3] = ((valint & 0xff00) >> 8);
}
}
break;
// channel 1
for (i = 0; i < len; i++) {
sbuffer0[i] =
dynamic_vol * 0.5 *
((float)((int16_t)(audio[i * 4 + 3] << 8) + audio[i * 4 + 2])) / 32768;
case dspfBiamp:
{
// Process audio ch0 LOW PASS FILTER
for (i = 0; i < len; i++)
{
sbuffer0[i] = dynamic_vol * 0.5
* ((float)((int16_t) (audio[i * 4 + 1] << 8)
+ audio[i * 4 + 0]))
/ 32768;
}
BIQUAD (sbuffer0, sbuftmp0, len, bq[0].coeffs, bq[0].w);
BIQUAD (sbuftmp0, sbufout0, len, bq[1].coeffs, bq[1].w);
for (i = 0; i < len; i++)
{
valint = (int16_t) (sbufout0[i] * 32768);
audio[i * 4 + 0] = (valint & 0x00ff);
audio[i * 4 + 1] = ((valint & 0xff00) >> 8);
}
// Process audio ch1 HIGH PASS FILTER
for (i = 0; i < len; i++)
{
sbuffer0[i] = dynamic_vol * 0.5
* ((float)((int16_t) (audio[i * 4 + 3] << 8)
+ audio[i * 4 + 2]))
/ 32768;
}
BIQUAD (sbuffer0, sbuftmp0, len, bq[2].coeffs, bq[2].w);
BIQUAD (sbuftmp0, sbufout0, len, bq[3].coeffs, bq[3].w);
for (i = 0; i < len; i++)
{
valint = (int16_t) (sbufout0[i] * 32768);
audio[i * 4 + 2] = (valint & 0x00ff);
audio[i * 4 + 3] = ((valint & 0xff00) >> 8);
}
}
BIQUAD(sbuffer0, sbufout0, len, bq[7].coeffs, bq[7].w);
break;
for (i = 0; i < len; i++) {
valint = (int16_t)(sbufout0[i] * 32768);
audio[i * 4 + 2] = (valint & 0x00ff);
audio[i * 4 + 3] = ((valint & 0xff00) >> 8);
case dspf2DOT1:
{ // Process audio L + R LOW PASS FILTER
/*
BIQUAD(sbuffer2, sbuftmp0, len, bq[0].coeffs, bq[0].w);
BIQUAD(sbuftmp0, sbufout2, len, bq[1].coeffs, bq[1].w);
// Process audio L HIGH PASS FILTER
BIQUAD(sbuffer0, sbuftmp0, len, bq[2].coeffs, bq[2].w);
BIQUAD(sbuftmp0, sbufout0, len, bq[3].coeffs, bq[3].w);
// Process audio R HIGH PASS FILTER
BIQUAD(sbuffer1, sbuftmp0, len, bq[4].coeffs, bq[4].w);
BIQUAD(sbuftmp0, sbufout1, len, bq[5].coeffs, bq[5].w);
int16_t valint[5];
for (uint16_t i = 0; i < len; i++) {
valint[0] =
(muteCH[0] == 1) ? (int16_t)0 : (int16_t)(sbufout0[i] *
32768); valint[1] = (muteCH[1] == 1) ? (int16_t)0 :
(int16_t)(sbufout1[i] * 32768); valint[2] = (muteCH[2] == 1) ?
(int16_t)0 : (int16_t)(sbufout2[i] * 32768); dsp_audio[i * 4 + 0] =
(valint[2] & 0xff); dsp_audio[i * 4 + 1] = ((valint[2] & 0xff00) >>
8); dsp_audio[i * 4 + 2] = 0; dsp_audio[i * 4 + 3] = 0;
dsp_audio1[i * 4 + 0] = (valint[0] & 0xff);
dsp_audio1[i * 4 + 1] = ((valint[0] & 0xff00) >> 8);
dsp_audio1[i * 4 + 2] = (valint[1] & 0xff);
dsp_audio1[i * 4 + 3] = ((valint[1] & 0xff00) >> 8);
}
// TODO: this copy could be avoided if dsp_audio buffers are
// allocated dynamically and pointers are exchanged after
// audio was freed
memcpy(audio, dsp_audio, chunk_size);
ESP_LOGW(TAG, "Don't know what to do with dsp_audio1");
*/
ESP_LOGW (TAG, "dspf2DOT1, not implemented yet, using stereo instead");
}
break;
} break;
case dspfFunkyHonda:
{ // Process audio L + R LOW PASS FILTER
/*
BIQUAD(sbuffer2, sbuftmp0, len, bq[0].coeffs, bq[0].w);
BIQUAD(sbuftmp0, sbufout2, len, bq[1].coeffs, bq[1].w);
case dspfBiamp: {
// Process audio ch0 LOW PASS FILTER
for (i = 0; i < len; i++) {
sbuffer0[i] =
dynamic_vol * 0.5 *
((float)((int16_t)(audio[i * 4 + 1] << 8) + audio[i * 4 + 0])) / 32768;
}
BIQUAD(sbuffer0, sbuftmp0, len, bq[0].coeffs, bq[0].w);
BIQUAD(sbuftmp0, sbufout0, len, bq[1].coeffs, bq[1].w);
// Process audio L HIGH PASS FILTER
BIQUAD(sbuffer0, sbuftmp0, len, bq[2].coeffs, bq[2].w);
BIQUAD(sbuftmp0, sbufout0, len, bq[3].coeffs, bq[3].w);
for (i = 0; i < len; i++) {
valint = (int16_t)(sbufout0[i] * 32768);
audio[i * 4 + 0] = (valint & 0x00ff);
audio[i * 4 + 1] = ((valint & 0xff00) >> 8);
// Process audio R HIGH PASS FILTER
BIQUAD(sbuffer1, sbuftmp0, len, bq[4].coeffs, bq[4].w);
BIQUAD(sbuftmp0, sbufout1, len, bq[5].coeffs, bq[5].w);
uint16_t scale = 16384; // 32768
int16_t valint[5];
for (uint16_t i = 0; i < len; i++) {
valint[0] =
(muteCH[0] == 1) ? (int16_t)0 : (int16_t)(sbufout0[i] * scale);
valint[1] =
(muteCH[1] == 1) ? (int16_t)0 : (int16_t)(sbufout1[i] * scale);
valint[2] =
(muteCH[2] == 1) ? (int16_t)0 : (int16_t)(sbufout2[i] * scale);
valint[3] = valint[0] + valint[2];
valint[4] = -valint[2];
valint[5] = -valint[1] - valint[2];
dsp_audio[i * 4 + 0] = (valint[3] & 0xff);
dsp_audio[i * 4 + 1] = ((valint[3] & 0xff00) >> 8);
dsp_audio[i * 4 + 2] = (valint[2] & 0xff);
dsp_audio[i * 4 + 3] = ((valint[2] & 0xff00) >> 8);
dsp_audio1[i * 4 + 0] = (valint[4] & 0xff);
dsp_audio1[i * 4 + 1] = ((valint[4] & 0xff00) >> 8);
dsp_audio1[i * 4 + 2] = (valint[5] & 0xff);
dsp_audio1[i * 4 + 3] = ((valint[5] & 0xff00) >> 8);
}
// TODO: this copy could be avoided if dsp_audio buffers are
// allocated dynamically and pointers are exchanged after
// audio was freed
memcpy(audio, dsp_audio, chunk_size);
ESP_LOGW(TAG, "Don't know what to do with dsp_audio1");
*/
ESP_LOGW (TAG,
"dspfFunkyHonda, not implemented yet, using stereo instead");
}
break;
// Process audio ch1 HIGH PASS FILTER
for (i = 0; i < len; i++) {
sbuffer0[i] =
dynamic_vol * 0.5 *
((float)((int16_t)(audio[i * 4 + 3] << 8) + audio[i * 4 + 2])) / 32768;
default:
{
}
BIQUAD(sbuffer0, sbuftmp0, len, bq[2].coeffs, bq[2].w);
BIQUAD(sbuftmp0, sbufout0, len, bq[3].coeffs, bq[3].w);
for (i = 0; i < len; i++) {
valint = (int16_t)(sbufout0[i] * 32768);
audio[i * 4 + 2] = (valint & 0x00ff);
audio[i * 4 + 3] = ((valint & 0xff00) >> 8);
}
} break;
case dspf2DOT1: { // Process audio L + R LOW PASS FILTER
/*
BIQUAD(sbuffer2, sbuftmp0, len, bq[0].coeffs, bq[0].w);
BIQUAD(sbuftmp0, sbufout2, len, bq[1].coeffs, bq[1].w);
// Process audio L HIGH PASS FILTER
BIQUAD(sbuffer0, sbuftmp0, len, bq[2].coeffs, bq[2].w);
BIQUAD(sbuftmp0, sbufout0, len, bq[3].coeffs, bq[3].w);
// Process audio R HIGH PASS FILTER
BIQUAD(sbuffer1, sbuftmp0, len, bq[4].coeffs, bq[4].w);
BIQUAD(sbuftmp0, sbufout1, len, bq[5].coeffs, bq[5].w);
int16_t valint[5];
for (uint16_t i = 0; i < len; i++) {
valint[0] =
(muteCH[0] == 1) ? (int16_t)0 : (int16_t)(sbufout0[i] * 32768);
valint[1] =
(muteCH[1] == 1) ? (int16_t)0 : (int16_t)(sbufout1[i] * 32768);
valint[2] =
(muteCH[2] == 1) ? (int16_t)0 : (int16_t)(sbufout2[i] * 32768);
dsp_audio[i * 4 + 0] = (valint[2] & 0xff);
dsp_audio[i * 4 + 1] = ((valint[2] & 0xff00) >> 8);
dsp_audio[i * 4 + 2] = 0;
dsp_audio[i * 4 + 3] = 0;
dsp_audio1[i * 4 + 0] = (valint[0] & 0xff);
dsp_audio1[i * 4 + 1] = ((valint[0] & 0xff00) >> 8);
dsp_audio1[i * 4 + 2] = (valint[1] & 0xff);
dsp_audio1[i * 4 + 3] = ((valint[1] & 0xff00) >> 8);
}
// TODO: this copy could be avoided if dsp_audio buffers are
// allocated dynamically and pointers are exchanged after
// audio was freed
memcpy(audio, dsp_audio, chunk_size);
ESP_LOGW(TAG, "Don't know what to do with dsp_audio1");
*/
ESP_LOGW(TAG, "dspf2DOT1, not implemented yet, using stereo instead");
} break;
case dspfFunkyHonda: { // Process audio L + R LOW PASS FILTER
/*
BIQUAD(sbuffer2, sbuftmp0, len, bq[0].coeffs, bq[0].w);
BIQUAD(sbuftmp0, sbufout2, len, bq[1].coeffs, bq[1].w);
// Process audio L HIGH PASS FILTER
BIQUAD(sbuffer0, sbuftmp0, len, bq[2].coeffs, bq[2].w);
BIQUAD(sbuftmp0, sbufout0, len, bq[3].coeffs, bq[3].w);
// Process audio R HIGH PASS FILTER
BIQUAD(sbuffer1, sbuftmp0, len, bq[4].coeffs, bq[4].w);
BIQUAD(sbuftmp0, sbufout1, len, bq[5].coeffs, bq[5].w);
uint16_t scale = 16384; // 32768
int16_t valint[5];
for (uint16_t i = 0; i < len; i++) {
valint[0] =
(muteCH[0] == 1) ? (int16_t)0 : (int16_t)(sbufout0[i] * scale);
valint[1] =
(muteCH[1] == 1) ? (int16_t)0 : (int16_t)(sbufout1[i] * scale);
valint[2] =
(muteCH[2] == 1) ? (int16_t)0 : (int16_t)(sbufout2[i] * scale);
valint[3] = valint[0] + valint[2];
valint[4] = -valint[2];
valint[5] = -valint[1] - valint[2];
dsp_audio[i * 4 + 0] = (valint[3] & 0xff);
dsp_audio[i * 4 + 1] = ((valint[3] & 0xff00) >> 8);
dsp_audio[i * 4 + 2] = (valint[2] & 0xff);
dsp_audio[i * 4 + 3] = ((valint[2] & 0xff00) >> 8);
dsp_audio1[i * 4 + 0] = (valint[4] & 0xff);
dsp_audio1[i * 4 + 1] = ((valint[4] & 0xff00) >> 8);
dsp_audio1[i * 4 + 2] = (valint[5] & 0xff);
dsp_audio1[i * 4 + 3] = ((valint[5] & 0xff00) >> 8);
}
// TODO: this copy could be avoided if dsp_audio buffers are
// allocated dynamically and pointers are exchanged after
// audio was freed
memcpy(audio, dsp_audio, chunk_size);
ESP_LOGW(TAG, "Don't know what to do with dsp_audio1");
*/
ESP_LOGW(TAG, "dspfFunkyHonda, not implemented yet, using stereo instead");
} break;
default: { } break; }
break;
}
return 0;
}
@@ -268,117 +252,134 @@ int dsp_processor(char *audio, size_t chunk_size, dspFlows_t dspFlow) {
// ----------------------------------------
// Fixed 2x2 biquad flow Xover for biAmp systems
// Interface for cross over frequency and level
void dsp_setup_flow(double freq, uint32_t samplerate, uint32_t chunkDurationMs) {
void
dsp_setup_flow (double freq, uint32_t samplerate, uint32_t chunkDurationMs)
{
float f = freq / samplerate / 2.0;
uint16_t len = (samplerate * chunkDurationMs / 1000);
if (((currentSamplerate == samplerate) && (currentChunkDurationMs == chunkDurationMs)) ||
(samplerate == 0) || (chunkDurationMs == 0))
{
return;
}
if (((currentSamplerate == samplerate)
&& (currentChunkDurationMs == chunkDurationMs))
|| (samplerate == 0) || (chunkDurationMs == 0))
{
return;
}
currentSamplerate = samplerate;
currentChunkDurationMs = chunkDurationMs;
bq[0] = (ptype_t){LPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[1] = (ptype_t){LPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[2] = (ptype_t){HPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[3] = (ptype_t){HPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[4] = (ptype_t){HPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[5] = (ptype_t){HPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[6] = (ptype_t){LOWSHELF, f, 6, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[7] = (ptype_t){LOWSHELF, f, 6, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[0]
= (ptype_t){ LPF, f, 0, 0.707, NULL, NULL, { 0, 0, 0, 0, 0 }, { 0, 0 } };
bq[1]
= (ptype_t){ LPF, f, 0, 0.707, NULL, NULL, { 0, 0, 0, 0, 0 }, { 0, 0 } };
bq[2]
= (ptype_t){ HPF, f, 0, 0.707, NULL, NULL, { 0, 0, 0, 0, 0 }, { 0, 0 } };
bq[3]
= (ptype_t){ HPF, f, 0, 0.707, NULL, NULL, { 0, 0, 0, 0, 0 }, { 0, 0 } };
bq[4]
= (ptype_t){ HPF, f, 0, 0.707, NULL, NULL, { 0, 0, 0, 0, 0 }, { 0, 0 } };
bq[5]
= (ptype_t){ HPF, f, 0, 0.707, NULL, NULL, { 0, 0, 0, 0, 0 }, { 0, 0 } };
bq[6] = (ptype_t){ LOWSHELF, f, 6, 0.707, NULL, NULL,
{ 0, 0, 0, 0, 0 }, { 0, 0 } };
bq[7] = (ptype_t){ LOWSHELF, f, 6, 0.707, NULL, NULL,
{ 0, 0, 0, 0, 0 }, { 0, 0 } };
// pnode_t *aflow = NULL;
// aflow = malloc(sizeof(pnode_t));
// if (aflow == NULL) {
// printf("Could not create node");
// }
for (uint8_t n = 0; n <= 7; n++) {
switch (bq[n].filtertype) {
case LOWSHELF:
dsps_biquad_gen_lowShelf_f32(bq[n].coeffs, bq[n].freq, bq[n].gain,
bq[n].q);
break;
case LPF:
dsps_biquad_gen_lpf_f32(bq[n].coeffs, bq[n].freq, bq[n].q);
break;
case HPF:
dsps_biquad_gen_hpf_f32(bq[n].coeffs, bq[n].freq, bq[n].q);
break;
default:
break;
for (uint8_t n = 0; n <= 7; n++)
{
switch (bq[n].filtertype)
{
case LOWSHELF:
dsps_biquad_gen_lowShelf_f32 (bq[n].coeffs, bq[n].freq, bq[n].gain,
bq[n].q);
break;
case LPF:
dsps_biquad_gen_lpf_f32 (bq[n].coeffs, bq[n].freq, bq[n].q);
break;
case HPF:
dsps_biquad_gen_hpf_f32 (bq[n].coeffs, bq[n].freq, bq[n].q);
break;
default:
break;
}
// for (uint8_t i = 0; i <= 4; i++) {
// printf("%.6f ", bq[n].coeffs[i]);
// }
// printf("\n");
}
// for (uint8_t i = 0; i <= 4; i++) {
// printf("%.6f ", bq[n].coeffs[i]);
// }
// printf("\n");
}
if (sbuffer0 != NULL) {
free(sbuffer0);
sbuffer0 = NULL;
}
if (sbufout0 != NULL) {
free(sbufout0);
sbufout0 = NULL;
}
if (sbuftmp0 != NULL) {
free(sbuftmp0);
sbuftmp0 = NULL;
}
if (sbuffer0 != NULL)
{
free (sbuffer0);
sbuffer0 = NULL;
}
if (sbufout0 != NULL)
{
free (sbufout0);
sbufout0 = NULL;
}
if (sbuftmp0 != NULL)
{
free (sbuftmp0);
sbuftmp0 = NULL;
}
sbuffer0 = (float *)heap_caps_malloc(sizeof(float) * len, MALLOC_CAP_8BIT);
sbufout0 = (float *)heap_caps_malloc(sizeof(float) * len, MALLOC_CAP_8BIT);
sbuftmp0 = (float *)heap_caps_malloc(sizeof(float) * len, MALLOC_CAP_8BIT);
if ((sbuffer0 == NULL) || (sbufout0 == NULL) || (sbuftmp0 == NULL)) {
ESP_LOGE(
TAG,
"Failed to allocate initial memory for dsp_processor %p %p %p", sbuffer0, sbufout0, sbuftmp0);
sbuffer0 = (float *)heap_caps_malloc (sizeof (float) * len, MALLOC_CAP_8BIT);
sbufout0 = (float *)heap_caps_malloc (sizeof (float) * len, MALLOC_CAP_8BIT);
sbuftmp0 = (float *)heap_caps_malloc (sizeof (float) * len, MALLOC_CAP_8BIT);
if ((sbuffer0 == NULL) || (sbufout0 == NULL) || (sbuftmp0 == NULL))
{
ESP_LOGE (TAG,
"Failed to allocate initial memory for dsp_processor %p %p %p",
sbuffer0, sbufout0, sbuftmp0);
if (sbuffer0) {
free(sbuffer0);
}
if (sbufout0) {
free(sbufout0);
}
if (sbuftmp0) {
free(sbuftmp0);
}
}
else {
ESP_LOGI(
TAG,
"GOT memory for dsp_processor %p %p", sbuffer0, sbufout0);
}
if (sbuffer0)
{
free (sbuffer0);
}
if (sbufout0)
{
free (sbufout0);
}
if (sbuftmp0)
{
free (sbuftmp0);
}
}
else
{
ESP_LOGI (TAG, "GOT memory for dsp_processor %p %p", sbuffer0, sbufout0);
}
}
void dsp_set_xoverfreq(uint8_t freqh, uint8_t freql, uint32_t samplerate) {
void
dsp_set_xoverfreq (uint8_t freqh, uint8_t freql, uint32_t samplerate)
{
float freq = freqh * 256 + freql;
// printf("%f\n", freq);
// printf("%f\n", freq);
float f = freq / samplerate / 2.;
for (int8_t n = 0; n <= 5; n++) {
bq[n].freq = f;
switch (bq[n].filtertype) {
case LPF:
// for (uint8_t i = 0; i <= 4; i++) {
// printf("%.6f ", bq[n].coeffs[i]);
// }
// printf("\n");
dsps_biquad_gen_lpf_f32(bq[n].coeffs, bq[n].freq, bq[n].q);
// for (uint8_t i = 0; i <= 4; i++) {
// printf("%.6f ", bq[n].coeffs[i]);
// }
// printf("%f \n", bq[n].freq);
break;
case HPF:
dsps_biquad_gen_hpf_f32(bq[n].coeffs, bq[n].freq, bq[n].q);
break;
default:
break;
for (int8_t n = 0; n <= 5; n++)
{
bq[n].freq = f;
switch (bq[n].filtertype)
{
case LPF:
// for (uint8_t i = 0; i <= 4; i++) {
// printf("%.6f ", bq[n].coeffs[i]);
// }
// printf("\n");
dsps_biquad_gen_lpf_f32 (bq[n].coeffs, bq[n].freq, bq[n].q);
// for (uint8_t i = 0; i <= 4; i++) {
// printf("%.6f ", bq[n].coeffs[i]);
// }
// printf("%f \n", bq[n].freq);
break;
case HPF:
dsps_biquad_gen_hpf_f32 (bq[n].coeffs, bq[n].freq, bq[n].q);
break;
default:
break;
}
}
}
}
#endif

View File

@@ -13,37 +13,43 @@
// limitations under the License.
#include "dsps_sqrt.h"
#include "esp_err.h"
#include <math.h>
inline float dsps_sqrtf_f32_ansi(float f)
inline float
dsps_sqrtf_f32_ansi (float f)
{
const int result = 0x1fbb4000 + (*(int*)&f >> 1);
return *(float*)&result;
const int result = 0x1fbb4000 + (*(int *)&f >> 1);
return *(float *)&result;
}
esp_err_t dsps_sqrt_f32_ansi(const float *input, float *output, int len)
esp_err_t
dsps_sqrt_f32_ansi (const float *input, float *output, int len)
{
if (NULL == input) return ESP_ERR_DSP_PARAM_OUTOFRANGE;
if (NULL == output) return ESP_ERR_DSP_PARAM_OUTOFRANGE;
if (NULL == input)
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
if (NULL == output)
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
for (int i = 0 ; i < len ; i++) {
output[i] = dsps_sqrtf_f32_ansi(input[i]);
for (int i = 0; i < len; i++)
{
output[i] = dsps_sqrtf_f32_ansi (input[i]);
}
return ESP_OK;
return ESP_OK;
}
float dsps_inverted_sqrtf_f32_ansi(float data )
{
const float x2 = data * 0.5F;
const float threehalfs = 1.5F;
float
dsps_inverted_sqrtf_f32_ansi (float data)
{
const float x2 = data * 0.5F;
const float threehalfs = 1.5F;
union {
float f;
uint32_t i;
} conv = {data}; // member 'f' set to value of 'data'.
conv.i = 0x5f3759df - ( conv.i >> 1 );
conv.f *= ( threehalfs - ( x2 * conv.f * conv.f ) );
return conv.f;
union
{
float f;
uint32_t i;
} conv = { data }; // member 'f' set to value of 'data'.
conv.i = 0x5f3759df - (conv.i >> 1);
conv.f *= (threehalfs - (x2 * conv.f * conv.f));
return conv.f;
}

View File

@@ -1,60 +1,69 @@
#ifndef __PLAYER_H__
#define __PLAYER_H__
#include "freertos/FreeRTOS.h"
#include "esp_types.h"
#include "freertos/FreeRTOS.h"
#include "i2s.h"
#include "sdkconfig.h"
#include "snapcast.h"
#include "i2s.h"
#define I2S_PORT I2S_NUM_0
extern volatile int64_t clientDacLatency;
#define LATENCY_MEDIAN_FILTER_LEN 99
#define SHORT_BUFFER_LEN 29
typedef struct pcm_chunk_fragment pcm_chunk_fragment_t;
struct pcm_chunk_fragment {
struct pcm_chunk_fragment
{
size_t size;
char *payload;
pcm_chunk_fragment_t *nextFragment;
};
typedef struct pcm_chunk_message {
typedef struct pcm_chunk_message
{
tv_t timestamp;
pcm_chunk_fragment_t *fragment;
} pcm_chunk_message_t;
typedef enum codec_type_e { NONE, PCM, FLAC, OGG, OPUS } codec_type_t;
typedef enum codec_type_e
{
NONE,
PCM,
FLAC,
OGG,
OPUS
} codec_type_t;
typedef struct snapcastSetting_s {
uint32_t buffer_ms;
uint32_t chunkDuration_ms;
typedef struct snapcastSetting_s
{
uint32_t buffer_ms;
uint32_t chunkDuration_ms;
int32_t clientDacLatency_ms;
codec_type_t codec;
int32_t sampleRate;
uint8_t channels;
i2s_bits_per_sample_t bits;
codec_type_t codec;
int32_t sampleRate;
uint8_t channels;
i2s_bits_per_sample_t bits;
bool muted;
uint32_t volume;
bool muted;
uint32_t volume;
} snapcastSetting_t;
QueueHandle_t init_player(void);
int deinit_player(void);
QueueHandle_t init_player (void);
int deinit_player (void);
int8_t insert_pcm_chunk(wire_chunk_message_t *decodedWireChunk);
int8_t free_pcm_chunk(pcm_chunk_message_t *pcmChunk);
int8_t insert_pcm_chunk (wire_chunk_message_t *decodedWireChunk);
int8_t free_pcm_chunk (pcm_chunk_message_t *pcmChunk);
int8_t player_latency_insert(int64_t newValue);
int8_t player_notify_buffer_ms(uint32_t ms);
int8_t player_send_snapcast_setting(snapcastSetting_t setting);
int8_t player_latency_insert (int64_t newValue);
int8_t player_notify_buffer_ms (uint32_t ms);
int8_t player_send_snapcast_setting (snapcastSetting_t setting);
int8_t reset_latency_buffer(void);
int8_t latency_buffer_full(void);
int8_t get_diff_to_server(int64_t *tDiff);
int8_t server_now(int64_t *sNow);
int8_t reset_latency_buffer (void);
int8_t latency_buffer_full (void);
int8_t get_diff_to_server (int64_t *tDiff);
int8_t server_now (int64_t *sNow);
#endif // __PLAYER_H__
#endif // __PLAYER_H__

File diff suppressed because it is too large Load Diff

View File

@@ -24,128 +24,136 @@ static const char *TAG = "NETF";
extern EventGroupHandle_t s_wifi_event_group;
static const char *if_str[] = {"STA", "AP", "ETH", "MAX"};
static const char *ip_protocol_str[] = {"V4", "V6", "MAX"};
static const char *if_str[] = { "STA", "AP", "ETH", "MAX" };
static const char *ip_protocol_str[] = { "V4", "V6", "MAX" };
void net_mdns_register(const char *clientname) {
ESP_LOGI(TAG, "Setup mdns");
ESP_ERROR_CHECK(mdns_init());
ESP_ERROR_CHECK(mdns_hostname_set(clientname));
ESP_ERROR_CHECK(mdns_instance_name_set("ESP32 SNAPcast client OTA"));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_http", "_tcp", 8032, NULL, 0));
void
net_mdns_register (const char *clientname)
{
ESP_LOGI (TAG, "Setup mdns");
ESP_ERROR_CHECK (mdns_init ());
ESP_ERROR_CHECK (mdns_hostname_set (clientname));
ESP_ERROR_CHECK (mdns_instance_name_set ("ESP32 SNAPcast client OTA"));
ESP_ERROR_CHECK (mdns_service_add (NULL, "_http", "_tcp", 8032, NULL, 0));
}
void mdns_print_results(mdns_result_t *results) {
void
mdns_print_results (mdns_result_t *results)
{
mdns_result_t *r = results;
mdns_ip_addr_t *a = NULL;
int i = 1, t;
while (r) {
printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if],
ip_protocol_str[r->ip_protocol]);
if (r->instance_name) {
printf(" PTR : %s\n", r->instance_name);
while (r)
{
printf ("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if],
ip_protocol_str[r->ip_protocol]);
if (r->instance_name)
{
printf (" PTR : %s\n", r->instance_name);
}
if (r->hostname)
{
printf (" SRV : %s.local:%u\n", r->hostname, r->port);
}
if (r->txt_count)
{
printf (" TXT : [%u] ", r->txt_count);
for (t = 0; t < r->txt_count; t++)
{
printf ("%s=%s; ", r->txt[t].key, r->txt[t].value);
}
printf ("\n");
}
a = r->addr;
while (a)
{
if (a->addr.type == IPADDR_TYPE_V6)
{
printf (" AAAA: " IPV6STR "\n", IPV62STR (a->addr.u_addr.ip6));
}
else
{
printf (" A : " IPSTR "\n", IP2STR (&(a->addr.u_addr.ip4)));
}
a = a->next;
}
r = r->next;
}
if (r->hostname) {
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
}
if (r->txt_count) {
printf(" TXT : [%u] ", r->txt_count);
for (t = 0; t < r->txt_count; t++) {
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
}
printf("\n");
}
a = r->addr;
while (a) {
if (a->addr.type == IPADDR_TYPE_V6) {
printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6));
} else {
printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4)));
}
a = a->next;
}
r = r->next;
}
}
uint32_t find_mdns_service(const char *service_name, const char *proto) {
ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto);
uint32_t
find_mdns_service (const char *service_name, const char *proto)
{
ESP_LOGI (TAG, "Query PTR: %s.%s.local", service_name, proto);
mdns_result_t *r = NULL;
esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &r);
if (err) {
ESP_LOGE(TAG, "Query Failed");
return -1;
}
if (!r) {
ESP_LOGW(TAG, "No results found!");
return -1;
}
esp_err_t err = mdns_query_ptr (service_name, proto, 3000, 20, &r);
if (err)
{
ESP_LOGE (TAG, "Query Failed");
return -1;
}
if (!r)
{
ESP_LOGW (TAG, "No results found!");
return -1;
}
if (r->instance_name) {
printf(" PTR : %s\n", r->instance_name);
}
if (r->hostname) {
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
return r->port;
}
mdns_query_results_free(r);
if (r->instance_name)
{
printf (" PTR : %s\n", r->instance_name);
}
if (r->hostname)
{
printf (" SRV : %s.local:%u\n", r->hostname, r->port);
return r->port;
}
mdns_query_results_free (r);
return 0;
}
static int sntp_synced = 0;
/*
void sntp_sync_time(struct timeval *tv_ntp) {
if ((sntp_synced%10) == 0) {
settimeofday(tv_ntp,NULL);
sntp_synced++;
ESP_LOGI(TAG,"SNTP time set from server number :%d",sntp_synced);
return;
}
sntp_synced++;
struct timeval tv_esp;
gettimeofday(&tv_esp, NULL);
//ESP_LOGI(TAG,"SNTP diff s: %ld , %ld ", tv_esp.tv_sec , tv_ntp->tv_sec);
ESP_LOGI(TAG,"SNTP diff us: %ld , %ld ", tv_esp.tv_usec , tv_ntp->tv_usec);
ESP_LOGI(TAG,"SNTP diff us: %.2f", (double)((tv_esp.tv_usec -
tv_ntp->tv_usec)/1000.0));
}*/
void sntp_cb(struct timeval *tv) {
struct tm timeinfo = {0};
/**
*
*/
void
sntp_cb (struct timeval *tv)
{
struct tm timeinfo = { 0 };
time_t now = tv->tv_sec;
localtime_r(&now, &timeinfo);
localtime_r (&now, &timeinfo);
char strftime_buf[64];
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
ESP_LOGI(TAG, "sntp_cb called :%s", strftime_buf);
strftime (strftime_buf, sizeof (strftime_buf), "%c", &timeinfo);
ESP_LOGI (TAG, "sntp_cb called :%s", strftime_buf);
}
void set_time_from_sntp() {
xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, false, true,
portMAX_DELAY);
void
set_time_from_sntp ()
{
xEventGroupWaitBits (s_wifi_event_group, WIFI_CONNECTED_BIT, false, true,
portMAX_DELAY);
// ESP_LOGI(TAG, "clock %");
ESP_LOGI(TAG, "Initializing SNTP");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, CONFIG_SNTP_SERVER);
sntp_init();
ESP_LOGI (TAG, "Initializing SNTP");
sntp_setoperatingmode (SNTP_OPMODE_POLL);
sntp_setservername (0, CONFIG_SNTP_SERVER);
sntp_init ();
// sntp_set_time_sync_notification_cb(sntp_cb);
setenv("TZ", SNTP_TIMEZONE, 1);
tzset();
setenv ("TZ", SNTP_TIMEZONE, 1);
tzset ();
time_t now = 0;
struct tm timeinfo = {0};
struct tm timeinfo = { 0 };
int retry = 0;
const int retry_count = 10;
while (timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry,
retry_count);
vTaskDelay(2000 / portTICK_PERIOD_MS);
time(&now);
localtime_r(&now, &timeinfo);
}
while (timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count)
{
ESP_LOGI (TAG, "Waiting for system time to be set... (%d/%d)", retry,
retry_count);
vTaskDelay (2000 / portTICK_PERIOD_MS);
time (&now);
localtime_r (&now, &timeinfo);
}
char strftime_buf[64];
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
ESP_LOGI(TAG, "The current date/time in UTC is: %s", strftime_buf);
strftime (strftime_buf, sizeof (strftime_buf), "%c", &timeinfo);
ESP_LOGI (TAG, "The current date/time in UTC is: %s", strftime_buf);
}

View File

@@ -6,21 +6,22 @@
*
* \brief RTP audio stream receiver
*
* \warning This software is a PROTOTYPE version and is not designed or intended
* for use in production, especially not for safety-critical applications! The
* user represents and warrants that it will NOT use or redistribute the
* Software for such purposes. This prototype is for research purposes only.
* This software is provided "AS IS," without a warranty of any kind.
* \warning This software is a PROTOTYPE version and is not designed or
* intended for use in production, especially not for safety-critical
* applications! The user represents and warrants that it will NOT use or
* redistribute the Software for such purposes. This prototype is for research
* purposes only. This software is provided "AS IS," without a warranty of any
* kind.
*/
#include "rtprx.h"
#include <lwip/netdb.h>
#include "i2s.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "freertos/FreeRTOS.h"
#include "i2s.h"
#include "lwip/api.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
@@ -31,34 +32,42 @@
static bool rtpRxState = 0;
void rtp_rx_start() {
if (rtpRxState == 0) {
setup_rtp_i2s();
xTaskCreate(rtp_rx_task, "RTPRx", 12 * 1024, NULL, 0, NULL);
rtpRxState = 1;
}
void
rtp_rx_start ()
{
if (rtpRxState == 0)
{
setup_rtp_i2s ();
xTaskCreate (rtp_rx_task, "RTPRx", 12 * 1024, NULL, 0, NULL);
rtpRxState = 1;
}
}
void rtp_rx_stop() {
if (rtpRxState == 1) {
i2s_custom_driver_uninstall(0);
// vTaskDelete(xTaskSignal); xxx Fix me
rtpRxState = 0;
}
void
rtp_rx_stop ()
{
if (rtpRxState == 1)
{
i2s_custom_driver_uninstall (0);
// vTaskDelete(xTaskSignal); xxx Fix me
rtpRxState = 0;
}
}
void rtp_rx_task(void *pvParameters) {
void
rtp_rx_task (void *pvParameters)
{
OpusDecoder *decoder;
// int size = opus_decoder_get_size(2);
int oe = 0;
decoder = opus_decoder_create(48000, 2, &oe);
decoder = opus_decoder_create (48000, 2, &oe);
// int error = opus_decoder_init(decoder, 48000, 2);
printf("Initialized Decoder: %d", oe);
printf ("Initialized Decoder: %d", oe);
// int32_t *audio32 = (int32_t*)malloc(960*sizeof(int32_t));
int16_t *audio = (int16_t *)malloc(960 * 2 * sizeof(int16_t));
i2s_custom_zero_dma_buffer(0);
int16_t *audio = (int16_t *)malloc (960 * 2 * sizeof (int16_t));
i2s_custom_zero_dma_buffer (0);
static struct netconn *conn;
static struct netbuf *buf;
static uint32_t pkg = 0;
@@ -66,115 +75,129 @@ void rtp_rx_task(void *pvParameters) {
err_t err;
uint16_t oldseq = 1;
uint16_t first = 1;
conn = netconn_new(NETCONN_UDP);
if (conn != NULL) {
printf("Net RTP RX\n");
netconn_bind(conn, IP_ADDR_ANY, 1350);
netconn_listen(conn);
printf("Net RTP will enter loopn\n");
while (1) {
netconn_recv(conn, &buf);
if (buf == NULL) {
printf("NETCONN RX error \n");
}
pkg++;
conn = netconn_new (NETCONN_UDP);
if (conn != NULL)
{
printf ("Net RTP RX\n");
netconn_bind (conn, IP_ADDR_ANY, 1350);
netconn_listen (conn);
printf ("Net RTP will enter loopn\n");
while (1)
{
netconn_recv (conn, &buf);
if (buf == NULL)
{
printf ("NETCONN RX error \n");
}
pkg++;
uint8_t *p = (buf->p->payload);
uint16_t seq = (p[2] << 8) + p[3];
if ((seq != oldseq + 1) & (first != 1)) {
printf("seq : %d, oldseq : %d \n", seq, oldseq);
uint16_t errors = seq - oldseq - 1;
pkgerror = pkgerror + errors;
printf("ERROR --- Package drop : %d %d \n", errors, pkgerror);
size_t bWritten;
// for (int i = 0; i;i++ )
int ret = i2s_custom_write_expand(0, (char *)audio, 960 * 2 * sizeof(int16_t),
16, 32, &bWritten, 100);
printf("bWritten : %d ret : %d \n ", bWritten, ret);
uint8_t *p = (buf->p->payload);
uint16_t seq = (p[2] << 8) + p[3];
if ((seq != oldseq + 1) & (first != 1))
{
printf ("seq : %d, oldseq : %d \n", seq, oldseq);
uint16_t errors = seq - oldseq - 1;
pkgerror = pkgerror + errors;
printf ("ERROR --- Package drop : %d %d \n", errors, pkgerror);
size_t bWritten;
// for (int i = 0; i;i++ )
int ret = i2s_custom_write_expand (0, (char *)audio,
960 * 2 * sizeof (int16_t),
16, 32, &bWritten, 100);
printf ("bWritten : %d ret : %d \n ", bWritten, ret);
// opus_pkg = NULL;
}
// opus_pkg = NULL;
}
if (seq < oldseq) {
printf("ERROR --- Package order:");
}
oldseq = seq;
first = 0;
// printf("UDP package len : %d -> \n", buf->p->len);
// printf("UDP package : %02x %02x %02x %02x\n",p[0],p[1],p[2],p[3]);
// printf("Timestamp : %02x %02x %02x %02x\n",p[4],p[5],p[6],p[7]);
// printf("Sync source : %02x %02x %02x
// %02x\n",p[8],p[9],p[10],p[11]); printf("R1 : %d
// \n",(p[12]&0xf8)>>3) ; int size = 240;
unsigned char *opus_pkg = buf->p->payload + 12;
int size = opus_decode(decoder, (unsigned char *)opus_pkg,
if (seq < oldseq)
{
printf ("ERROR --- Package order:");
}
oldseq = seq;
first = 0;
// printf("UDP package len : %d -> \n", buf->p->len);
// printf("UDP package : %02x %02x %02x
// %02x\n",p[0],p[1],p[2],p[3]); printf("Timestamp : %02x %02x
// %02x %02x\n",p[4],p[5],p[6],p[7]); printf("Sync source : %02x
// %02x %02x %02x\n",p[8],p[9],p[10],p[11]); printf("R1 : %d
// \n",(p[12]&0xf8)>>3) ; int size = 240;
unsigned char *opus_pkg = buf->p->payload + 12;
int size
= opus_decode (decoder, (unsigned char *)opus_pkg,
buf->p->len - 12, (opus_int16 *)audio, 960, 0);
if (size < 0) {
printf("Decode error : %d \n", size);
}
if (size < 0)
{
printf ("Decode error : %d \n", size);
}
// for (int i = 0; i < size*2; i++) {
// audio[i*2] = 0x0000;
// audio[i*2+1] = 0x0000;
//}
// for (int i = 0; i < size*2; i++) {
// audio[i*2] = 0x0000;
// audio[i*2+1] = 0x0000;
//}
size_t bWritten;
int ret = i2s_custom_write_expand(0, (char *)audio, size * 2 * sizeof(int16_t),
16, 32, &bWritten, 100);
if (ret != 0)
printf("Error I2S written: %d %d %d \n", ret,
size * 2 * sizeof(int16_t), bWritten);
size_t bWritten;
int ret = i2s_custom_write_expand (0, (char *)audio,
size * 2 * sizeof (int16_t), 16,
32, &bWritten, 100);
if (ret != 0)
printf ("Error I2S written: %d %d %d \n", ret,
size * 2 * sizeof (int16_t), bWritten);
if ((pkg % 1000) == 1) {
// printf("I2S written: %d %d \n", size*sizeof(int32_t) ,bWritten);
printf("%d > %d %d %d\n", pkg, size, buf->p->len, buf->p->tot_len);
printf("UDP package len : %d -> \n", buf->p->len);
printf("UDP package : %02x %02x %02x %02x\n", p[0], p[1], p[2],
p[3]);
printf("Timestamp : %02x %02x %02x %02x\n", p[4], p[5], p[6],
p[7]);
printf("Sync source : %02x %02x %02x %02x\n", p[8], p[9], p[10],
p[11]);
printf("R1 : %d \n", (p[12] & 0xf8) >> 3);
if ((pkg % 1000) == 1)
{
// printf("I2S written: %d %d \n", size*sizeof(int32_t)
// ,bWritten);
printf ("%d > %d %d %d\n", pkg, size, buf->p->len,
buf->p->tot_len);
printf ("UDP package len : %d -> \n", buf->p->len);
printf ("UDP package : %02x %02x %02x %02x\n", p[0], p[1],
p[2], p[3]);
printf ("Timestamp : %02x %02x %02x %02x\n", p[4], p[5],
p[6], p[7]);
printf ("Sync source : %02x %02x %02x %02x\n", p[8], p[9],
p[10], p[11]);
printf ("R1 : %d \n", (p[12] & 0xf8) >> 3);
for (int i = 0; i < 8; i++)
printf("%02d %04x %04x\n", i, audio[2 * i], audio[2 * i + 1]);
}
for (int i = 0; i < 8; i++)
printf ("%02d %04x %04x\n", i, audio[2 * i], audio[2 * i + 1]);
}
// netbuf_free(buf);
netbuf_delete(buf);
// netbuf_free(buf);
netbuf_delete (buf);
}
}
}
netconn_close(conn);
netconn_delete(conn);
netconn_close (conn);
netconn_delete (conn);
}
void setup_rtp_i2s() {
void
setup_rtp_i2s ()
{
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
.sample_rate = 48000,
.bits_per_sample = 32,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
.communication_format = I2S_COMM_FORMAT_I2S,
.dma_buf_count = 8,
.dma_buf_len = 480,
//.intr_alloc_flags = 1, //Default interrupt priority
.use_apll = true,
.fixed_mclk = 0,
.tx_desc_auto_clear = true // Auto clear tx descriptor on underflow
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
.sample_rate = 48000,
.bits_per_sample = 32,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.dma_buf_count = 8,
.dma_buf_len = 480,
//.intr_alloc_flags = 1, //Default interrupt priority
.use_apll = true,
.fixed_mclk = 0,
.tx_desc_auto_clear = true // Auto clear tx descriptor on underflow
};
i2s_custom_driver_install(0, &i2s_config, 0, NULL);
i2s_custom_start(0);
i2s_custom_zero_dma_buffer(0);
i2s_custom_driver_install (0, &i2s_config, 0, NULL);
i2s_custom_start (0);
i2s_custom_zero_dma_buffer (0);
i2s_pin_config_t pin_config = {
.bck_io_num = 12, // CONFIG_EXAMPLE_I2S_BCK_PIN,
.ws_io_num = 13, // CONFIG_EXAMPLE_I2S_LRCK_PIN,
.data_out_num = 14, // CONFIG_EXAMPLE_I2S_DATA_PIN,
.data_in_num = -1 // Not used
.bck_io_num = 12, // CONFIG_EXAMPLE_I2S_BCK_PIN,
.ws_io_num = 13, // CONFIG_EXAMPLE_I2S_LRCK_PIN,
.data_out_num = 14, // CONFIG_EXAMPLE_I2S_DATA_PIN,
.data_in_num = -1 // Not used
};
i2s_custom_set_pin(0, &pin_config);
printf("Here... set pin\n");
i2s_custom_set_pin (0, &pin_config);
printf ("Here... set pin\n");
}

View File

@@ -19,413 +19,504 @@ This program is free software: you can redistribute it and/or modify
#include "websocket_server.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include <string.h>
static SemaphoreHandle_t xwebsocket_mutex; // to lock the client array
static QueueHandle_t xwebsocket_queue; // to hold the clients that send messages
static ws_client_t clients[WEBSOCKET_SERVER_MAX_CLIENTS]; // holds list of clients
static TaskHandle_t xtask; // the task itself
static QueueHandle_t
xwebsocket_queue; // to hold the clients that send messages
static ws_client_t
clients[WEBSOCKET_SERVER_MAX_CLIENTS]; // holds list of clients
static TaskHandle_t xtask; // the task itself
static void background_callback(struct netconn* conn, enum netconn_evt evt,u16_t len) {
switch(evt) {
static void
background_callback (struct netconn *conn, enum netconn_evt evt, u16_t len)
{
switch (evt)
{
case NETCONN_EVT_RCVPLUS:
xQueueSendToBack(xwebsocket_queue,&conn,WEBSOCKET_SERVER_QUEUE_TIMEOUT);
xQueueSendToBack (xwebsocket_queue, &conn,
WEBSOCKET_SERVER_QUEUE_TIMEOUT);
break;
default:
break;
}
}
}
static void handle_read(uint8_t num) {
static void
handle_read (uint8_t num)
{
ws_header_t header;
char* msg;
char *msg;
header.received = 0;
msg = ws_read(&clients[num],&header);
msg = ws_read (&clients[num], &header);
if(!header.received) {
if(msg) free(msg);
return NULL;
}
if (!header.received)
{
if (msg)
free (msg);
return;
}
switch(clients[num].last_opcode) {
switch (clients[num].last_opcode)
{
case WEBSOCKET_OPCODE_CONT:
break;
case WEBSOCKET_OPCODE_BIN:
clients[num].scallback(num,WEBSOCKET_BIN,msg,header.length);
clients[num].scallback (num, WEBSOCKET_BIN, msg, header.length);
break;
case WEBSOCKET_OPCODE_TEXT:
clients[num].scallback(num,WEBSOCKET_TEXT,msg,header.length);
clients[num].scallback (num, WEBSOCKET_TEXT, msg, header.length);
break;
case WEBSOCKET_OPCODE_PING:
ws_send(&clients[num],WEBSOCKET_OPCODE_PONG,msg,header.length,0);
clients[num].scallback(num,WEBSOCKET_PING,msg,header.length);
ws_send (&clients[num], WEBSOCKET_OPCODE_PONG, msg, header.length, 0);
clients[num].scallback (num, WEBSOCKET_PING, msg, header.length);
break;
case WEBSOCKET_OPCODE_PONG:
if(clients[num].ping) {
clients[num].scallback(num,WEBSOCKET_PONG,NULL,0);
clients[num].ping = 0;
}
if (clients[num].ping)
{
clients[num].scallback (num, WEBSOCKET_PONG, NULL, 0);
clients[num].ping = 0;
}
break;
case WEBSOCKET_OPCODE_CLOSE:
clients[num].scallback(num,WEBSOCKET_DISCONNECT_EXTERNAL,NULL,0);
ws_disconnect_client(&clients[num], 0);
clients[num].scallback (num, WEBSOCKET_DISCONNECT_EXTERNAL, NULL, 0);
ws_disconnect_client (&clients[num], 0);
break;
default:
break;
}
if(msg) free(msg);
}
if (msg)
free (msg);
}
static void ws_server_task(void* pvParameters) {
struct netconn* conn;
static void
ws_server_task (void *pvParameters)
{
struct netconn *conn;
xwebsocket_mutex = xSemaphoreCreateMutex();
xwebsocket_queue = xQueueCreate(WEBSOCKET_SERVER_QUEUE_SIZE, sizeof(struct netconn*));
xwebsocket_mutex = xSemaphoreCreateMutex ();
xwebsocket_queue
= xQueueCreate (WEBSOCKET_SERVER_QUEUE_SIZE, sizeof (struct netconn *));
// initialize all clients
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
clients[i].conn = NULL;
clients[i].url = NULL;
clients[i].ping = 0;
clients[i].last_opcode = 0;
clients[i].contin = NULL;
clients[i].len = 0;
clients[i].ccallback = NULL;
clients[i].scallback = NULL;
}
for(;;) {
xQueueReceive(xwebsocket_queue,&conn,portMAX_DELAY);
if(!conn) continue; // if the connection was NULL, ignore it
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY); // take access
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(clients[i].conn == conn) {
handle_read(i);
break;
}
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
clients[i].conn = NULL;
clients[i].url = NULL;
clients[i].ping = 0;
clients[i].last_opcode = 0;
clients[i].contin = NULL;
clients[i].len = 0;
clients[i].ccallback = NULL;
clients[i].scallback = NULL;
}
xSemaphoreGive(xwebsocket_mutex); // return access
}
vTaskDelete(NULL);
for (;;)
{
xQueueReceive (xwebsocket_queue, &conn, portMAX_DELAY);
if (!conn)
continue; // if the connection was NULL, ignore it
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY); // take access
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (clients[i].conn == conn)
{
handle_read (i);
break;
}
}
xSemaphoreGive (xwebsocket_mutex); // return access
}
vTaskDelete (NULL);
}
int ws_server_start() {
if(xtask) return 0;
#if WEBSOCKET_SERVER_PINNED
xTaskCreatePinnedToCore(&ws_server_task,
"ws_server_task",
WEBSOCKET_SERVER_TASK_STACK_DEPTH,
NULL,
WEBSOCKET_SERVER_TASK_PRIORITY,
&xtask,
WEBSOCKET_SERVER_PINNED_CORE);
#else
xTaskCreate(&ws_server_task,
"ws_server_task",
WEBSOCKET_SERVER_TASK_STACK_DEPTH,
NULL,
WEBSOCKET_SERVER_TASK_PRIORITY,
&xtask);
#endif
int
ws_server_start ()
{
if (xtask)
return 0;
#if WEBSOCKET_SERVER_PINNED
xTaskCreatePinnedToCore (&ws_server_task, "ws_server_task",
WEBSOCKET_SERVER_TASK_STACK_DEPTH, NULL,
WEBSOCKET_SERVER_TASK_PRIORITY, &xtask,
WEBSOCKET_SERVER_PINNED_CORE);
#else
xTaskCreate (&ws_server_task, "ws_server_task",
WEBSOCKET_SERVER_TASK_STACK_DEPTH, NULL,
WEBSOCKET_SERVER_TASK_PRIORITY, &xtask);
#endif
return 1;
}
int ws_server_stop() {
if(!xtask) return 0;
vTaskDelete(xtask);
int
ws_server_stop ()
{
if (!xtask)
return 0;
vTaskDelete (xtask);
return 1;
}
static bool prepare_response(char* buf,uint32_t buflen,char* handshake,char* protocol) {
static bool
prepare_response (char *buf, uint32_t buflen, char *handshake, char *protocol)
{
const char WS_HEADER[] = "Upgrade: websocket\r\n";
const char WS_KEY[] = "Sec-WebSocket-Key: ";
const char WS_RSP[] = "HTTP/1.1 101 Switching Protocols\r\n" \
"Upgrade: websocket\r\n" \
"Connection: Upgrade\r\n" \
"Sec-WebSocket-Accept: %s\r\n" \
const char WS_RSP[] = "HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %s\r\n"
"%s\r\n";
char* key_start;
char* key_end;
char* hashed_key;
char *key_start;
char *key_end;
char *hashed_key;
if(!strstr(buf,WS_HEADER)) return 0;
if(!buflen) return 0;
key_start = strstr(buf,WS_KEY);
if(!key_start) return 0;
if (!strstr (buf, WS_HEADER))
return 0;
if (!buflen)
return 0;
key_start = strstr (buf, WS_KEY);
if (!key_start)
return 0;
key_start += 19;
key_end = strstr(key_start,"\r\n");
if(!key_end) return 0;
key_end = strstr (key_start, "\r\n");
if (!key_end)
return 0;
hashed_key = ws_hash_handshake(key_start,key_end-key_start);
if(!hashed_key) return 0;
if(protocol) {
char tmp[256];
sprintf(tmp,WS_RSP,hashed_key,"Sec-WebSocket-Protocol: %s\r\n");
sprintf(handshake,tmp,protocol);
}
else {
sprintf(handshake,WS_RSP,hashed_key,"");
}
free(hashed_key);
hashed_key = ws_hash_handshake (key_start, key_end - key_start);
if (!hashed_key)
return 0;
if (protocol)
{
char tmp[256];
sprintf (tmp, WS_RSP, hashed_key, "Sec-WebSocket-Protocol: %s\r\n");
sprintf (handshake, tmp, protocol);
}
else
{
sprintf (handshake, WS_RSP, hashed_key, "");
}
free (hashed_key);
return 1;
}
int ws_server_add_client_protocol(struct netconn* conn,
char* msg,
uint16_t len,
char* url,
char* protocol,
void (*callback)(uint8_t num,
WEBSOCKET_TYPE_t type,
char* msg,
uint64_t len)) {
int
ws_server_add_client_protocol (struct netconn *conn, char *msg, uint16_t len,
char *url, char *protocol,
void (*callback) (uint8_t num,
WEBSOCKET_TYPE_t type,
char *msg, uint64_t len))
{
int ret;
char handshake[256];
if(!prepare_response(msg,len,handshake,protocol)) {
netconn_close(conn);
netconn_delete(conn);
return -2;
}
if (!prepare_response (msg, len, handshake, protocol))
{
netconn_close (conn);
netconn_delete (conn);
return -2;
}
ret = -1;
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
conn->callback = background_callback;
netconn_write(conn,handshake,strlen(handshake),NETCONN_COPY);
netconn_write (conn, handshake, strlen (handshake), NETCONN_COPY);
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(clients[i].conn) continue;
clients[i] = ws_connect_client(conn,url,NULL,callback);
callback(i,WEBSOCKET_CONNECT,NULL,0);
if(!ws_is_connected(clients[i])) {
callback(i,WEBSOCKET_DISCONNECT_ERROR,NULL,0);
ws_disconnect_client(&clients[i], 0);
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (clients[i].conn)
continue;
clients[i] = ws_connect_client (conn, url, NULL, callback);
callback (i, WEBSOCKET_CONNECT, NULL, 0);
if (!ws_is_connected (clients[i]))
{
callback (i, WEBSOCKET_DISCONNECT_ERROR, NULL, 0);
ws_disconnect_client (&clients[i], 0);
break;
}
ret = i;
break;
}
ret = i;
break;
}
xSemaphoreGive(xwebsocket_mutex);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_len_url(char* url) {
int
ws_server_len_url (char *url)
{
int ret;
ret = 0;
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(clients[i].url && strcmp(url,clients[i].url)) ret++;
}
xSemaphoreGive(xwebsocket_mutex);
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (clients[i].url && strcmp (url, clients[i].url))
ret++;
}
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_add_client(struct netconn* conn,
char* msg,
uint16_t len,
char* url,
void (*callback)(uint8_t num,
WEBSOCKET_TYPE_t type,
char* msg,
uint64_t len)) {
return ws_server_add_client_protocol(conn,msg,len,url,NULL,callback);
int
ws_server_add_client (struct netconn *conn, char *msg, uint16_t len, char *url,
void (*callback) (uint8_t num, WEBSOCKET_TYPE_t type,
char *msg, uint64_t len))
{
return ws_server_add_client_protocol (conn, msg, len, url, NULL, callback);
}
int ws_server_len_all() {
int
ws_server_len_all ()
{
int ret;
ret = 0;
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(clients[i].conn) ret++;
}
xSemaphoreGive(xwebsocket_mutex);
return ret;
}
int ws_server_remove_client(int num) {
int ret = 0;
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
if(ws_is_connected(clients[num])) {
clients[num].scallback(num,WEBSOCKET_DISCONNECT_INTERNAL,NULL,0);
ws_disconnect_client(&clients[num], 0);
ret = 1;
}
xSemaphoreGive(xwebsocket_mutex);
return ret;
}
int ws_server_remove_clients(char* url) {
int ret = 0;
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(ws_is_connected(clients[i]) && strcmp(url,clients[i].url)) {
clients[i].scallback(i,WEBSOCKET_DISCONNECT_INTERNAL,NULL,0);
ws_disconnect_client(&clients[i], 0);
ret += 1;
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (clients[i].conn)
ret++;
}
}
xSemaphoreGive(xwebsocket_mutex);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_remove_all() {
int
ws_server_remove_client (int num)
{
int ret = 0;
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(ws_is_connected(clients[i])) {
clients[i].scallback(i,WEBSOCKET_DISCONNECT_INTERNAL,NULL,0);
ws_disconnect_client(&clients[i], 0);
ret += 1;
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
if (ws_is_connected (clients[num]))
{
clients[num].scallback (num, WEBSOCKET_DISCONNECT_INTERNAL, NULL, 0);
ws_disconnect_client (&clients[num], 0);
ret = 1;
}
}
xSemaphoreGive(xwebsocket_mutex);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int
ws_server_remove_clients (char *url)
{
int ret = 0;
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (ws_is_connected (clients[i]) && strcmp (url, clients[i].url))
{
clients[i].scallback (i, WEBSOCKET_DISCONNECT_INTERNAL, NULL, 0);
ws_disconnect_client (&clients[i], 0);
ret += 1;
}
}
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int
ws_server_remove_all ()
{
int ret = 0;
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (ws_is_connected (clients[i]))
{
clients[i].scallback (i, WEBSOCKET_DISCONNECT_INTERNAL, NULL, 0);
ws_disconnect_client (&clients[i], 0);
ret += 1;
}
}
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
// The following functions are already written below, but without the mutex.
int ws_server_send_text_client(int num,char* msg,uint64_t len) {
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
int ret = ws_server_send_text_client_from_callback(num, msg, len);
xSemaphoreGive(xwebsocket_mutex);
int
ws_server_send_text_client (int num, char *msg, uint64_t len)
{
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
int ret = ws_server_send_text_client_from_callback (num, msg, len);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_send_bin_client(int num,char* msg,uint64_t len) {
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
int ret = ws_server_send_bin_client_from_callback(num, msg, len);
xSemaphoreGive(xwebsocket_mutex);
int
ws_server_send_bin_client (int num, char *msg, uint64_t len)
{
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
int ret = ws_server_send_bin_client_from_callback (num, msg, len);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_send_text_clients(char* url,char* msg,uint64_t len) {
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
int ret = ws_server_send_text_clients_from_callback(url, msg, len);
xSemaphoreGive(xwebsocket_mutex);
int
ws_server_send_text_clients (char *url, char *msg, uint64_t len)
{
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
int ret = ws_server_send_text_clients_from_callback (url, msg, len);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_send_bin_clients(char* url,char* msg,uint64_t len) {
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
int ret = ws_server_send_bin_clients_from_callback(url, msg, len);
xSemaphoreGive(xwebsocket_mutex);
int
ws_server_send_bin_clients (char *url, char *msg, uint64_t len)
{
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
int ret = ws_server_send_bin_clients_from_callback (url, msg, len);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_send_text_all(char* msg,uint64_t len) {
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
int ret = ws_server_send_text_all_from_callback(msg, len);
xSemaphoreGive(xwebsocket_mutex);
int
ws_server_send_text_all (char *msg, uint64_t len)
{
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
int ret = ws_server_send_text_all_from_callback (msg, len);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
int ws_server_send_bin_all(char* msg,uint64_t len) {
xSemaphoreTake(xwebsocket_mutex,portMAX_DELAY);
int ret = ws_server_send_bin_all_from_callback(msg, len);
xSemaphoreGive(xwebsocket_mutex);
int
ws_server_send_bin_all (char *msg, uint64_t len)
{
xSemaphoreTake (xwebsocket_mutex, portMAX_DELAY);
int ret = ws_server_send_bin_all_from_callback (msg, len);
xSemaphoreGive (xwebsocket_mutex);
return ret;
}
// the following functions should be used inside of the callback. The regular versions
// grab the mutex, but it is already grabbed from inside the callback so it will hang.
// the following functions should be used inside of the callback. The regular
// versions grab the mutex, but it is already grabbed from inside the callback
// so it will hang.
int ws_server_send_text_client_from_callback(int num,char* msg,uint64_t len) {
int
ws_server_send_text_client_from_callback (int num, char *msg, uint64_t len)
{
int ret = 0;
int err;
if(ws_is_connected(clients[num])) {
err = ws_send(&clients[num],WEBSOCKET_OPCODE_TEXT,msg,len,0);
ret = 1;
if(err) {
clients[num].scallback(num,WEBSOCKET_DISCONNECT_ERROR,NULL,0);
ws_disconnect_client(&clients[num], 0);
ret = 0;
if (ws_is_connected (clients[num]))
{
err = ws_send (&clients[num], WEBSOCKET_OPCODE_TEXT, msg, len, 0);
ret = 1;
if (err)
{
clients[num].scallback (num, WEBSOCKET_DISCONNECT_ERROR, NULL, 0);
ws_disconnect_client (&clients[num], 0);
ret = 0;
}
}
}
return ret;
}
int ws_server_send_bin_client_from_callback(int num,char* msg,uint64_t len) {
int
ws_server_send_bin_client_from_callback (int num, char *msg, uint64_t len)
{
int ret = 0;
int err;
if(ws_is_connected(clients[num])) {
err = ws_send(&clients[num],WEBSOCKET_OPCODE_BIN,msg,len,0);
ret = 1;
if(err) {
clients[num].scallback(num,WEBSOCKET_DISCONNECT_ERROR,NULL,0);
ws_disconnect_client(&clients[num], 0);
ret = 0;
if (ws_is_connected (clients[num]))
{
err = ws_send (&clients[num], WEBSOCKET_OPCODE_BIN, msg, len, 0);
ret = 1;
if (err)
{
clients[num].scallback (num, WEBSOCKET_DISCONNECT_ERROR, NULL, 0);
ws_disconnect_client (&clients[num], 0);
ret = 0;
}
}
}
return ret;
}
int ws_server_send_text_clients_from_callback(char* url,char* msg,uint64_t len) {
int
ws_server_send_text_clients_from_callback (char *url, char *msg, uint64_t len)
{
int ret = 0;
int err;
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(ws_is_connected(clients[i]) && strcmp(clients[i].url,url)) {
err = ws_send(&clients[i],WEBSOCKET_OPCODE_TEXT,msg,len,0);
if(!err) ret += 1;
else {
clients[i].scallback(i,WEBSOCKET_DISCONNECT_ERROR,NULL,0);
ws_disconnect_client(&clients[i], 0);
}
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (ws_is_connected (clients[i]) && strcmp (clients[i].url, url))
{
err = ws_send (&clients[i], WEBSOCKET_OPCODE_TEXT, msg, len, 0);
if (!err)
ret += 1;
else
{
clients[i].scallback (i, WEBSOCKET_DISCONNECT_ERROR, NULL, 0);
ws_disconnect_client (&clients[i], 0);
}
}
}
}
return ret;
}
int ws_server_send_bin_clients_from_callback(char* url,char* msg,uint64_t len) {
int
ws_server_send_bin_clients_from_callback (char *url, char *msg, uint64_t len)
{
int ret = 0;
int err;
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(ws_is_connected(clients[i]) && strcmp(clients[i].url,url)) {
err = ws_send(&clients[i],WEBSOCKET_OPCODE_BIN,msg,len,0);
if(!err) ret += 1;
else {
clients[i].scallback(i,WEBSOCKET_DISCONNECT_ERROR,NULL,0);
ws_disconnect_client(&clients[i], 0);
}
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (ws_is_connected (clients[i]) && strcmp (clients[i].url, url))
{
err = ws_send (&clients[i], WEBSOCKET_OPCODE_BIN, msg, len, 0);
if (!err)
ret += 1;
else
{
clients[i].scallback (i, WEBSOCKET_DISCONNECT_ERROR, NULL, 0);
ws_disconnect_client (&clients[i], 0);
}
}
}
}
return ret;
}
int ws_server_send_text_all_from_callback(char* msg,uint64_t len) {
int
ws_server_send_text_all_from_callback (char *msg, uint64_t len)
{
int ret = 0;
int err;
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(ws_is_connected(clients[i])) {
err = ws_send(&clients[i],WEBSOCKET_OPCODE_TEXT,msg,len,0);
if(!err) ret += 1;
else {
clients[i].scallback(i,WEBSOCKET_DISCONNECT_ERROR,NULL,0);
ws_disconnect_client(&clients[i], 0);
}
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (ws_is_connected (clients[i]))
{
err = ws_send (&clients[i], WEBSOCKET_OPCODE_TEXT, msg, len, 0);
if (!err)
ret += 1;
else
{
clients[i].scallback (i, WEBSOCKET_DISCONNECT_ERROR, NULL, 0);
ws_disconnect_client (&clients[i], 0);
}
}
}
}
return ret;
}
int ws_server_send_bin_all_from_callback(char* msg,uint64_t len) {
int
ws_server_send_bin_all_from_callback (char *msg, uint64_t len)
{
int ret = 0;
int err;
for(int i=0;i<WEBSOCKET_SERVER_MAX_CLIENTS;i++) {
if(ws_is_connected(clients[i])) {
err = ws_send(&clients[i],WEBSOCKET_OPCODE_BIN,msg,len,0);
if(!err) ret += 1;
else {
clients[i].scallback(i,WEBSOCKET_DISCONNECT_ERROR,NULL,0);
ws_disconnect_client(&clients[i], 0);
}
for (int i = 0; i < WEBSOCKET_SERVER_MAX_CLIENTS; i++)
{
if (ws_is_connected (clients[i]))
{
err = ws_send (&clients[i], WEBSOCKET_OPCODE_BIN, msg, len, 0);
if (!err)
ret += 1;
else
{
clients[i].scallback (i, WEBSOCKET_DISCONNECT_ERROR, NULL, 0);
ws_disconnect_client (&clients[i], 0);
}
}
}
}
return ret;
}

File diff suppressed because it is too large Load Diff