How to control sound volume through software?

__vnv__
Posts: 17
Joined: Sat Feb 16, 2019 9:42 pm

How to control sound volume through software?

Postby __vnv__ » Thu Mar 21, 2019 8:44 am

Hello everyone,

using example from ESP32 ADF repo (element_sdcard_mp3_example) with UDA1334A [1] I am playing mp3 on my headphones but I cannot control volume. Is there somehow a way to control volume through software?





[1] https://www.google.com/url?sa=i&source= ... 4116035981

Superkurt
Posts: 15
Joined: Thu Mar 03, 2016 11:38 pm

Re: How to control sound volume through software?

Postby Superkurt » Sun Mar 24, 2019 12:26 am

I also didn't find a solution. Could we use the equalizer features?

https://docs.espressif.com/projects/esp ... lizer.html

__vnv__
Posts: 17
Joined: Sat Feb 16, 2019 9:42 pm

Re: How to control sound volume through software?

Postby __vnv__ » Sun Mar 24, 2019 11:40 am

I have researched through equalizer code but didn't find if this would be possible.
Could someone from ESP32 team answer this please, does such a feature exists?

hallgrim
Posts: 4
Joined: Fri Nov 30, 2018 10:35 am

Re: How to control sound volume through software?

Postby hallgrim » Fri Mar 29, 2019 9:59 pm

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.

Who is online

Users browsing this forum: No registered users and 8 guests