Skip to content

How to Add a New Codec

Phil Schatzmann edited this page Jun 3, 2025 · 19 revisions

This guide explains the steps required to add support for a board and audio codec to the arduino-audio-driver library.

1. Prepare Your Codec Source Files

  1. Create a new folder for your codec under Driver (e.g., src/Driver/mycodec/).
  2. Add your codec implementation files (e.g., mycodec.c, mycodec.h) to this folder.
    • Use existing codecs (e.g., src/Driver/wm8960/) as a reference for structure.
  • Header-only implementations are preferred for new codecs. Existing codecs are planned be migrated to header-only in the future.
  • If your codec uses I2C or SPI, use the platform abstraction APIs provided in Platforms (e.g., API_I2C.h). Do not use platform-specific or Arduino specific code directly in your codec implementation.

2. Implement the Codec API

Add a new class in DriverAPI.h that calls the functionality provided in step 1. It might look as follows:

class AudioDriverYourDriverClass : public AudioDriver {
 public:
  AudioDriverYourDriverClass() { i2c_default_address = 0x1A; }
  bool setMute(bool mute) { return xxx_set_voice_mute(mute); }
  bool setVolume(int volume) {
    this->volume = volume;
    return xxxx_set_voice_volume(limitValue(volume, 0, 100));
  };
  /// Oprionally provide volume from driver scaled from 0 to 100
  int getVolume() {
    int vol;
    xxxx_get_voice_volume(&vol);
    return vol;
  };

 protected:
  /// setup the codec
  bool init(codec_config_t codec_cfg) {
    return xxxx_init(&codec_cfg, getI2C(), getI2CAddress()) == RESULT_OK;
  }
  /// Shut down the codec 
  bool deinit() { return xxxx_deinit() == RESULT_OK; }
  /// Use DAC, ADC or both
  bool controlState(codec_mode_t mode) {
    return xxxx_ctrl_state_active(mode, true) == RESULT_OK;
  }
  /// Setup i2s basied on sample rate, bits, channels, format, master/slave
  bool configInterface(codec_mode_t mode, I2SDefinition iface) {
    return xxxx_config_i2s(mode, &iface) == RESULT_OK;
  }
};

Refer to the existing drivers in Driver.h for more detailed examples.

3. Optionally add a Pin Definition for Your Audio Board

If your audio baord comes with hardocded pins, add a new DriverPins subclass to the DriverPins.h and a global static variable that can be used in your sketch.

/**
 * @brief Pins for ....
 * @author Phil Schatzmann
 * @copyright GPLv3
 */
class PinsYourBoardClass : public DriverPins {
 public:
  PinsYourBoardClass() {
    // sd pins
    addSPI(ESP32PinsSD);
    // add i2c codec pins: scl, sda, port, frequency
    addI2C(PinFunction::CODEC, 23, 18);
    // add i2s pins: mclk, bck, ws,data_out, data_in ,(port)
    addI2S(PinFunction::CODEC, 0, 5, 25, 26, 35);

    // add other pins
    addPin(PinFunction::KEY, 36, PinLogic::InputActiveLow, 1);
    addPin(PinFunction::KEY, 39, PinLogic::InputActiveLow, 2);
    addPin(PinFunction::KEY, 33, PinLogic::InputActiveLow, 3);
    addPin(PinFunction::KEY, 32, PinLogic::InputActiveLow, 4);
    addPin(PinFunction::KEY, 13, PinLogic::InputActiveLow, 5);
    addPin(PinFunction::KEY, 27, PinLogic::InputActiveLow, 6);
    addPin(PinFunction::AUXIN_DETECT, 12, PinLogic::InputActiveLow);
    addPin(PinFunction::PA, 21, PinLogic::Output);
    addPin(PinFunction::LED, 22, PinLogic::Output, 1);
    addPin(PinFunction::LED, 19, PinLogic::Output, 2);
  }
};
/// Add this to the end of the file
static PinsYourBoardClass PinsYourBoardPins;

4. Global Static Variable for Your Board (or Generic Driver)

Add an entry at the end of AudioBoard.h to create a static varialbe for your generic driver or baord. E.g:

static AudioBoard GenericYourDriver{AudioDriverYourDriverClass, NoPins}; // Pins defined in your Sketch
static AudioBoard YourBoard{AudioDriverYourDriverClass, PinsYourBoardClass}; // if baord has defined pins 

5. Testing

For generic drivers w/o pin definitions you need to set up the pins in your sketch. e.g.

I2SCodecStream i2s(GenericYourDriver);

void setup() {
  Wire.setPins(sda_pin, scl_pin);
  Wire.begin();

  auto config = i2s.defaultConfig(TX_MODE);
  config.pin_bck = 14;
  config.pin_ws = 15;
  config.pin_data = 22;
  // config.pin_mck = 0; // optional master clock pin
  // config.i2s_format = I2S_STD_FORMAT; // default format
  // config.is_master = true; // default esp32 is master

  i2s.begin(config);

}

See this Wiki for further info.

6. Contribute

  • Ensure your code follows the style and conventions of the project.
  • Submit a pull request with your changes and documentation.

Clone this wiki locally