Audio delay and VOX using ESP32

This simple project implements an audio delay and time-shifing VOX using the ESP32S ADC and DAC capabilities.

Similar projects worth following
Simple audio delay and/or VOX implementation using ESP32

This simple and cheap project in its standard form implements an  audio delay using an inexpensive ESP32S NodeMCU  board and incorporates an optional VOX to trigger a transmitter with the delayed audio so that said audio is not lost due to VOX response time, key-up delays or CTCSS processing delays at endpoint receivers.  It was built for a simple one way cross band rebroadcaster which uses off the shelf portable two way radios, but you could use it in any circuit that needed an audio delay if hi fidelity wasn't a requirement.

I've also included the code for the delay only, (no VOX).  This code supports a (practical) audio delay of up to about 12 seconds at a  nominal 10k/s sampling rate (depending on typically available heap memory), or proportionately less delay at higher sampling rates (automatic, although I've capped the maximum sample rate at 40k/s).

Why bother?

When I first decided to do this I found there didn’t seem to be much on the internet that dealt with the sort of audio delay I needed; mostly stuff for music echo/reverb effects with fairly ordinary performance using the ubiquitous PT2399 IC   hence this RYO approach.  The simple ability to add VOX in the same program was a bonus.  It is by no means a complex or cutting edge project, just something useful.

Update: I have since found a kit from the Electric Druid that might suit folks who are just after a delay, no vox. see:

Why use the ESP32?

Because a friend suggested it, because it's cheap, powerful and has an "adequate" ADC and DAC on board along with a decent size memory - and because I could program it using the Arduino IDE instead of having to learn a new language or development process.  OK, yes, it doesn't use the wifi, bluetooth etc.. facilities, so again, yes, it's the proverbial sledgehammer cracking a nut.


Status: working in basic form

To do: finish boxing up the working prototype for field trials.

General discussion

Performance of the delay is not bad for voice at a sample rate of 20k/sec, and the original test lashup can get by without any anti-aliasing filter on the input, probably because the audio response on the incoming receiver is too poor to carry much in the way of non-voice frequencies, and the input on the transceiver is likewise not too fussy.

The program allows for extension of the delay up to about 10 seconds at progressively lower sample rates.

Time shift VOX mode

In VOX mode, the input audio stream is continuously stored in a ring buffer.  The processor keeps a running average of the input level over a configurable period of samples (0.3 seconds in prototype).   If this exceeds a threshold,  the VOX is triggered, raising a transmit signal so the radio which sees the delayed audio is immediately set to transmit and the output DAC is enabled thus starting to send recorded audio from a defined delay time before the VOX was triggered (time shift).  

The VOX/transmit remains triggered until input audio is stopped and stays triggered for a full delay period plus a small bit extra (the Tail) before turning off the radio transmitter transmit signal.  

The idea is to compensate for missing audio due to delays in VOX triggering.  By transmitting a bit of silence before the payload audio, you can also compensate for slow key-up of the transmitter and slow triggering of the eventual receiver.  

The unit can be used with transceivers that don't have a separate transmit line but do have their own internal VOX.

I have also added the ability to insert a beep at the start of the delayed output audio.

The VOX as implemented...

Read more »

Updated delay program with small code fixes and tabbed source, better comments

x-zip-compressed - 3.18 kB - 09/13/2021 at 06:36


Updated delay with VOX code. General tidy up and automatic calculation of optimum memory use and sample rate. Also set up with tabs for readability and more comments. Some small non-fatal bug fixes.

application/x-zip-compressed - 10.23 kB - 09/10/2021 at 05:54



Basic timing diagram for time shifting VOX

JPEG Image - 41.23 kB - 12/18/2018 at 02:33



Revised hookup for ESP32S with VOX adjustment pot

JPEG Image - 46.81 kB - 12/16/2018 at 02:04



Test of the repeater. Note you can see the signal strength meter on the receiver on the left show the incoming transmission. The transmitter on the right shows it transmitting the start beep almost immediately (which we are hearing through a separate CB receiver off camera) and then we hear the delayed transmitted audio about a second later. If you look closely, you can see the LED on the ESP32 light up as well.

MPEG-4 Video - 3.17 MB - 12/13/2018 at 21:34


View all 11 files

  • Updated source files

    J Reynoldson09/13/2021 at 06:41 0 comments

    Source files for both the simple delay and VOX repeater have been updated.

    Along with better commented tabbed code, there are some simple fixes and one major change, being the way the leading beep is implemented in the repeater. The original calculated waveform actually caused lost interrupts not being serviced due to floating point delays.  A lookup table for a sine wave had reduced overhead by a factor of 4.

  • Updated delay-only code, better use of heap storage, best sample rate

    J Reynoldson12/17/2018 at 08:02 0 comments

    The delay-only code has been updated so that the only thing that needs to be configured is the delay time in seconds.  The program automatically allocates the biggest buffer it can from heap space and increases the sample rate to the maximum for best quality. However, the sample rate is capped at 40k/sec as in practice the quality is really going to be limited by the 256 level output of the Digital/Analog converter.   A 12 second delay still results in quite reasonable sound.

  • Added pre-transmission beep

    J Reynoldson12/11/2018 at 01:06 0 comments

    As I wanted to be able to use transmitters that didn't externalise the PTT, and also because I wanted to alert the final receivers that the transmission was a crossband one, I have added a beep that sounds before the delayed voice.  This can be heard by the receivers, and also serves to give the transmitter VOX something to trigger it quickly.

    In addition, I added a flag to stop DAC output unless the delay VOX was triggered so that the quiescent input signal to the transmitter VOX would be as quiet as possible.

    Code update soon.

  • Filters built and tested

    J Reynoldson12/10/2018 at 04:26 0 comments

    10 Dec 18: Added circuit diagram for an antialiasing filter which can also be used as a smoothing filter for the DAC output for sampling rates above 20000/sec.

  • Back in business

    J Reynoldson12/10/2018 at 02:49 0 comments

    With a new ESP32S I was able to test the pre and post filters.  The result looks pretty clean (see the project gallery for some scope shots of input and output).

  • Slight hiccup

    J Reynoldson12/09/2018 at 22:42 0 comments

    10 Dec 2018:  While trying out an anti-aliasing filter, I accidentally let the magic smoke out of my test rig.  Waiting for a replacement ESP32!

  • Initial version

    J Reynoldson12/04/2018 at 21:52 0 comments

    05-Dec-2018:  Posted first iteration.  This version works, but includes no external filtering or antialiasing circuitry to get optimum results.

View all 7 project logs

  • 1
    Getting Started - the software!

    I'm going to assume you're not a noob to building electronics because, after all, this is just a functional block that you're going to be placing in your own larger project.  Hence there will be no egg-sucking tutorials.  Google it if you don't feel up to speed with anything.   However, I'm going to assume that maybe you've never had much to do with the Arduino development environment.

    You're going to need an ESP32 based board and you're going to need a way to program it.

    The board is easy.  Search Ebay for "ESP32S NodeMCU" and you will find a nice board which includes a USB connector, can be run directly from 5V (it has its own 3.3V regulator) and all the exposed IO pins you could ask for as well as an onboard LED you can flash.  Buy it.  

    These instructions are for Windows.  Me no do Linux, or apple-ly 'puters.   Also, I only show the normally successful path.  Who knows what horrors might happen;  if things go pear shaped, try Googling the error.  It mostly works for me.

    The development environment is pretty simple too. If you haven't already, download and install the latest Arduino Integrated Development Environment (IDE) package from  and fire it up.

    Go to File>Preferences and you will find a spot marked "Additional Boards Manager URLs".  Click on the icon to the right of this and add the line ""  and press OK.

    Then go back and goto Tools>Boards:something>Boards Manager.  Wait for this to populate the list, then enter "ESP32" in the search line.  From the list, select "ESP32 by Expressif Systems" and click on "INSTALL".   

    Once installation is complete, go back to Tools>Board:something>  and from the huge list of boards, select "NodeMCU-32S"

    You are ready to rock!

    Try to load the project code.  It will probably prompt you to create a directory (most likely in My Documents>Arduino) to store it in. That's fine.

    You can then try a test compile (Sketch>verify/compile) to make sure all is well with the libraries.

  • 2
    Uploading code to the NodeMCU board

    Connect a microUSB cable to the board and a spare USB socket.  

    The appropriate device driver should load and a new COM port will appear in the list of com ports on the IDE: Tools>Port.  Choose it.

    Select an upload speed of 115200.  Then select Sketch>Upload

    The compile will complete and you will see a message:  "Connecting.....____..." indicating that it's waiting for connection (which means it's waiting to talk to the board bootloader program).

    Press and hold the BOOT button on the board until the program starts being written.

    The message"Hard resetting via RTS pin..."  is your cue to celebrate a successful upload.  The program is now running!

  • 3
    Things you need to know about the ESP32

    The ESP32 itself runs on 3.3V.  Don't put more than 3.3V on an input pin. You may let the magic smoke out.

    The NodeMCU implementation includes a 3.3V regulator and includes an USB interface so you don't have to muck about with USB to Serial converters.  You can apply 5V to the Vin pin in the production setup to run the unit.

    When programming the board, you need to press the BOOT button while the programming software is trying to upload.  This starts the boot loader routine and the board and the programming software will then hopefully start talking.

    The analogue inputs take 0-3.3 v with a corresponding reading of 0-4095.  The DAC outputs have only 0-255 levels for the same 0-3.3V output.

View all 3 instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates