mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-06 19:47:02 +03:00
equalizer - release
This commit is contained in:
@@ -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
|
||||
|
||||
10
components/audio/component.mk
Normal file
10
components/audio/component.mk
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
78
components/audio/inc/esp_equalizer.h
Normal file
78
components/audio/inc/esp_equalizer.h
Normal file
@@ -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
|
||||
BIN
components/audio/lib/libesp_processing.a
Normal file
BIN
components/audio/lib/libesp_processing.a
Normal file
Binary file not shown.
@@ -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
|
||||
|
||||
|
||||
89
components/squeezelite/equalizer.c
Normal file
89
components/squeezelite/equalizer.c
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
26
components/squeezelite/equalizer.h
Normal file
26
components/squeezelite/equalizer.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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);
|
||||
@@ -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,
|
||||
@@ -156,6 +158,8 @@ int32_t output_bt_data(uint8_t *data, int32_t len) {
|
||||
}
|
||||
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);
|
||||
SET_MIN_MAX((len-wanted_len), rec);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Binary file not shown.
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
<name>PLUGIN_SQUEEZEESP32</name>
|
||||
<description>PLUGIN_SQUEEZEESP32_DESC</description>
|
||||
<module>Plugins::SqueezeESP32::Plugin</module>
|
||||
<version>0.72</version>
|
||||
<version>0.80</version>
|
||||
<creator>Philippe</creator>
|
||||
</extensions>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version='1.0' standalone='yes'?>
|
||||
<extensions>
|
||||
<plugins>
|
||||
<plugin version="0.72" name="SqueezeESP32" minTarget="7.5" maxTarget="*">
|
||||
<plugin version="0.80" name="SqueezeESP32" minTarget="7.5" maxTarget="*">
|
||||
<link>https://github.com/sle118/squeezelite-esp32</link>
|
||||
<creator>Philippe</creator>
|
||||
<sha>50679aff5e938359342d3a4d8251dcd25fab3eff</sha>
|
||||
<sha>91e29c4380ce11728692f1cdabab080d1924a8d3</sha>
|
||||
<email>philippe_44@outlook.com</email>
|
||||
<desc lang="EN">SqueezeESP32 additional player id (100)</desc>
|
||||
<url>http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip</url>
|
||||
|
||||
Reference in New Issue
Block a user