Adding Volume Control either digitally or using analog input
markirwin opened this issue · 1 comments
markirwin commented
I am attempting to use a potentiometer to add analog volume control to the i2s play back by modifying the play function like below however this is causing the esp32 to panic do you have a better idea of how this could be implemented digitally?:
void play(Output *output, const char *fname)
{
int16_t *samples = (int16_t *)malloc(sizeof(int16_t) * 1024);
// open the file on the sdcard
FILE *fp = fopen(fname, "rb");
// create a new wave file writer
WAVFileReader *reader = new WAVFileReader(fp);
ESP_LOGI(TAG, "Start playing");
output->start(reader->sample_rate());
ESP_LOGI(TAG, "Opened wav file");
// read until theres no more samples
int16_t samples_read_signed;
uint16_t i;
while (true)
{
int16_t samples_read = reader->read(samples, 1024);
if (samples_read == 0)
{
break;
}
Volume = float(analogRead(PIN_VOL_ADC)) / 2047;
for(i=0;i<samples_read;i+=2) // We step 2 bytes at a time as we're using 16bits per channel
{
samples_read_signed=*((int16_t *)(samples_read+i)); // Get the Byte address, convert to an int pointer, then get contents of that address as an int
samples_read_signed=samples_read_signed*Volume; // multiply by the volume - a value that will be between 0 and 1, 1 would be full vol
*((int16_t *)(samples_read+i))=samples_read_signed; // Store back in the memory location we got the sample from
}
ESP_LOGI(TAG, "Read %d samples", samples_read);
output->write(samples, samples_read);
ESP_LOGI(TAG, "Played samples");
}
// stop the input
output->stop();
fclose(fp);
delete reader;
free(samples);
ESP_LOGI(TAG, "Finished playing");
}
cgreening commented
Try adding this line to your platformio.ini
it will switch on exception decoding and should give you a better idea of what's going wrong with the code:
monitor_filters = esp32_exception_decoder
But, you will kick yourself. You are currently trying to use samples_read
as if it were the buffer of samples - but it's the count of how many samples were read. You shouldn't need to do any casting as the samples buffer is already a pointer int16_t
for(int i = 0; i<samples_read; i++) {
samples[i] = samples[i] * volume;
}