Hi,
Below is some scraps of code that we use to control the volume in software. Note that this is hardcoded to use 32 bits audio. You can apply the same technique on 16 bits as well, but then you will be loose some dynamic range.
Code: Select all
#include <string.h>
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "audio_element.h"
#include "audio_event_iface.h"
#include "audio_mem.h"
#include "audio_common.h"
#define ENVELOPE_FILTER_BUFFER_SIZE (1764)
static esp_err_t envelope_filter_destroy(audio_element_handle_t self) {
return ESP_OK;
}
static esp_err_t envelope_filter_open(audio_element_handle_t self) {
return ESP_OK;
}
static esp_err_t envelope_filter_close(audio_element_handle_t self) {
if (audio_element_get_state(self) != AEL_STATE_PAUSED) {
audio_element_info_t info = {0};
audio_element_getinfo(self, &info);
info.byte_pos = 0;
audio_element_setinfo(self, &info);
}
return ESP_OK;
}
static double currentVolume = 0.2;
void envelope_volume_to(double volume) {
currentVolume = volume
}
static void apply_envelope(void *buffer, int size) {
// assume 32 bit samples:
int32_t *samples = buffer;
size_t count = size / 4;
for (size_t i = 0; i < count; i++) {
samples[i] = samples[i] * currentVolume;
}
}
static int envelope_filter_process(audio_element_handle_t self, char *buffer, int size)
{
audio_element_info_t info = { 0 };
audio_element_getinfo(self, &info);
int size_read = audio_element_input(self, buffer, size);
int result = size_read; // Could be negative error code
if (size_read > 0) {
apply_envelope(buffer, size_read);
int size_write = audio_element_output(self, buffer, size_read);
if (size_write > 0) {
info.byte_pos += size_write;
}
result = size_write;
}
audio_element_setinfo(self, &info);
return result;
}
audio_element_handle_t create_envelope_filter() {
audio_element_cfg_t cfg = DEFAULT_AUDIO_ELEMENT_CONFIG();
cfg.process = envelope_filter_process;
cfg.open = envelope_filter_open;
cfg.close = envelope_filter_close;
cfg.destroy = envelope_filter_destroy;
cfg.buffer_len = ENVELOPE_FILTER_BUFFER_SIZE;
cfg.tag = "volume";
cfg.task_prio = 5;
cfg.task_core = 0;
cfg.out_rb_size = 3 * ENVELOPE_FILTER_BUFFER_SIZE;
audio_element_handle_t el = audio_element_init(&cfg);
mem_assert(el);
audio_element_info_t info = {0};
audio_element_setinfo(el, &info);
return el;
}
To use it you need to create the audio element, register it with the pipeline and link it up.