diff --git a/README.md b/README.md
index 8ff7d61a..7b86caa4 100644
--- a/README.md
+++ b/README.md
@@ -330,6 +330,7 @@ See squeezlite command line, but keys options are
- per mad & few others, edit configure and change $ac_link to add -c (faking link)
- change ac_files to remove ''
- add DEPS_CFLAGS and DEPS_LIBS to avoid pkg-config to be required
+ - stack consumption can be very high with some codec variants, so set NONTHREADSAFE_PSEUDOSTACK and GLOBAL_STACK_SIZE=32000 and unset VAR_ARRAYS in config.h
- better use helixaac
- set IDF_PATH=/home/esp-idf
- set ESPPORT=COM9
diff --git a/components/audio/component.mk b/components/audio/component.mk
new file mode 100644
index 00000000..3d8e364d
--- /dev/null
+++ b/components/audio/component.mk
@@ -0,0 +1,10 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
+COMPONENT_ADD_LDFLAGS=-l$(COMPONENT_NAME) \
+ $(COMPONENT_PATH)/lib/libesp_processing.a
+
+
+
+
diff --git a/components/audio/inc/esp_equalizer.h b/components/audio/inc/esp_equalizer.h
new file mode 100644
index 00000000..e1f815d1
--- /dev/null
+++ b/components/audio/inc/esp_equalizer.h
@@ -0,0 +1,78 @@
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+// All rights reserved.
+
+#ifndef _ESP_EQUALIZER_H
+#define _ESP_EQUALIZER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+* @brief Initialize the equalizer handle
+*
+* @param nch The audio channel number
+* @param g_rate The audio sample rate. Four sample rates are supported: 11025Hz, 22050Hz, 44100Hz and 48000Hz.
+* @param n_band The number of audio sub-bands. Fixed number of 10 sub-bands is supported and this value should be set to 10.
+* @param use_xmms_original_freqs Currently should be set 0
+*
+* @return The equalizer handle.
+*/
+void *esp_equalizer_init(int nch, int g_rate, int n_band, int use_xmms_original_freqs);
+
+/**
+* @brief Uninitialize the equalizer handle.
+*
+* @param handle The the equalizer handle
+*/
+void esp_equalizer_uninit(void *handle);
+
+/**
+* @brief Process the data through the equalizer
+*
+* @param handle The the equalizer handle
+* @param pcm_buf The audio pcm input & output buffer
+* @param length The length of current bytes in pcm_buf
+* @param g_rate The audio sample rate. Four sample rates are supported: 11025Hz, 22050Hz, 44100Hz and 48000Hz.
+* @param nch The audio channel number
+*
+* @return Length of pcm_buf after processing
+*/
+int esp_equalizer_process(void *handle, unsigned char *pcm_buf, int length, int g_rate, int nch);
+
+/**
+* @brief Set the number of sub-bands for the equalizer
+*
+* @param handle The the equalizer handle
+* @param value The audio sub-bands gain. unit:db. 0 means no gain.
+* @param index The index of audio sub-bands. e.g. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
+* @param nch The audio channel number
+*/
+void esp_equalizer_set_band_value(void *handle, float value, int index, int nch);
+
+/**
+* @brief Get the number of the equalizer sub-bands
+*
+* @param handle The the equalizer handle
+*
+* @return The number of the equalizer sub-bands
+*/
+int esp_equalizer_get_band_count(void *handle);
+
+/**
+* @brief Get the value of the equalizer sub-bands
+*
+* @param handle The the equalizer handle
+* @param index The index of audio sub-bands. Currently only support 10 sub-bands, so it should be 0-9.
+* @param nch The audio channel number
+*
+* @return The number of the equalizer sub-bands
+*/
+float esp_equalizer_get_band_value(void *handle, int index, int nch);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/components/audio/lib/libesp_processing.a b/components/audio/lib/libesp_processing.a
new file mode 100644
index 00000000..df02f06a
Binary files /dev/null and b/components/audio/lib/libesp_processing.a differ
diff --git a/components/squeezelite/component.mk b/components/squeezelite/component.mk
index 16d89dcf..c6c4d5f1 100644
--- a/components/squeezelite/component.mk
+++ b/components/squeezelite/component.mk
@@ -15,7 +15,8 @@ CFLAGS += -O3 -DLINKALL -DLOOPBACK -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DTREMOR_ON
-I$(COMPONENT_PATH)/../codecs/inc/opusfile \
-I$(COMPONENT_PATH)/../driver_bt \
-I$(COMPONENT_PATH)/../raop \
- -I$(COMPONENT_PATH)/../services
+ -I$(COMPONENT_PATH)/../services \
+ -I$(COMPONENT_PATH)/../audio/inc
# -I$(COMPONENT_PATH)/../codecs/inc/faad2
diff --git a/components/squeezelite/equalizer.c b/components/squeezelite/equalizer.c
new file mode 100644
index 00000000..3a5517fc
--- /dev/null
+++ b/components/squeezelite/equalizer.c
@@ -0,0 +1,89 @@
+/*
+ * Squeezelite for esp32
+ *
+ * (c) Philippe G. 2020, philippe_44@outlook.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "squeezelite.h"
+#include "equalizer.h"
+#include "esp_equalizer.h"
+
+#define EQ_BANDS 10
+
+static log_level loglevel = lINFO;
+
+static struct {
+ void *handle;
+ float gain[EQ_BANDS];
+ bool update;
+} equalizer = { .update = true };
+
+/****************************************************************************************
+ * open equalizer
+ */
+void equalizer_open(u32_t sample_rate) {
+ if (sample_rate != 11025 && sample_rate != 22050 && sample_rate != 44100 && sample_rate != 48000) {
+ LOG_WARN("equalizer only supports 11025, 22050, 44100 and 48000 sample rates, not %u", sample_rate);
+ return;
+ }
+
+ equalizer.handle = esp_equalizer_init(2, sample_rate, EQ_BANDS, 0);
+ equalizer.update = false;
+
+ if (equalizer.handle) {
+ LOG_INFO("equalizer initialized");
+ for (int i = 0; i < EQ_BANDS; i++) {
+ esp_equalizer_set_band_value(equalizer.handle, equalizer.gain[i], i, 0);
+ esp_equalizer_set_band_value(equalizer.handle, equalizer.gain[i], i, 1);
+ }
+ } else {
+ LOG_WARN("can't init equalizer");
+ }
+}
+
+/****************************************************************************************
+ * close equalizer
+ */
+void equalizer_close(void) {
+ if (equalizer.handle) {
+ esp_equalizer_uninit(equalizer.handle);
+ equalizer.handle = NULL;
+ }
+}
+
+/****************************************************************************************
+ * update equalizer gain
+ */
+void equalizer_update(s8_t *gain) {
+ for (int i = 0; i < EQ_BANDS; i++) equalizer.gain[i] = gain[i];
+ equalizer.update = true;
+}
+
+/****************************************************************************************
+ * process equalizer
+ */
+void equalizer_process(u8_t *buf, u32_t bytes, u32_t sample_rate) {
+ // don't want to process with output locked, so tak ethe small risk to miss one parametric update
+ if (equalizer.update) {
+ equalizer_close();
+ equalizer_open(sample_rate);
+ }
+
+ if (equalizer.handle) {
+ esp_equalizer_process(equalizer.handle, buf, bytes, sample_rate, 2);
+ }
+}
\ No newline at end of file
diff --git a/components/squeezelite/equalizer.h b/components/squeezelite/equalizer.h
new file mode 100644
index 00000000..c67ac328
--- /dev/null
+++ b/components/squeezelite/equalizer.h
@@ -0,0 +1,26 @@
+/*
+ * Squeezelite for esp32
+ *
+ * (c) Philippe G. 2020, philippe_44@outlook.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#pragma once
+
+void equalizer_open(u32_t sample_rate);
+void equalizer_close(void);
+void equalizer_update(s8_t *gain);
+void equalizer_process(u8_t *buf, u32_t bytes, u32_t sample_rate);
diff --git a/components/squeezelite/output_bt.c b/components/squeezelite/output_bt.c
index 72cf6d39..2def7c9c 100644
--- a/components/squeezelite/output_bt.c
+++ b/components/squeezelite/output_bt.c
@@ -21,6 +21,7 @@
#include "driver/gpio.h"
#include "squeezelite.h"
+#include "equalizer.h"
#include "perf_trace.h"
#include "config.h"
@@ -84,6 +85,7 @@ void output_close_bt(void) {
running = false;
UNLOCK;
hal_bluetooth_stop();
+ equalizer_close();
}
static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
@@ -155,6 +157,8 @@ int32_t output_bt_data(uint8_t *data, int32_t len) {
SET_MIN_MAX(wanted_len, under);
}
output.frames_in_process = len-wanted_len;
+
+ equalizer_process(data, (len - wanted_len) * BYTES_PER_FRAME, output.current_sample_rate);
UNLOCK;
SET_MIN_MAX(TIME_MEASUREMENT_GET(start_timer),lock_out_time);
diff --git a/components/squeezelite/output_embedded.c b/components/squeezelite/output_embedded.c
index cfd1a544..d66e2284 100644
--- a/components/squeezelite/output_embedded.c
+++ b/components/squeezelite/output_embedded.c
@@ -19,10 +19,13 @@
*
*/
#include "squeezelite.h"
+#include "equalizer.h"
extern struct outputstate output;
extern struct buffer *outputbuf;
+static bool (*slimp_handler_chain)(u8_t *data, int len);
+
#define FRAME_BLOCK MAX_SILENCE_FRAMES
#define LOCK mutex_lock(outputbuf->mutex)
@@ -47,11 +50,39 @@ static log_level loglevel;
static bool (*volume_cb)(unsigned left, unsigned right);
static void (*close_cb)(void);
+#pragma pack(push, 1)
+struct eqlz_packet {
+ char opcode[4];
+};
+#pragma pack(pop)
+
+static bool handler(u8_t *data, int len){
+ bool res = true;
+
+ if (!strncmp((char*) data, "eqlz", 4)) {
+ s8_t *gain = (s8_t*) (data + sizeof(struct eqlz_packet));
+ LOG_INFO("got equalizer %d", len);
+ // update will be done at next opportunity
+ equalizer_update(gain);
+ } else {
+ res = false;
+ }
+
+ // chain protocol handlers (bitwise or is fine)
+ if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len);
+
+ return res;
+}
+
void output_init_embedded(log_level level, char *device, unsigned output_buf_size, char *params,
unsigned rates[], unsigned rate_delay, unsigned idle) {
loglevel = level;
LOG_INFO("init device: %s", device);
+ // chain handlers
+ slimp_handler_chain = slimp_handler;
+ slimp_handler = handler;
+
memset(&output, 0, sizeof(output));
output_init_common(level, device, output_buf_size, rates, idle);
output.start_frames = FRAME_BLOCK;
diff --git a/components/squeezelite/output_i2s.c b/components/squeezelite/output_i2s.c
index a56ee7fe..e57a6abf 100644
--- a/components/squeezelite/output_i2s.c
+++ b/components/squeezelite/output_i2s.c
@@ -53,6 +53,7 @@ sure that using rate_delay would fix that
#include "monitor.h"
#include "config.h"
#include "accessors.h"
+#include "equalizer.h"
#include "globdefs.h"
#define LOCK mutex_lock(outputbuf->mutex)
@@ -137,7 +138,7 @@ static void jack_handler(bool inserted) {
/****************************************************************************************
* amp GPIO
*/
-void set_amp_gpio(int gpio, char *value) {
+static void set_amp_gpio(int gpio, char *value) {
if (!strcasecmp(value, "amp")) {
amp_gpio = gpio;
@@ -314,6 +315,8 @@ void output_close_i2s(void) {
i2s_driver_uninstall(CONFIG_I2S_NUM);
free(obuf);
+ equalizer_close();
+
adac->deinit();
}
@@ -483,9 +486,15 @@ static void *output_thread_i2s(void *arg) {
i2s_config.sample_rate = output.current_sample_rate;
i2s_set_sample_rates(CONFIG_I2S_NUM, spdif ? i2s_config.sample_rate * 2 : i2s_config.sample_rate);
i2s_zero_dma_buffer(CONFIG_I2S_NUM);
+
+ equalizer_close();
+ equalizer_open(output.current_sample_rate);
//return;
}
+ // run equalizer
+ equalizer_process(obuf, oframes * bytes_per_frame, output.current_sample_rate);
+
// we assume that here we have been able to entirely fill the DMA buffers
if (spdif) {
spdif_convert((ISAMPLE_T*) obuf, oframes, (u32_t*) sbuf, &count);
diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip
index 329291ce..605a0139 100644
Binary files a/plugin/SqueezeESP32.zip and b/plugin/SqueezeESP32.zip differ
diff --git a/plugin/SqueezeESP32/Player.pm b/plugin/SqueezeESP32/Player.pm
index 7e638201..a2024151 100644
--- a/plugin/SqueezeESP32/Player.pm
+++ b/plugin/SqueezeESP32/Player.pm
@@ -15,6 +15,12 @@ sub hasIR { 0 }
sub init {
my $client = shift;
+
+ $prefs->client($client)->init( {
+ eq => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ }
+ );
+
$client->SUPER::init(@_);
Plugins::SqueezeESP32::Plugin::config_artwork($client);
}
@@ -55,6 +61,7 @@ sub reconnect {
my $client = shift;
$client->pluginData('artwork_md5', '');
$client->SUPER::reconnect(@_);
+ Plugins::SqueezeESP32::Plugin::send_equalizer($client);
}
1;
diff --git a/plugin/SqueezeESP32/PlayerSettings.pm b/plugin/SqueezeESP32/PlayerSettings.pm
index ce41c608..86bc1929 100644
--- a/plugin/SqueezeESP32/PlayerSettings.pm
+++ b/plugin/SqueezeESP32/PlayerSettings.pm
@@ -30,7 +30,7 @@ sub page {
sub prefs {
my ($class, $client) = @_;
- my @prefs = qw(width small_VU spectrum artwork);
+ my @prefs = qw(width small_VU spectrum artwork eq);
return ($prefs->client($client), @prefs);
}
@@ -55,6 +55,13 @@ sub handler {
$client->display->modes($client->display->build_modes);
$client->display->update;
+ my $eq = $cprefs->get('eq');
+ for my $i (0 .. $#{$eq}) {
+ $eq->[$i] = $paramRef->{"pref_eq.$i"};
+ }
+ $cprefs->set('eq', $eq);
+ Plugins::SqueezeESP32::Plugin::send_equalizer($client);
+
# force update or disable artwork
if ($artwork->{'enable'}) {
Plugins::SqueezeESP32::Plugin::update_artwork($client, 1);
@@ -72,6 +79,7 @@ sub handler {
# logic of "Settings" is beyond me and I really hate it
$paramRef->{'pref_spectrum'} = $cprefs->get('spectrum');
$paramRef->{'pref_artwork'} = $cprefs->get('artwork');
+ $paramRef->{'pref_eq'} = $cprefs->get('eq');
return $class->SUPER::handler($client, $paramRef);
}
diff --git a/plugin/SqueezeESP32/Plugin.pm b/plugin/SqueezeESP32/Plugin.pm
index dd9aee47..3c2ad5b5 100644
--- a/plugin/SqueezeESP32/Plugin.pm
+++ b/plugin/SqueezeESP32/Plugin.pm
@@ -56,8 +56,6 @@ sub onNotification {
my $client = $request->client;
my $reqstr = $request->getRequestString();
- $log->info("artwork update notification $reqstr");
- #my $path = $request->getParam('_path');
update_artwork($client);
}
@@ -108,6 +106,14 @@ sub send_artwork {
}
}
+sub send_equalizer {
+ my ($client) = @_;
+ my $equalizer = $prefs->client($client)->get('eq');
+ my $size = @$equalizer;
+ my $data = pack("c[$size]", @{$equalizer});
+ $client->sendFrame( eqlz => \$data );
+}
+
sub config_artwork {
my ($client) = @_;
my $artwork = $prefs->client($client)->get('artwork');
diff --git a/plugin/SqueezeESP32/install.xml b/plugin/SqueezeESP32/install.xml
index f1dbce20..2126e68f 100644
--- a/plugin/SqueezeESP32/install.xml
+++ b/plugin/SqueezeESP32/install.xml
@@ -10,6 +10,6 @@
PLUGIN_SQUEEZEESP32PLUGIN_SQUEEZEESP32_DESCPlugins::SqueezeESP32::Plugin
- 0.72
+ 0.80Philippe
diff --git a/plugin/SqueezeESP32/strings.txt b/plugin/SqueezeESP32/strings.txt
index d5ed82c2..5c03547c 100644
--- a/plugin/SqueezeESP32/strings.txt
+++ b/plugin/SqueezeESP32/strings.txt
@@ -14,7 +14,7 @@ PLUGIN_SQUEEZEESP32_DESC
EN Adds a new player id (100) to enable display with SqueezeESP32
PLUGIN_SQUEEZEESP32_PLAYERSETTINGS
- EN Display (ESP32)
+ EN ESP32 settings
PLUGIN_SQUEEZEESP32_WIDTH
EN Screen width
@@ -69,3 +69,7 @@ PLUGIN_SQUEEZEESP32_ARTWORK_X
PLUGIN_SQUEEZEESP32_ARTWORK_Y
EN Y
+
+PLUGIN_SQUEEZEESP32_EQUALIZER
+ EN Parametric equalizer
+
diff --git a/plugin/repo.xml b/plugin/repo.xml
index ffb006d5..36a5ec2f 100644
--- a/plugin/repo.xml
+++ b/plugin/repo.xml
@@ -1,10 +1,10 @@
-
+
https://github.com/sle118/squeezelite-esp32
Philippe
- 50679aff5e938359342d3a4d8251dcd25fab3eff
+ 91e29c4380ce11728692f1cdabab080d1924a8d3philippe_44@outlook.comSqueezeESP32 additional player id (100)http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip