parent
81e727f1b5
commit
71328bbf05
@ -0,0 +1,204 @@ |
|||||||
|
/**
|
||||||
|
* @file control_AK4452_F32.cpp |
||||||
|
* @author Piotr Zapart |
||||||
|
* @brief driver for the AK4452 DAC |
||||||
|
* @version 0.1 |
||||||
|
* @date 2024-06-14 |
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024 www.hexefx.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 <https://www.gnu.org/licenses/>."
|
||||||
|
*/ |
||||||
|
#include "control_AK4452_F32.h" |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL1 (0x00) |
||||||
|
#define AK4452_REG_CTRL1_DFLT (0x0C) |
||||||
|
#define AK4452_BIT_RSTN (1<<0) |
||||||
|
#define AK4452_DIF_MASK (0x0E) |
||||||
|
#define AK4452_DIF_SHIFT (0x01) |
||||||
|
#define AK4452_DIF(x) (((x)<<AK4452_DIF_SHIFT)&AK4452_DIF_MASK) |
||||||
|
#define AK4452_DIF_16B_LSB (0x00) |
||||||
|
#define AK4452_DIF_20B_LSB (0x01) |
||||||
|
#define AK4452_DIF_24B_MSB (0x02) |
||||||
|
#define AK4452_DIF_24B_I2S (0x03) |
||||||
|
#define AK4452_DIF_24B_LSB (0x04) |
||||||
|
#define AK4452_DIF_32B_LSB (0x05) |
||||||
|
#define AK4452_DIF_32B_MSB (0x06) |
||||||
|
#define AK4452_DIF_32B_I2S (0x07) |
||||||
|
#define AK4452_BIT_ACKS (1<<7) |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL2 (0x01) |
||||||
|
#define AK4452_REG_CTRL2_DFLT (0x22) |
||||||
|
#define AK4452_BIT_SMUTE (1<<0) |
||||||
|
#define AK4452_DEM_MASK (0x06) |
||||||
|
#define AK4452_DEM_SHIFT (0x01) |
||||||
|
#define AK4452_DEM(x) (((x)<<AK4452_DEM_SHIFT)&AK4452_DEM_MASK) |
||||||
|
#define AK4452_DEM_44_1K (0x00) |
||||||
|
#define AK4452_DEM_OFF (0x01) |
||||||
|
#define AK4452_DEM_48K (0x02) |
||||||
|
#define AK4452_DEM_32K (0x03) |
||||||
|
#define AK4452_DFS10_MASK (0x18) |
||||||
|
#define AK4452_DFS10_SHIFT (0x03) |
||||||
|
#define AK4452_DFS10(x) (((x)<<AK4452_DFS10_SHIFT)&AK4452_DFS10_MASK) |
||||||
|
#define AK4452_DFS_NORMAL (0x00) |
||||||
|
#define AK4452_DFS_DOUBLE (0x01) |
||||||
|
#define AK4452_DFS_QUAD (0x02) |
||||||
|
#define AK4452_DFS_OCT (0x04) |
||||||
|
#define AK4452_DFS_HEX (0x05) |
||||||
|
#define AK4452_BIT_SD (1<<5) |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL3 (0x02) |
||||||
|
#define AK4452_REG_CTRL3_DFLT (0x00) |
||||||
|
#define AK4452_BIT_SLOW (1<<0) |
||||||
|
#define AK4452_BIT_SELLR1 (1<<1) |
||||||
|
#define AK4452_BIT_DZFB (1<<2) |
||||||
|
#define AK4452_BIT_MONO1 (1<<3) |
||||||
|
#define AK4452_BIT_DCKB (1<<4) |
||||||
|
#define AK4452_BIT_DCKS (1<<5) |
||||||
|
#define AK4452_BIT_DP (1<<7) |
||||||
|
|
||||||
|
#define AK4452_REG_L1CH_ATT (0x03) |
||||||
|
#define AK4452_REG_L1CH_ATT_DFLT (0xFF) |
||||||
|
#define AK4452_REG_R1CH_ATT (0x04) |
||||||
|
#define AK4452_REG_R1CH_ATT_DFLT (0xFF) |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL4 (0x05) |
||||||
|
#define AK4452_REG_CTRL4_DFLT (0x00) |
||||||
|
#define AK4452_BIT_SSLOW (1<<0) |
||||||
|
#define AK4452_DFS2_MASK (1<<1) |
||||||
|
#define AK4452_DFS2_SHIFT (0x01) |
||||||
|
#define AK4452_DFS2(x) (((x)<<AK4452_DFS2_SHIFT)&AK4452_DFS2_MASK) // bits10 in CTRL2
|
||||||
|
#define AK4452_BIT_INVL1 (1<<6) |
||||||
|
#define AK4452_BIT_INVR1 (1<<7) |
||||||
|
|
||||||
|
#define AK4452_REG_DSD1 (0x06) |
||||||
|
#define AK4452_REG_DSD1_DFLT (0x00) |
||||||
|
#define AK4452_BIT_DSDSEL0 (1<<0) |
||||||
|
#define AK4452_BIT_DSDD (1<<1) |
||||||
|
#define AK4452_BIT_DMRE (1<<3) |
||||||
|
#define AK4452_BIT_DMC (1<<4) |
||||||
|
#define AK4452_BIT_DMR1 (1<<5) |
||||||
|
#define AK4452_BIT_DML1 (1<<6) |
||||||
|
#define AK4452_BIT_DDM (1<<7) |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL5 (0x07) |
||||||
|
#define AK4452_REG_CTRL5_DFLT (0x03) |
||||||
|
#define AK4452_BIT_SYNCE (1<<0) |
||||||
|
|
||||||
|
#define AK4452_REG_SND_CTRL (0x08) |
||||||
|
#define AK4452_REG_SND_CTRL_DFLT (0x00) |
||||||
|
#define AK4452_SC_MASK (0x03) |
||||||
|
#define AK4452_SC_SHIFT (0x00) |
||||||
|
#define AK4452_SC(x) (((x)<<AK4452_SC_SHIFT)&AK4452_SC_MASK) |
||||||
|
#define AK4452_SC_NORMAL (0x00) |
||||||
|
#define AK4452_SC_MAX (0x01) |
||||||
|
#define AK4452_SC_MIN (0x02) |
||||||
|
#define AK4452_BIT_DZF_L1 (1<<6) |
||||||
|
#define AK4452_BIT_DZF_R1 (1<<7) |
||||||
|
|
||||||
|
#define AK4452_REG_DSD2 (0x09) |
||||||
|
#define AK4452_REG_DSD2_DFLT (0x00) |
||||||
|
#define AK4452_BIT_DSDSEL1 (1<<0) |
||||||
|
#define AK4452_BIT_DSDF (1<<1) |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL6 (0x0A) |
||||||
|
#define AK4452_REG_CTRL6_DFLT (0x0D) |
||||||
|
#define AK4452_BIT_PW1 (1<<2) |
||||||
|
#define AK4452_SDS21_MASK (0x30) |
||||||
|
#define AK4452_SDS21_SHIFT (0x04) |
||||||
|
#define AK4452_SDS21(x) (((x)<<AK4452_SDS21_SHIFT)&AK4452_SDS21_MASK) |
||||||
|
#define AK4452_SDS_TDM128_L1R1 (0x00) |
||||||
|
#define AK4452_SDS_TDM128_L2R2 (0x01) |
||||||
|
#define AK4452_SDS_TDM256_L1R1 (0x00) |
||||||
|
#define AK4452_SDS_TDM256_L2R2 (0x01) |
||||||
|
#define AK4452_SDS_TDM256_L3R3 (0x02) |
||||||
|
#define AK4452_SDS_TDM256_L4R4 (0x03) |
||||||
|
#define AK4452_SDS_TDM512_L1R1 (0x00) |
||||||
|
#define AK4452_SDS_TDM512_L2R2 (0x01) |
||||||
|
#define AK4452_SDS_TDM512_L3R3 (0x02) |
||||||
|
#define AK4452_SDS_TDM512_L4R4 (0x03) |
||||||
|
#define AK4452_SDS_TDM512_L5R5 (0x04) |
||||||
|
#define AK4452_SDS_TDM512_L6R6 (0x05) |
||||||
|
#define AK4452_SDS_TDM512_L7R7 (0x06) |
||||||
|
#define AK4452_SDS_TDM512_L8R8 (0x07) |
||||||
|
#define AK4452_TDM_MASK (0xC0) |
||||||
|
#define AK4452_TDM_SHIFT (0x06) |
||||||
|
#define AK4452_TDM(x) (((x)<<AK4452_TDM_SHIFT)&AK4452_TDM_MASK) |
||||||
|
#define AK4452_TDM_NORMAL (0x00) |
||||||
|
#define AK4452_TDM_128 (0x01) |
||||||
|
#define AK4452_TDM_246 (0x02) |
||||||
|
#define AK4452_TDM_512 (0x03) |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL7 (0x0B) |
||||||
|
#define AK4452_REG_CTRL7_DFLT (0x0C) |
||||||
|
#define AK4452_BIT_DCHAIN (1<<2) |
||||||
|
#define AK4452_SDS0_MASK (1<<4) |
||||||
|
#define AK4452_SDS0_SHIFT (0x04) |
||||||
|
#define AK4452_SDS0(x) (((x)<<AK4452_SDS0_SHIFT)&AK4452_SDS0_MASK) |
||||||
|
#define AK4452_ATS_MASK (0xC0) |
||||||
|
#define AK4452_ATS_SHIFT (0x06) |
||||||
|
#define AK4452_ATS(x) (((x)<<AK4452_ATS_SHIFT)&AK4452_ATS_MASK) |
||||||
|
#define AK4452_ATS_4080 (0x00) |
||||||
|
#define AK4452_ATS_2040 (0x01) |
||||||
|
#define AK4452_ATS_510 (0x02) |
||||||
|
#define AK4452_ATS_255 (0x03) |
||||||
|
|
||||||
|
#define AK4452_REG_CTRL8 (0x0C) |
||||||
|
#define AK4452_REG_CTRL8_DFLT (0x00) |
||||||
|
#define AK4452_FIR(x) ((x)&0x07) |
||||||
|
|
||||||
|
bool AudioControlAK4452_F32::configured = false; |
||||||
|
|
||||||
|
bool AudioControlAK4452_F32::enable(TwoWire *i2cBus, uint8_t addr) |
||||||
|
{ |
||||||
|
ctrlBus = i2cBus; |
||||||
|
i2cAddr = addr; |
||||||
|
ctrlBus->begin(); |
||||||
|
ctrlBus->setClock(400000); |
||||||
|
|
||||||
|
if (!writeReg(AK4452_REG_CTRL1, 0x00)) // put the registers in reset mode
|
||||||
|
{ |
||||||
|
return false; // codec not found
|
||||||
|
}
|
||||||
|
// DIF[2:0] = 0b111 - 32bit I2S, Normal mode
|
||||||
|
// DFS[2:0] = 0b000 (default) Normal speed mode
|
||||||
|
// DSDSEL[1:0] = 0b10 256fs
|
||||||
|
writeReg(AK4452_REG_DSD2, AK4452_BIT_DSDSEL1); |
||||||
|
writeReg(AK4452_REG_CTRL1, AK4452_DIF(AK4452_DIF_32B_I2S) | AK4452_BIT_RSTN); |
||||||
|
|
||||||
|
configured = true; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool AudioControlAK4452_F32::writeReg(uint8_t addr, uint8_t val) |
||||||
|
{ |
||||||
|
ctrlBus->beginTransmission(i2cAddr); |
||||||
|
ctrlBus->write(addr); |
||||||
|
ctrlBus->write(val); |
||||||
|
return ctrlBus->endTransmission() == 0; |
||||||
|
} |
||||||
|
bool AudioControlAK4452_F32::readReg(uint8_t addr, uint8_t *valPtr) |
||||||
|
{ |
||||||
|
ctrlBus->beginTransmission(i2cAddr); |
||||||
|
ctrlBus->write(addr); |
||||||
|
if (ctrlBus->endTransmission(false) != 0) |
||||||
|
return false;
|
||||||
|
if (ctrlBus->requestFrom((int)i2cAddr, 1) < 1) return false; |
||||||
|
*valPtr = ctrlBus->read(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t AudioControlAK4452_F32::modifyReg(uint8_t reg, uint8_t val, uint8_t iMask) |
||||||
|
{ |
||||||
|
uint8_t val1; |
||||||
|
val1 = (readReg(reg, &val1) & (~iMask)) | val; |
||||||
|
if (!writeReg(reg, val1)) |
||||||
|
return 0; |
||||||
|
return val1; |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
/**
|
||||||
|
* @file control_AK4452_F32.h |
||||||
|
* @author Piotr Zapart |
||||||
|
* @brief driver for the AK4452 DAC |
||||||
|
* @version 0.1 |
||||||
|
* @date 2024-06-14 |
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024 www.hexefx.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 <https://www.gnu.org/licenses/>."
|
||||||
|
*/ |
||||||
|
#ifndef _CONTROL_AK4452_H_ |
||||||
|
#define _CONTROL_AK4452_H_ |
||||||
|
#include <Arduino.h> |
||||||
|
#include <Wire.h> |
||||||
|
#include "AudioControl.h" |
||||||
|
|
||||||
|
#define AK4452_ADDR00 (0x10) |
||||||
|
#define AK4452_ADDR01 (0x11) |
||||||
|
#define AK4452_ADDR10 (0x12) |
||||||
|
#define AK4452_ADDR11 (0x13) |
||||||
|
|
||||||
|
class AudioControlAK4452_F32 : public AudioControl |
||||||
|
{ |
||||||
|
public: |
||||||
|
AudioControlAK4452_F32(){}; |
||||||
|
~AudioControlAK4452_F32(){}; |
||||||
|
bool enable() |
||||||
|
{ |
||||||
|
return enable(&Wire, AK4452_ADDR10); |
||||||
|
} |
||||||
|
bool enable(TwoWire *i2cBus, uint8_t addr); |
||||||
|
|
||||||
|
// not used but required by AudioControl
|
||||||
|
bool disable() {return true;} |
||||||
|
bool volume(float volume) {return true;}; |
||||||
|
bool inputLevel(float volume) {return true;} |
||||||
|
bool inputSelect(int n) {return true;} |
||||||
|
|
||||||
|
private: |
||||||
|
static bool configured; |
||||||
|
TwoWire *ctrlBus; |
||||||
|
uint8_t i2cAddr; |
||||||
|
|
||||||
|
bool writeReg(uint8_t addr, uint8_t val); |
||||||
|
bool readReg(uint8_t addr, uint8_t* valPtr); |
||||||
|
uint8_t modifyReg(uint8_t reg, uint8_t val, uint8_t iMask); |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // _CONTROL_AK4452_H_
|
@ -0,0 +1,114 @@ |
|||||||
|
/**
|
||||||
|
* @file control_AK5552_F32.cpp |
||||||
|
* @author Piotr Zapart |
||||||
|
* @brief driver for the AK5552 ADC |
||||||
|
* @version 0.1 |
||||||
|
* @date 2024-06-14 |
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024 www.hexefx.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 <https://www.gnu.org/licenses/>."
|
||||||
|
*/ |
||||||
|
#include "control_AK5552_F32.h" |
||||||
|
|
||||||
|
#define AK5552_REG_PWR_MAN1 (0x00) |
||||||
|
#define AK5552_REG_PWR_MAN1_DFLT (0xFF) |
||||||
|
#define AK5552_BIT_PW1 (1<<0) |
||||||
|
#define AK5552_BIT_PW2 (1<<1) |
||||||
|
|
||||||
|
#define AK5552_REG_PWR_MAN2 (0x01) |
||||||
|
#define AK5552_REG_PWR_MAN2_DFLT (0x01) |
||||||
|
#define AK5552_BIT_RSTN (1<<0) |
||||||
|
#define AK5552_BIT_MONO1 (1<<1) |
||||||
|
#define AK5552_BIT_MONO2 (1<<2) |
||||||
|
|
||||||
|
#define AK5552_REG_PWR_CTRL1 (0x02) |
||||||
|
#define AK5552_REG_PWR_CTRL1_DFLT (0x01) |
||||||
|
#define AK5552_BIT_HPFE (1<<0) |
||||||
|
#define AK5552_BIT_DIF0 (1<<1) |
||||||
|
#define AK5552_BIT_DIF1 (1<<2) |
||||||
|
#define AK5552_BIT_CKS0 (1<<3) |
||||||
|
#define AK5552_BIT_CKS1 (1<<4) |
||||||
|
#define AK5552_BIT_CKS2 (1<<5) |
||||||
|
#define AK5552_BIT_CKS3 (1<<6) |
||||||
|
|
||||||
|
#define AK5552_REG_PWR_CTRL2 (0x03) |
||||||
|
#define AK5552_REG_PWR_CTRL2_DFLT (0x00) |
||||||
|
#define AK5552_BIT_TDM0 (1<<5) |
||||||
|
#define AK5552_BIT_TDM1 (1<<6) |
||||||
|
|
||||||
|
#define AK5552_REG_PWR_CTRL3 (0x04) |
||||||
|
#define AK5552_REG_PWR_CTRL3_DFLT (0x00) |
||||||
|
#define AK5552_BIT_SLOW (1<<0) |
||||||
|
#define AK5552_BIT_SD (1<<1) |
||||||
|
|
||||||
|
#define AK5552_REG_PWR_DSD (0x04) |
||||||
|
#define AK5552_REG_PWR_DSD_DFLT (0x00) |
||||||
|
#define AK5552_DSDSEL_64FS (0x00) |
||||||
|
#define AK5552_DSDSEL_128FS (0x01) |
||||||
|
#define AK5552_DSDSEL_256FS (0x10) |
||||||
|
#define AK5552_DSDSEL(x) ((x)&0x03) |
||||||
|
#define AK5552_BIT_DCKB (1<<2) |
||||||
|
#define AK5552_BIT_PMOD (1<<3) |
||||||
|
#define AK5552_BIT_DCKS (1<<5) |
||||||
|
|
||||||
|
bool AudioControlAK5552_F32::configured = false; |
||||||
|
|
||||||
|
|
||||||
|
bool AudioControlAK5552_F32::enable(TwoWire *i2cBus, uint8_t addr) |
||||||
|
{ |
||||||
|
ctrlBus = i2cBus; |
||||||
|
i2cAddr = addr; |
||||||
|
ctrlBus->begin(); |
||||||
|
ctrlBus->setClock(400000); |
||||||
|
|
||||||
|
if (!writeReg(AK5552_REG_PWR_MAN2, 0x00)) // put the registers in reset mode
|
||||||
|
{ |
||||||
|
return false; // codec not found
|
||||||
|
}
|
||||||
|
// Normal Speed 256fs, table 5, page 34
|
||||||
|
// CKS3=0, CKS2=0, CKS1=1, CKS0=0
|
||||||
|
// 32bit I2S, Slave mode, table 8, page 62
|
||||||
|
// TDM1=0, TDM0=0, MSN=0, DIF1=1, DIF0=1
|
||||||
|
writeReg( AK5552_REG_PWR_CTRL1, AK5552_BIT_CKS1 |
|
||||||
|
AK5552_BIT_DIF1 |
|
||||||
|
AK5552_BIT_DIF0); |
||||||
|
// enable short delay
|
||||||
|
writeReg(AK5552_REG_PWR_CTRL3, AK5552_BIT_SD); |
||||||
|
writeReg(AK5552_REG_PWR_MAN2, AK5552_BIT_RSTN); // register in normal operation
|
||||||
|
configured = true; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool AudioControlAK5552_F32::writeReg(uint8_t addr, uint8_t val) |
||||||
|
{ |
||||||
|
ctrlBus->beginTransmission(i2cAddr); |
||||||
|
ctrlBus->write(addr); |
||||||
|
ctrlBus->write(val); |
||||||
|
return ctrlBus->endTransmission() == 0; |
||||||
|
} |
||||||
|
bool AudioControlAK5552_F32::readReg(uint8_t addr, uint8_t *valPtr) |
||||||
|
{ |
||||||
|
ctrlBus->beginTransmission(i2cAddr); |
||||||
|
ctrlBus->write(addr); |
||||||
|
if (ctrlBus->endTransmission(false) != 0) |
||||||
|
return false;
|
||||||
|
if (ctrlBus->requestFrom((int)i2cAddr, 1) < 1) return false; |
||||||
|
*valPtr = ctrlBus->read(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t AudioControlAK5552_F32::modifyReg(uint8_t reg, uint8_t val, uint8_t iMask) |
||||||
|
{ |
||||||
|
uint8_t val1; |
||||||
|
val1 = (readReg(reg, &val1) & (~iMask)) | val; |
||||||
|
if (!writeReg(reg, val1)) |
||||||
|
return 0; |
||||||
|
return val1; |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
/**
|
||||||
|
* @file control_AK5552_F32.h |
||||||
|
* @author Piotr Zapart |
||||||
|
* @brief driver for the AK5552 ADC |
||||||
|
* @version 0.1 |
||||||
|
* @date 2024-06-14 |
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024 www.hexefx.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 <https://www.gnu.org/licenses/>."
|
||||||
|
*/ |
||||||
|
#ifndef _CONTROL_AK5552_F32_H_ |
||||||
|
#define _CONTROL_AK5552_F32_H_ |
||||||
|
|
||||||
|
#include <Arduino.h> |
||||||
|
#include <Wire.h> |
||||||
|
#include "AudioControl.h" |
||||||
|
|
||||||
|
#define AK5552_ADDR00 (0x10) |
||||||
|
#define AK5552_ADDR01 (0x11) |
||||||
|
#define AK5552_ADDR10 (0x12) |
||||||
|
#define AK5552_ADDR11 (0x13) |
||||||
|
|
||||||
|
class AudioControlAK5552_F32 : public AudioControl |
||||||
|
{ |
||||||
|
public: |
||||||
|
AudioControlAK5552_F32(){}; |
||||||
|
~AudioControlAK5552_F32(){}; |
||||||
|
bool enable() |
||||||
|
{ |
||||||
|
return enable(&Wire, AK5552_ADDR00); |
||||||
|
} |
||||||
|
bool enable(TwoWire *i2cBus, uint8_t addr); |
||||||
|
|
||||||
|
// not used but required by AudioControl
|
||||||
|
bool disable() {return true;} |
||||||
|
bool volume(float volume) {return true;}; |
||||||
|
bool inputLevel(float volume) {return true;} |
||||||
|
bool inputSelect(int n) {return true;} |
||||||
|
|
||||||
|
private: |
||||||
|
static bool configured; |
||||||
|
TwoWire *ctrlBus; |
||||||
|
uint8_t i2cAddr; |
||||||
|
|
||||||
|
bool writeReg(uint8_t addr, uint8_t val); |
||||||
|
bool readReg(uint8_t addr, uint8_t* valPtr); |
||||||
|
uint8_t modifyReg(uint8_t reg, uint8_t val, uint8_t iMask); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif // _CONTROL_AK5552_H_
|
@ -0,0 +1,254 @@ |
|||||||
|
/**
|
||||||
|
* @file effect_wahMono_F32.cpp |
||||||
|
* @author Piotr Zapart |
||||||
|
* @brief Mono WAH effect |
||||||
|
* @version 0.1 |
||||||
|
* @date 2024-07-09 |
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024 www.hexefx.com |
||||||
|
*
|
||||||
|
* Implementation is based on the work of Transmogrifox |
||||||
|
* https://cackleberrypines.net/transmogrifox/src/bela/inductor_wah_C_src/
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>."
|
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#include "effect_wahMono_F32.h" |
||||||
|
|
||||||
|
#define k *1e3 |
||||||
|
#define nF *1e-9 |
||||||
|
const AudioEffectWahMono_F32::wah_componentValues_t AudioEffectWahMono_F32::compValues[WAH_MODEL_LAST] =
|
||||||
|
{// Lp Cf Ci Rpot Ri Rs Rp, Rc Rbias Re beta name
|
||||||
|
{0.50f, 10.0f nF, 10.0f nF, 100.0f k, 68.0f k, 1.5f k, 33.0f k, 22.0f k, 470.0f k, 390.0f, 250.0f}, // G1
|
||||||
|
{0.50f, 10.0f nF, 10.0f nF, 100.0f k, 68.0f k, 1.5f k, 33.0f k, 22.0f k, 470.0f k, 510.0f, 650.0f}, // G2
|
||||||
|
{0.66f, 10.0f nF, 10.0f nF, 100.0f k, 68.0f k, 1.5f k, 33.0f k, 22.0f k, 470.0f k, 390.0f, 250.0f}, // G3
|
||||||
|
{0.50f, 10.0f nF, 10.0f nF, 100.0f k, 68.0f k, 1.5f k, 100.0f k,22.0f k, 470.0f k, 470.0f, 250.0f}, // G4
|
||||||
|
{0.50f, 15.0f nF, 8.0f nF, 100.0f k, 220.0f k, 0.1f k, 47.0f k, 22.0f k, 470.0f k, 510.0f, 250.0f}, // VOCAL
|
||||||
|
{0.50f, 10.0f nF, 47.0f nF, 100.0f k, 68.0f k, 1.5f k,150.0f k, 22.0f k, 470.0f k, 150.0f, 250.0f}, // EXTREME
|
||||||
|
{0.66f, 10.0f nF, 10.0f nF, 100.0f k, 68.0f k, 1.5f k,33.0f k, 22.0f k, 470.0f k, 470.0f, 250.0f}, // CUSTOM
|
||||||
|
{0.50f, 100.0f nF, 10.0f nF, 100.0f k, 100.0f k, 1.5f k,100.0f k, 22.0f k, 470.0f k, 470.0f, 200.0f} // BASS
|
||||||
|
}; |
||||||
|
#undef k |
||||||
|
#undef nF |
||||||
|
|
||||||
|
void AudioEffectWahMono_F32::update() |
||||||
|
{ |
||||||
|
audio_block_f32_t *blockL, *blockR, *blockMod; |
||||||
|
float32_t a0, a1, a2, ax, drySig; |
||||||
|
uint16_t i; |
||||||
|
if (bp) // handle bypass
|
||||||
|
{ |
||||||
|
blockL = AudioStream_F32::receiveReadOnly_f32(0); |
||||||
|
blockR = AudioStream_F32::receiveReadOnly_f32(1); |
||||||
|
if (!blockL || !blockR) |
||||||
|
{ |
||||||
|
if (blockL) |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
if (blockR) |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
return; |
||||||
|
} |
||||||
|
AudioStream_F32::transmit(blockL, 0); |
||||||
|
AudioStream_F32::transmit(blockR, 1); |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
return; |
||||||
|
} |
||||||
|
blockL = AudioStream_F32::receiveWritable_f32(0); |
||||||
|
blockR = AudioStream_F32::receiveWritable_f32(1); |
||||||
|
if (!blockL || !blockR) |
||||||
|
{ |
||||||
|
if (blockL) |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
if (blockR) |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
return; |
||||||
|
} |
||||||
|
blockMod = AudioStream_F32::receiveReadOnly_f32(2); |
||||||
|
|
||||||
|
arm_add_f32(blockL->data, blockR->data, blockL->data, blockL->length); // add two channels
|
||||||
|
arm_scale_f32(blockL->data, input_gain, blockL->data, blockL->length); |
||||||
|
for (i=0; i<blockL->length; i++) |
||||||
|
{ |
||||||
|
//variable gp is the pot gain, nominal range 0.0 to 1.0
|
||||||
|
//although this can be abused for extended range.
|
||||||
|
//A value less than zero would make the filter go unstable
|
||||||
|
//and put a lot of NaNs in your audio output
|
||||||
|
if (blockMod)
|
||||||
|
{ |
||||||
|
// TODO: scale the range to 0.0-1.0
|
||||||
|
gp = blockMod->data[i]; |
||||||
|
} |
||||||
|
if(gp < 0.0f) gp = 0.0f; |
||||||
|
float32_t gp_scaled = map_sat(gp, 0.0f, 1.0f, gp_top, gp_btm); |
||||||
|
|
||||||
|
//The magic numbers below approximate frequency warping characteristic
|
||||||
|
float32_t gw = 4.6f-18.4f/(4.0f + gp_scaled); |
||||||
|
|
||||||
|
//Update Biquad coefficients
|
||||||
|
a0 = a0b + gw*a0c; |
||||||
|
a1 = -(a1b + gw*a1c); |
||||||
|
a2 = -(a2b + gw*a2c); |
||||||
|
ax = 1.0f/a0; |
||||||
|
|
||||||
|
drySig = blockL->data[i]; |
||||||
|
|
||||||
|
//run it through the 1-pole HPF and gain first
|
||||||
|
float32_t hpf = ghpf * (drySig - xh1) - a1p*yh1; |
||||||
|
xh1 = drySig; |
||||||
|
yh1 = hpf; |
||||||
|
|
||||||
|
//Apply modulated biquad
|
||||||
|
float32_t y0 = b0*hpf + b1*x1 + b2*x2 + a1*y1 + a2*y2; |
||||||
|
y0 *= ax; |
||||||
|
float32_t out = clip(y0); |
||||||
|
y0 = 0.95f*y0 + 0.05f*out; //Let a little harmonic distortion feed back into the filter loop
|
||||||
|
x2 = x1; |
||||||
|
x1 = hpf; |
||||||
|
y2 = y1; |
||||||
|
y1 = y0; |
||||||
|
|
||||||
|
out = out * wet_gain + drySig * dry_gain; |
||||||
|
|
||||||
|
blockL->data[i] = out; |
||||||
|
blockR->data[i] = out; |
||||||
|
} |
||||||
|
AudioStream_F32::transmit(blockL, 0); // send blockL on both output channels
|
||||||
|
AudioStream_F32::transmit(blockL, 1); |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
if (blockMod) AudioStream_F32::release(blockMod); |
||||||
|
} |
||||||
|
|
||||||
|
FLASHMEM void AudioEffectWahMono_F32::setModel(wahModel_t model) |
||||||
|
{ |
||||||
|
if (model > WAH_MODEL_LAST) model = WAH_MODEL_G1; |
||||||
|
|
||||||
|
float32_t _b0, _b1, _b2; |
||||||
|
float32_t _a0c, _a1c, _a2c; |
||||||
|
float32_t _b0h, _b1h, _b2h; |
||||||
|
float32_t _b0b, _b2b; |
||||||
|
float32_t _a0b, _a1b, _a2b; |
||||||
|
float32_t _a1p, _ghpf; |
||||||
|
|
||||||
|
//helper variables
|
||||||
|
float32_t ro = 0.0f; |
||||||
|
float32_t re = 0.0f; |
||||||
|
float32_t Req = 0.0f; |
||||||
|
float32_t ic = 0.0f; |
||||||
|
|
||||||
|
float32_t RpRi, f0, w0, Q, c, s, alpha; |
||||||
|
|
||||||
|
//Equivalent output resistance seen from BJT collector
|
||||||
|
ro = compValues[model].Rc * compValues[model].Rpot / (compValues[model].Rc + compValues[model].Rpot) ; |
||||||
|
ro = ro * compValues[model].Rbias / (ro + compValues[model].Rbias); |
||||||
|
ic = 3.7f/compValues[model].Rc; //Typical bias current
|
||||||
|
re = 0.025f/ic; //BJT gain stage equivalent internal emitter resistance
|
||||||
|
// gm = Ic/Vt, re = 1/gm
|
||||||
|
Req = compValues[model].Re + re; |
||||||
|
gf = -ro/Req; //forward gain of transistor stage
|
||||||
|
re = compValues[model].beta*Req; //Resistance looking into BJT emitter
|
||||||
|
Rp = compValues[model].Rp*re/(re + compValues[model].Rp); |
||||||
|
|
||||||
|
RpRi = Rp*compValues[model].Ri/(Rp + compValues[model].Ri); |
||||||
|
f0 = 1.0f/(2.0f*M_PI*sqrtf(compValues[model].Lp*compValues[model].Cf)); |
||||||
|
w0 = 2.0f*M_PI*f0/fs; |
||||||
|
Q = RpRi*sqrtf(compValues[model].Cf/compValues[model].Lp); |
||||||
|
c = cosf(w0); |
||||||
|
s = sinf(w0); |
||||||
|
alpha = s/(2.0f*Q); |
||||||
|
|
||||||
|
//High Pass Biquad Coefficients
|
||||||
|
_b0h = (1.0f + c)/2.0f; |
||||||
|
_b1h = -(1.0f + c); |
||||||
|
_b2h = (1.0f + c)/2.0f; |
||||||
|
|
||||||
|
//Band-pass biquad coefficients
|
||||||
|
_b0b = Q*alpha; |
||||||
|
_b2b = -Q*alpha; |
||||||
|
_a0b = 1.0f + alpha; |
||||||
|
_a1b = -2.0f*c; |
||||||
|
_a2b = 1.0f - alpha; |
||||||
|
|
||||||
|
//1-pole high pass filter coefficients
|
||||||
|
// H(z) = g * (1 - z^-1)/(1 - a1*z^-1)
|
||||||
|
// Direct Form 1:
|
||||||
|
// y[n] = ghpf * ( x[n] - x[n-1] ) - a1p*y[n-1]
|
||||||
|
|
||||||
|
_a1p = -expf(-1.0f/(compValues[model].Ri*compValues[model].Ci*fs)); |
||||||
|
_ghpf = gf*(1.0f - a1p)*0.5f; //BJT forward gain worked in here to
|
||||||
|
// save extra multiplications in
|
||||||
|
// updating biquad coefficients
|
||||||
|
|
||||||
|
//Distill all down to final biquad coefficients
|
||||||
|
float32_t Gi = compValues[model].Rs/(compValues[model].Ri + compValues[model].Rs); |
||||||
|
float32_t gbpf = 1.0f/(2.0f*M_PI*f0*compValues[model].Ri*compValues[model].Cf); //band-pass component equivalent gain
|
||||||
|
|
||||||
|
//Final Biquad numerator coefficients
|
||||||
|
_b0 = gbpf*b0b + Gi*a0b; |
||||||
|
_b1 = Gi*a1b; |
||||||
|
_b2 = gbpf*b2b + Gi*a2b; |
||||||
|
|
||||||
|
//Constants to make denominator coefficients computation more efficient
|
||||||
|
//in real-time
|
||||||
|
_a0c = -gf*b0h; |
||||||
|
_a1c = -gf*b1h; |
||||||
|
_a2c = -gf*b2h; |
||||||
|
|
||||||
|
__disable_irq(); |
||||||
|
b0h = _b0h; |
||||||
|
b1h = _b1h; |
||||||
|
b2h = _b2h; |
||||||
|
b0b = _b0b; |
||||||
|
b2b = _b2b; |
||||||
|
a0b = _a0b; |
||||||
|
a1b = _a1b; |
||||||
|
a2b = _a2b; |
||||||
|
a1p = _a1p; |
||||||
|
ghpf = _ghpf; |
||||||
|
b0 = _b0; |
||||||
|
b1 = _b1; |
||||||
|
b2 = _b2; |
||||||
|
a0c = _a0c; |
||||||
|
a1c = _a1c; |
||||||
|
a2c = _a2c; |
||||||
|
y1 = 0.0f; //biquad state variables
|
||||||
|
y2 = 0.0f; |
||||||
|
x1 = 0.0f; |
||||||
|
x2 = 0.0f; |
||||||
|
//First order high-pass filter state variables
|
||||||
|
yh1 = 0.0f; |
||||||
|
xh1 = 0.0f;
|
||||||
|
__enable_irq(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
float32_t AudioEffectWahMono_F32::clip(float32_t x) |
||||||
|
{ |
||||||
|
|
||||||
|
float32_t thrs = 0.8f; |
||||||
|
float32_t nthrs = -0.72f; |
||||||
|
float32_t f=1.25f; |
||||||
|
|
||||||
|
//Hard limiting
|
||||||
|
if(x >= 1.2f) x = 1.2f; |
||||||
|
if(x <= -1.12f) x = -1.12f; |
||||||
|
|
||||||
|
//Soft clipping
|
||||||
|
if(x > thrs) |
||||||
|
{ |
||||||
|
x -= f*sqr(x - thrs); |
||||||
|
} |
||||||
|
if(x < nthrs){ |
||||||
|
x += f*sqr(x - nthrs); |
||||||
|
}
|
||||||
|
return x; |
||||||
|
} |
@ -0,0 +1,167 @@ |
|||||||
|
/**
|
||||||
|
* @file effect_wahMono_F32.h |
||||||
|
* @author Piotr Zapart |
||||||
|
* @brief Mono WAH effect |
||||||
|
* @version 0.1 |
||||||
|
* @date 2024-07-09 |
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024 www.hexefx.com |
||||||
|
*
|
||||||
|
* Implementation is based on the work of Transmogrifox |
||||||
|
* https://cackleberrypines.net/transmogrifox/src/bela/inductor_wah_C_src/
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>."
|
||||||
|
*/ |
||||||
|
#ifndef _EFFECT_WAHMONO_F32_H_ |
||||||
|
#define _EFFECT_WAHMONO_F32_H_ |
||||||
|
|
||||||
|
#include <Arduino.h> |
||||||
|
#include "AudioStream_F32.h" |
||||||
|
#include "basic_DSPutils.h" |
||||||
|
|
||||||
|
typedef enum |
||||||
|
{ |
||||||
|
WAH_MODEL_G1 = 0, |
||||||
|
WAH_MODEL_G2, |
||||||
|
WAH_MODEL_G3, |
||||||
|
WAH_MODEL_G4, |
||||||
|
WAH_MODEL_VOCAL, |
||||||
|
WAH_MODEL_EXTREME, |
||||||
|
WAH_MODEL_CUSTOM, |
||||||
|
WAH_MODEL_BASS, |
||||||
|
WAH_MODEL_LAST |
||||||
|
}wahModel_t; |
||||||
|
|
||||||
|
class AudioEffectWahMono_F32 : public AudioStream_F32 |
||||||
|
{ |
||||||
|
public: |
||||||
|
AudioEffectWahMono_F32(void) : AudioStream_F32(3, inputQueueArray_f32)
|
||||||
|
{ |
||||||
|
setModel(WAH_MODEL_G3); |
||||||
|
} |
||||||
|
// Alternate specification of block size. Sample rate does not apply for analyze_rms
|
||||||
|
AudioEffectWahMono_F32(const AudioSettings_F32 &settings) : AudioStream_F32(3, inputQueueArray_f32) |
||||||
|
{ |
||||||
|
block_size = settings.audio_block_samples; |
||||||
|
fs = settings.sample_rate_Hz; |
||||||
|
setModel(WAH_MODEL_G3); |
||||||
|
} |
||||||
|
virtual void update(); |
||||||
|
|
||||||
|
void setModel(wahModel_t model); |
||||||
|
void setFreq(float32_t val) |
||||||
|
{ |
||||||
|
val = constrain(val, 0.0f, 1.0f); |
||||||
|
val = 1.0f - val; |
||||||
|
__disable_irq(); |
||||||
|
gp = val; |
||||||
|
__enable_irq(); |
||||||
|
} |
||||||
|
void setRange(float32_t heel, float32_t toe) |
||||||
|
{ |
||||||
|
gp_top = 1.0f - constrain(heel, 0.0f, 1.0f); |
||||||
|
gp_btm = 1.0f - constrain(toe, 0.0f, 1.0f); |
||||||
|
} |
||||||
|
|
||||||
|
void setMix(float32_t mix) |
||||||
|
{ |
||||||
|
mix = constrain(mix, 0.0f, 1.0f); |
||||||
|
float32_t dry, wet; |
||||||
|
mix_pwr(mix, &wet, &dry); |
||||||
|
__disable_irq(); |
||||||
|
dry_gain = dry; |
||||||
|
wet_gain = wet; |
||||||
|
__enable_irq(); |
||||||
|
} |
||||||
|
bool bypass_get(void) {return bp;} |
||||||
|
void bypass_set(bool state) {bp = state;} |
||||||
|
bool bypass_tgl(void)
|
||||||
|
{ |
||||||
|
bp ^= 1;
|
||||||
|
return bp; |
||||||
|
}
|
||||||
|
private: |
||||||
|
bool bp = true; // bypass flag
|
||||||
|
audio_block_f32_t *inputQueueArray_f32[3]; |
||||||
|
uint16_t block_size = AUDIO_BLOCK_SAMPLES; |
||||||
|
float32_t fs = AUDIO_SAMPLE_RATE_EXACT; |
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
//Circuit parameters
|
||||||
|
//Using these makes it straight-forward to model other
|
||||||
|
//variants of the circuit
|
||||||
|
float32_t Lp; //RLC tank inductor
|
||||||
|
float32_t Cf; //feedback capacitor
|
||||||
|
float32_t Ci; //input capacitor
|
||||||
|
|
||||||
|
float32_t Rpot; //Pot resistance value
|
||||||
|
float32_t Ri; //input feed resistor
|
||||||
|
float32_t Rs; //RLC tank to BJT base resistor (dry mix)
|
||||||
|
float32_t Rp; //resistor placed parallel with the inductor
|
||||||
|
|
||||||
|
//Gain-setting components
|
||||||
|
float32_t Rc; //BJT gain stage collector resistor
|
||||||
|
|
||||||
|
float32_t Rbias; //Typically 470k bias resistor shows up in parallel with output
|
||||||
|
float32_t Re; //BJT gain stage emitter resistor
|
||||||
|
|
||||||
|
float32_t beta; //BJT forward gain
|
||||||
|
}wah_componentValues_t; |
||||||
|
|
||||||
|
static const wah_componentValues_t compValues[WAH_MODEL_LAST]; |
||||||
|
|
||||||
|
float32_t gp = 0.0f; // pot gain
|
||||||
|
float32_t input_gain = 0.5f; |
||||||
|
float32_t dry_gain = 0.0f; |
||||||
|
float32_t wet_gain = 1.0f; |
||||||
|
float32_t gp_top = 0.0f; |
||||||
|
float32_t gp_btm = 1.0f; |
||||||
|
|
||||||
|
float32_t re; //equivalent resistance looking into input BJT base
|
||||||
|
float32_t Rp; //resistor placed parallel with the inductor
|
||||||
|
float32_t gf; //forward gain of BJT amplifier
|
||||||
|
//High-Pass biquad coefficients
|
||||||
|
float32_t b0h, b1h, b2h; |
||||||
|
|
||||||
|
//Band-Pass biquad coefficients
|
||||||
|
float32_t b0b, b2b; |
||||||
|
float32_t a0b, a1b, a2b; |
||||||
|
|
||||||
|
//Final combined biquad coefficients used by run_filter()
|
||||||
|
float32_t b0; |
||||||
|
float32_t b1; |
||||||
|
float32_t b2; |
||||||
|
|
||||||
|
float32_t a0c; |
||||||
|
float32_t a1c; |
||||||
|
float32_t a2c; |
||||||
|
//First order high-pass filter coefficients
|
||||||
|
//y[n] = ghpf * ( x[n] - x[n-1] ) - a1p*y[n-1]
|
||||||
|
float32_t a1p; |
||||||
|
float32_t ghpf; |
||||||
|
|
||||||
|
//biquad state variables
|
||||||
|
float32_t y1; |
||||||
|
float32_t y2; |
||||||
|
float32_t x1; |
||||||
|
float32_t x2; |
||||||
|
|
||||||
|
//First order high-pass filter state variables
|
||||||
|
float32_t yh1; |
||||||
|
float32_t xh1; |
||||||
|
float32_t clip(float32_t x); |
||||||
|
float32_t sqr(float32_t x) |
||||||
|
{ |
||||||
|
return x*x; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif // _EFFECT_WAHMONO_F32_H_
|
@ -0,0 +1,153 @@ |
|||||||
|
/**
|
||||||
|
* @file filter_DCblockerStereo_F32.h |
||||||
|
* @author Piotr Zapart |
||||||
|
* @brief simple IIR based stereo DB blocking filter |
||||||
|
* @version 0.1 |
||||||
|
* @date 2024-06-01 |
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024 |
||||||
|
* 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 <https://www.gnu.org/licenses/>."
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef _FILTER_DCBLOCKERSTEREO_F32_H_ |
||||||
|
#define _FILTER_DCBLOCKERSTEREO_F32_H_ |
||||||
|
|
||||||
|
#include <AudioStream_F32.h> |
||||||
|
#include "basic_DSPutils.h" |
||||||
|
#include <arm_math.h> |
||||||
|
|
||||||
|
// y = x - xm1 + 0.995 * ym1;
|
||||||
|
// xm1 = x;
|
||||||
|
// ym1 = y;
|
||||||
|
|
||||||
|
class AudioFilterDCblockerStereo_F32 : public AudioStream_F32 |
||||||
|
{ |
||||||
|
public: |
||||||
|
AudioFilterDCblockerStereo_F32(void) : AudioStream_F32(2, inputQueueArray) |
||||||
|
{ |
||||||
|
fs_Hz = AUDIO_SAMPLE_RATE_EXACT; |
||||||
|
blockSize = AUDIO_BLOCK_SAMPLES; |
||||||
|
} |
||||||
|
|
||||||
|
AudioFilterDCblockerStereo_F32(const AudioSettings_F32 &settings) : AudioStream_F32(2, inputQueueArray) |
||||||
|
{ |
||||||
|
fs_Hz = settings.sample_rate_Hz; |
||||||
|
blockSize = settings.audio_block_samples;
|
||||||
|
} |
||||||
|
|
||||||
|
void update() |
||||||
|
{ |
||||||
|
audio_block_f32_t *blockL, *blockR; |
||||||
|
uint16_t i; |
||||||
|
float32_t tmpf32; |
||||||
|
|
||||||
|
|
||||||
|
if (bp) // handle bypass
|
||||||
|
{ |
||||||
|
blockL = AudioStream_F32::receiveReadOnly_f32(0); |
||||||
|
blockR = AudioStream_F32::receiveReadOnly_f32(1); |
||||||
|
if (!blockL || !blockR) |
||||||
|
{ |
||||||
|
if (blockL) |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
if (blockR) |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
return; |
||||||
|
} |
||||||
|
AudioStream_F32::transmit(blockL, 0); |
||||||
|
AudioStream_F32::transmit(blockR, 1); |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
return; |
||||||
|
} |
||||||
|
blockL = AudioStream_F32::receiveWritable_f32(0); |
||||||
|
blockR = AudioStream_F32::receiveWritable_f32(1); |
||||||
|
if (!blockL || !blockR) |
||||||
|
{ |
||||||
|
if (blockL) |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
if (blockR) |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
float32_t _xRegL = xRegL; |
||||||
|
float32_t _xRegR = xRegR; |
||||||
|
float32_t _yRegL = yRegL; |
||||||
|
float32_t _yRegR = yRegR; |
||||||
|
|
||||||
|
for (i=0; i<blockSize; i=i+4) |
||||||
|
{ |
||||||
|
tmpf32 = blockL->data[i] - _xRegL + k * _yRegL; |
||||||
|
_yRegL = tmpf32; |
||||||
|
_xRegL = blockL->data[i]; |
||||||
|
blockL->data[i] = _yRegL; |
||||||
|
|
||||||
|
tmpf32 = blockL->data[i+1] - _xRegL + k * _yRegL; |
||||||
|
_yRegL = tmpf32; |
||||||
|
_xRegL = blockL->data[i+1]; |
||||||
|
blockL->data[i+1] = _yRegL; |
||||||
|
|
||||||
|
tmpf32 = blockL->data[i+2] - _xRegL + k * _yRegL; |
||||||
|
_yRegL = tmpf32; |
||||||
|
_xRegL = blockL->data[i+2]; |
||||||
|
blockL->data[i+2] = _yRegL; |
||||||
|
|
||||||
|
tmpf32 = blockL->data[i+3] - _xRegL + k * _yRegL; |
||||||
|
_yRegL = tmpf32; |
||||||
|
_xRegL = blockL->data[i+3]; |
||||||
|
blockL->data[i+3] = _yRegL; |
||||||
|
|
||||||
|
tmpf32 = blockR->data[i] - _xRegR + k * _yRegR; |
||||||
|
_yRegR = tmpf32; |
||||||
|
_xRegR = blockR->data[i]; |
||||||
|
blockR->data[i] = _yRegR; |
||||||
|
|
||||||
|
tmpf32 = blockR->data[i+1] - _xRegR + k * _yRegR; |
||||||
|
_yRegR = tmpf32; |
||||||
|
_xRegR = blockR->data[i+1]; |
||||||
|
blockR->data[i+1] = _yRegR; |
||||||
|
|
||||||
|
tmpf32 = blockR->data[i+2] - _xRegR + k * _yRegR; |
||||||
|
_yRegR = tmpf32; |
||||||
|
_xRegR = blockR->data[i+2]; |
||||||
|
blockR->data[i+2] = _yRegR; |
||||||
|
|
||||||
|
tmpf32 = blockR->data[i+3] - _xRegR + k * _yRegR; |
||||||
|
_yRegR = tmpf32; |
||||||
|
_xRegR = blockR->data[i+3]; |
||||||
|
blockR->data[i+3] = _yRegR; |
||||||
|
} |
||||||
|
xRegL = _xRegL; |
||||||
|
yRegL = _yRegL; |
||||||
|
xRegR = _xRegR; |
||||||
|
yRegR = _yRegR; |
||||||
|
|
||||||
|
AudioStream_F32::transmit(blockL, 0); // send blockL on both output channels
|
||||||
|
AudioStream_F32::transmit(blockL, 1); |
||||||
|
AudioStream_F32::release(blockL); |
||||||
|
AudioStream_F32::release(blockR); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
audio_block_f32_t *inputQueueArray[2]; |
||||||
|
float32_t fs_Hz; |
||||||
|
uint16_t blockSize; |
||||||
|
float k = 0.995f; |
||||||
|
bool bp = false; // bypass flag
|
||||||
|
float32_t xRegL = 0.0f; |
||||||
|
float32_t xRegR = 0.0f; |
||||||
|
float32_t yRegL = 0.0f; |
||||||
|
float32_t yRegR = 0.0f; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif // _FILTER_DCBLOCKERSTEREO_F32_H_
|
Loading…
Reference in new issue