equalizer - release

This commit is contained in:
Philippe G
2020-04-17 08:03:17 -07:00
parent 7e4c0d2ac4
commit 394d6b6465
17 changed files with 283 additions and 9 deletions

View File

@@ -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

View 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

View 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

Binary file not shown.

View File

@@ -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

View 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);
}
}

View 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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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');

View File

@@ -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>

View File

@@ -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

View File

@@ -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>