mirror of
https://github.com/pschatzmann/arduino-audio-tools.git
synced 2024-09-22 10:57:31 +00:00
AnalogAudio corrections
This commit is contained in:
parent
33493201c8
commit
0e6b930877
44
examples/streams-analog-I2S/README.md
Normal file
44
examples/streams-analog-I2S/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
# Stream Analog Input to I2S
|
||||
|
||||
## General Description:
|
||||
|
||||
In this sketch we get the data from via the ESP32 I2S ADC and send it to I2S
|
||||
Since the ADC via I2S is using the i2s port 0, we use port 1 for the output.
|
||||
|
||||
### Analog Input:
|
||||
|
||||
| ADC | ESP32
|
||||
| --------| ---------------
|
||||
| GND | GND
|
||||
| Left | GPIO34
|
||||
| Right | GPIO35
|
||||
|
||||
|
||||
### External DAC:
|
||||
|
||||
![DAC](https://pschatzmann.github.io/arduino-audio-tools/resources/dac.jpeg)
|
||||
|
||||
For my tests I am using the 24-bit PCM5102 PCM5102A Stereo DAC Digital-to-analog Converter PLL Voice Module pHAT
|
||||
|
||||
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
|
||||
|
||||
|
||||
| DAC | ESP32
|
||||
| --------| ---------------
|
||||
| VDD | 5V
|
||||
| GND | GND
|
||||
| SD | OUT (GPIO22)
|
||||
| L/R | GND
|
||||
| WS | WS (GPIO15)
|
||||
| SCK | BCK (GPIO14)
|
||||
| FMT | GND
|
||||
| XSMT | GPIO23
|
||||
|
||||
|
||||
- DEMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
|
||||
- FLT - Filter select : Normal latency (Low) / Low latency (High)
|
||||
- SCK - System clock input (probably SCL on your board).
|
||||
- FMT - Audio format selection : I2S (Low) / Left justified (High)
|
||||
- XSMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)
|
||||
|
43
examples/streams-analog-I2S/streams-analog-I2S.ino
Normal file
43
examples/streams-analog-I2S/streams-analog-I2S.ino
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file streams-analog-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/streams-analog-i2s/README.md
|
||||
*
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "AudioTools.h"
|
||||
|
||||
using namespace audio_tools;
|
||||
|
||||
const uint16_t sample_rate = 44100;
|
||||
AnalogAudioStream in;
|
||||
I2SStream out;
|
||||
StreamCopy copier(out, in); // copy i2sStream to a2dpStream
|
||||
ConverterAutoCenter<int16_t> converter;
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// RX automatically uses port 0 with pins GPIO34,GPIO35
|
||||
auto cfgRx = in.defaultConfig(RX_MODE);
|
||||
cfgRx.sample_rate = sample_rate;
|
||||
in.begin(cfgRx);
|
||||
|
||||
// TX on I2S_NUM_1
|
||||
auto cfgTx = out.defaultConfig(TX_MODE);
|
||||
cfgTx.port_no = 1;
|
||||
cfgTx.sample_rate = sample_rate;
|
||||
out.begin(cfgTx);
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop - copy data
|
||||
void loop() {
|
||||
copier.copy(converter);
|
||||
}
|
19
examples/streams-analog-serial/README.md
Normal file
19
examples/streams-analog-serial/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
# Stream Analog Input to Serial Output
|
||||
|
||||
## General Description:
|
||||
|
||||
In this sketch we get the data from via the ESP32 I2S ADC and send it to the Plotter
|
||||
Since the ADC via I2S is using the i2s port 0 with the pins GPIO34 and GPIO35.
|
||||
|
||||
The ACD provides values centered around 24576 but we want to make sure that the average of the singal is around 0, so we use the ConverterAutoCenter.
|
||||
|
||||
### Analog Input:
|
||||
|
||||
| ADC | ESP32
|
||||
| --------| ---------------
|
||||
| GND | GND
|
||||
| Left | GPIO34
|
||||
| Right | GPIO35
|
||||
|
||||
|
41
examples/streams-analog-serial/streams-analog-serial.ino
Normal file
41
examples/streams-analog-serial/streams-analog-serial.ino
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file streams-analog-serial.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/streams-analog-serial/README.md
|
||||
*
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "AudioTools.h"
|
||||
|
||||
using namespace audio_tools;
|
||||
|
||||
const uint16_t sample_rate = 44100;
|
||||
const uint8_t channels = 2;
|
||||
AnalogAudioStream in;
|
||||
CsvStream<int16_t> out(Serial, channels); // ASCII output stream
|
||||
StreamCopy copier(out, in); // copy i2sStream to a2dpStream
|
||||
ConverterAutoCenter<int16_t> center; // set avg to 0
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// RX automatically uses port 0 with pins GPIO34,GPIO35
|
||||
auto cfgRx = in.defaultConfig(RX_MODE);
|
||||
cfgRx.sample_rate = sample_rate;
|
||||
in.begin(cfgRx);
|
||||
|
||||
// open output
|
||||
out.begin();
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop - copy data
|
||||
void loop() {
|
||||
copier.copy(center);
|
||||
}
|
@ -8,3 +8,21 @@ Currently we provide multiple mp3 decoders
|
||||
|
||||
Unfortunatly non of those are currently stable in all environments....
|
||||
|
||||
### Output Device: Piezo Electric Element
|
||||
|
||||
To test the output I am using piezo electric elements
|
||||
|
||||
![DAC](https://pschatzmann.github.io/arduino-audio-tools/resources/piezo.jpeg)
|
||||
|
||||
It should also be possible to connect a headphone to the output pins.
|
||||
|
||||
|
||||
| PIEZO Left | ESP32
|
||||
| ------------| --------------
|
||||
| + | GPIO25
|
||||
| - | GND
|
||||
|
||||
| PIEZO2 Rigt | ESP32
|
||||
| ------------| --------------
|
||||
| + | GPIO26
|
||||
| - | GND
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Decoding a MP3 file
|
||||
|
||||
In this example we decode a MP3 file into RAW output and send it the analog output pins.
|
||||
In this example we decode a MP3 file into RAW output and write the output with the help of a PWM signal to the pins.
|
||||
|
||||
Currently we provide multiple mp3 decoders
|
||||
- libhelix
|
||||
@ -8,3 +8,22 @@ Currently we provide multiple mp3 decoders
|
||||
|
||||
Unfortunatly non of those are currently stable in all environments....
|
||||
|
||||
|
||||
### Output Device: Earphone
|
||||
|
||||
To test the output I am using an earphone from a mobile phone.
|
||||
We get 2 signals one for the left and the other for the right channel.
|
||||
|
||||
![DAC](https://pschatzmann.github.io/arduino-audio-tools/resources/earphones.jpg)
|
||||
|
||||
|
||||
The pins depend on the Processor:
|
||||
|
||||
|
||||
| EarPhone | ESP32 | RPI Pico | MBED |
|
||||
| -----------| -------------|---------------|--------------|
|
||||
| Left | GPI2 | GPI2 | GPI2 |
|
||||
| Right | GPI3 | GPIO3 | GPI3 |
|
||||
| GND | GND | GND | GND |
|
||||
|
||||
To verify check the PWM_START_PIN in AudioConfig.h or you can set the pins by calling setPins() method on the PWMConfig object.
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "AudioAnalog/ESP32AnalogAudio.h"
|
||||
#include "AudioAnalog/AnalogAudioESP32.h"
|
||||
|
||||
|
||||
|
||||
|
@ -41,9 +41,9 @@ class AnalogConfig : public AudioBaseInfo {
|
||||
RxTxMode mode;
|
||||
int dma_buf_count = I2S_BUFFER_COUNT;
|
||||
int dma_buf_len = I2S_BUFFER_SIZE;
|
||||
bool use_apll = false;
|
||||
int mode_internal;
|
||||
i2s_port_t i2s_port = I2S_NUM_0; // Analog input only supports 0!
|
||||
int port_no = I2S_NUM_0; // Analog input and output only supports 0!
|
||||
bool use_apll = false;
|
||||
|
||||
AnalogConfig() {
|
||||
sample_rate = 44100;
|
||||
@ -85,13 +85,13 @@ class AnalogConfig : public AudioBaseInfo {
|
||||
void logInfo() {
|
||||
AudioBaseInfo::logInfo();
|
||||
if (mode == TX_MODE){
|
||||
//int pin1, pin2;
|
||||
//dac_pad_get_io_num(DAC_CHANNEL_1, pin1);
|
||||
//dac_pad_get_io_num(DAC_CHANNEL_2, pin2);
|
||||
LOGI("analog left output pin: %d", 25);
|
||||
LOGI("analog right output pin: %d", 26);
|
||||
} else {
|
||||
LOGI("input pin: %d", adc_pin);
|
||||
LOGI("input pin1: %d", adc_pin[0]);
|
||||
if (channels==2){
|
||||
LOGI("input pin2: %d", adc_pin[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,35 +106,35 @@ class AnalogConfig : public AudioBaseInfo {
|
||||
this->adc_pin[channelIdx] = gpio;
|
||||
switch(gpio){
|
||||
case 32:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO32_CHANNEL;
|
||||
break;
|
||||
case 33:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO33_CHANNEL;
|
||||
break;
|
||||
case 34:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO34_CHANNEL;
|
||||
break;
|
||||
case 35:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO35_CHANNEL;
|
||||
break;
|
||||
case 36:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO36_CHANNEL;
|
||||
break;
|
||||
case 37:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO37_CHANNEL;
|
||||
break;
|
||||
case 38:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO38_CHANNEL;
|
||||
break;
|
||||
case 39:
|
||||
adc_unit[0] = ADC_UNIT_1;
|
||||
adc_unit[channelIdx] = ADC_UNIT_1;
|
||||
adc_channel[channelIdx] = ADC1_GPIO39_CHANNEL;
|
||||
break;
|
||||
|
||||
@ -142,8 +142,6 @@ class AnalogConfig : public AudioBaseInfo {
|
||||
LOGE( "%s - pin GPIO%d is not supported", __func__,gpio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -190,6 +188,7 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
|
||||
void begin(AnalogConfig cfg) {
|
||||
LOGI(LOG_METHOD);
|
||||
cfg.logInfo();
|
||||
port_no = (i2s_port_t) cfg.port_no;
|
||||
|
||||
adc_config = cfg;
|
||||
i2s_config_t i2s_config = {
|
||||
@ -207,13 +206,13 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
|
||||
|
||||
|
||||
// setup config
|
||||
if (i2s_driver_install(cfg.i2s_port, &i2s_config, 0, nullptr)!=ESP_OK){
|
||||
if (i2s_driver_install(port_no, &i2s_config, 0, nullptr)!=ESP_OK){
|
||||
LOGE( "%s - %s", __func__, "i2s_driver_install");
|
||||
return;
|
||||
}
|
||||
|
||||
// clear i2s buffer
|
||||
if (i2s_zero_dma_buffer(cfg.i2s_port)!=ESP_OK) {
|
||||
if (i2s_zero_dma_buffer(port_no)!=ESP_OK) {
|
||||
LOGE( "%s - %s", __func__, "i2s_zero_dma_buffer");
|
||||
return;
|
||||
}
|
||||
@ -221,10 +220,12 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
|
||||
switch (cfg.mode) {
|
||||
case RX_MODE:
|
||||
//init ADC pad
|
||||
|
||||
if (i2s_set_adc_mode(cfg.adc_unit[0], cfg.adc_channel[0])!=ESP_OK) {
|
||||
LOGE( "%s - %s", __func__, "i2s_driver_install");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cfg.channels>1){
|
||||
if (i2s_set_adc_mode(cfg.adc_unit[1], cfg.adc_channel[1])!=ESP_OK) {
|
||||
LOGE( "%s - %s", __func__, "i2s_driver_install");
|
||||
@ -233,14 +234,21 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
|
||||
}
|
||||
|
||||
// enable the ADC
|
||||
if (i2s_adc_enable(cfg.i2s_port)!=ESP_OK) {
|
||||
if (i2s_adc_enable(port_no)!=ESP_OK) {
|
||||
LOGE( "%s - %s", __func__, "i2s_adc_enable");
|
||||
return;
|
||||
}
|
||||
|
||||
// if (adc1_config_channel_atten(ADC1_CHANNEL_6,ADC_ATTEN_DB_11)!=ESP_OK){
|
||||
// LOGE( "%s - %s", __func__, "adc1_config_channel_atten");
|
||||
// }
|
||||
// if (adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_11)!=ESP_OK){
|
||||
// LOGE( "%s - %s", __func__, "adc1_config_channel_atten");
|
||||
// }
|
||||
|
||||
break;
|
||||
case TX_MODE:
|
||||
i2s_set_pin(cfg.i2s_port, nullptr);
|
||||
i2s_set_pin(port_no, nullptr);
|
||||
break;
|
||||
}
|
||||
active = true;
|
||||
@ -251,7 +259,8 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
|
||||
/// stops the I2C and unistalls the driver
|
||||
void end(){
|
||||
LOGD( "%s", __func__);
|
||||
i2s_driver_uninstall(adc_config.i2s_port);
|
||||
i2s_adc_disable(port_no);
|
||||
i2s_driver_uninstall(port_no);
|
||||
active = false;
|
||||
}
|
||||
|
||||
@ -273,19 +282,19 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
|
||||
|
||||
size_t result = 0;
|
||||
if (adc_config.channels==2){
|
||||
if (i2s_write(adc_config.i2s_port, src, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
|
||||
if (i2s_write(port_no, src, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
|
||||
LOGE(LOG_METHOD);
|
||||
}
|
||||
LOGD("i2s_write %d -> %d bytes", size_bytes, result);
|
||||
} else {
|
||||
result = I2SBase::writeExpandChannel(adc_config.i2s_port, adc_config.bits_per_sample, src, size_bytes);
|
||||
result = I2SBase::writeExpandChannel(port_no, adc_config.bits_per_sample, src, size_bytes);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t readBytes(void *dest, size_t size_bytes){
|
||||
size_t result = 0;
|
||||
if (i2s_read(adc_config.i2s_port, dest, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
|
||||
if (i2s_read(port_no, dest, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
|
||||
LOGE(LOG_METHOD);
|
||||
}
|
||||
LOGD( "%s - len: %d -> %d", __func__, size_bytes, result);
|
||||
@ -314,77 +323,9 @@ class AnalogAudio : public Stream, public AudioBaseInfoDependent {
|
||||
|
||||
protected:
|
||||
AnalogConfig adc_config;
|
||||
i2s_port_t port_no;
|
||||
bool active = false;
|
||||
|
||||
|
||||
// /// writes the data by making shure that we send 2 channels 16 data scaled to 8 bits
|
||||
// static size_t writeExpandChannel(i2s_port_t i2s_port, int channels, const int bits_per_sample, const void *src, size_t size_bytes){
|
||||
// size_t result = 0;
|
||||
// int j;
|
||||
// switch(bits_per_sample){
|
||||
|
||||
// case 8:
|
||||
// for (j=0;j<size_bytes;j+=channels) {
|
||||
// int16_t frame[2];
|
||||
// int8_t *data = (int8_t *)src;
|
||||
// frame[0]=convert8DAC(data[j],bits_per_sample);
|
||||
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
|
||||
// size_t result_call = 0;
|
||||
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
|
||||
// LOGE(LOG_METHOD);
|
||||
// } else {
|
||||
// result += result_call;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case 16:
|
||||
// for (j=0;j<size_bytes/2;j+=channels) {
|
||||
// int16_t frame[2];
|
||||
// int16_t *data = (int16_t*)src;
|
||||
// frame[0]=convert8DAC(data[j],bits_per_sample);
|
||||
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
|
||||
// size_t result_call = 0;
|
||||
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
|
||||
// LOGE(LOG_METHOD);
|
||||
// } else {
|
||||
// result += result_call;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case 24:
|
||||
// for (j=0;j<size_bytes/4;j+=channels){
|
||||
// int16_t frame[2];
|
||||
// int24_t *data = (int24_t*) src;
|
||||
// frame[0]=convert8DAC(data[j],bits_per_sample);
|
||||
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
|
||||
// size_t result_call = 0;
|
||||
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
|
||||
// LOGE(LOG_METHOD);
|
||||
// } else {
|
||||
// result += result_call;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case 32:
|
||||
// for (j=0;j<size_bytes/4;j+=channels){
|
||||
// int16_t frame[2];
|
||||
// int32_t *data = (int32_t*) src;
|
||||
// frame[0]=convert8DAC(data[j],bits_per_sample);
|
||||
// frame[1]=convert8DAC(data[j+channels-1],bits_per_sample);
|
||||
// size_t result_call = 0;
|
||||
// if (i2s_write(i2s_port, frame, sizeof(int16_t)*2, &result_call, portMAX_DELAY)!=ESP_OK){
|
||||
// LOGE(LOG_METHOD);
|
||||
// } else {
|
||||
// result += result_call;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
};
|
||||
|
||||
/**
|
Loading…
Reference in New Issue
Block a user