Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
2K views255 pages

Practical Audio DSP Projects With The Esp32 Ebook

The document is a publication titled 'Practical Audio DSP Projects with the ESP32' authored by Dogan Ibrahim and Ahmet Ibrahim, focusing on digital signal processing using the ESP32 microcontroller. It includes detailed chapters on the ESP32 architecture, development boards, and various projects utilizing the Arduino IDE. The book is intended for educational purposes, with all rights reserved and a disclaimer regarding the accuracy of the information provided.

Uploaded by

Horacio M
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2K views255 pages

Practical Audio DSP Projects With The Esp32 Ebook

The document is a publication titled 'Practical Audio DSP Projects with the ESP32' authored by Dogan Ibrahim and Ahmet Ibrahim, focusing on digital signal processing using the ESP32 microcontroller. It includes detailed chapters on the ESP32 architecture, development boards, and various projects utilizing the Arduino IDE. The book is intended for educational purposes, with all rights reserved and a disclaimer regarding the accuracy of the information provided.

Uploaded by

Horacio M
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 255

books

books

Practical
Audio DSP Projects
with the ESP32
Easy and Affordable Digital Signal Processing

ON STAGE
ESP32 DevKitC
/DAC
Pmod I2S2 ADC
Ts
FIR, IIR, & the FF

guration
hone pin confi
// I2S microp
//
in_MIC()
void i2s_setp
{ n_config =
n_config_t pi
const i2s_pi
{ C,
= I2S_SCK_MI
.bck_io_num
I2S_WS_MIC, // No output
.ws_io_num = NO_CHANGE,
m = I2S_PIN_ // Input from
.data_out_nu
= I2S_SD_MIC
.data_in_num
}; in_config);
I2S_PORT0, &p
i2s_set_pin(
}

Dogan Ibrahim
Ahmet Ibrahim
Practical Audio DSP Projects
with the ESP32
Easy and Affordable Digital Signal Processing


Dogan Ibrahim
Ahmet Ibrahim

Practical Audio DSP Projects with the ESP32 - UK.indd 3 06-07-2023 10:40
● This is an Elektor Publication. Elektor is the media brand of
Elektor International Media B.V.
PO Box 11, NL-6114-ZG Susteren, The Netherlands
Phone: +31 46 4389444

● All rights reserved. No part of this book may be reproduced in any material form, including photocopying, or
storing in any medium by electronic means and whether or not transiently or incidentally to some other use of this
publication, without the written permission of the copyright holder except in accordance with the provisions of the
Copyright Designs and Patents Act 1988 or under the terms of a licence issued by the Copyright Licencing Agency
Ltd., 90 Tottenham Court Road, London, England W1P 9HE. Applications for the copyright holder's permission to
reproduce any part of the publication should be addressed to the publishers.

● Declaration
The author, editor, and publisher have used their best efforts in ensuring the correctness of the information contained
in this book. They do not assume, and hereby disclaim, any liability to any party for any loss or damage caused by
errors or omissions in this book, whether such errors or omissions result from negligence, accident or any other cause.
All the programs given in the book are Copyright of the Author and Elektor International Media. These programs
may only be used for educational purposes. Written permission from the Author or Elektor must be obtained before
any of these programs can be used for commercial purposes.

● British Library Cataloguing in Publication Data


A catalogue record for this book is available from the British Library

● ISBN 978-3-89576-567-4 Print


ISBN 978-3-89576-568-1 eBook

● © Copyright 2023: Elektor International Media B.V.


Editor: Jan Buiting
Prepress Production: D-Vision, Julian van den Berg

Elektor is the world's leading source of essential technical information and electronics products for pro engineers,
electronics designers, and the companies seeking to engage them. Each day, our international team develops and delivers
high-quality content - via a variety of media channels (including magazines, video, digital media, and social media) in
several languages - relating to electronics design and DIY electronics. www.elektormagazine.com

●4

Practical Audio DSP Projects with the ESP32 - UK.indd 4 06-07-2023 10:40
Contents

Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Chapter 1 • The ESP32 Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

1.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

1.2 The ESP32 architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

1.2.1 The CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

1.2.2 Internal memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.3 External memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.4 General purpose timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.5 Watchdog timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.6 The system clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.7 Real-time clock (RTC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.8 General purpose input-outputs (GPIOs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.9 Analog to digital converter (ADC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2.10 Digital to analog converter (DAC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.11 Hall sensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.12 Built-in temperature sensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.13 Touch sensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.14 UART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2 15 I2C interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.16 I2S interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.17 Infrared controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.18 Pulse width modulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.19 LED PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.2.20 Pulse counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.2.21 SPI interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.2.22 Hardware accelerators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.2.23 Wi-Fi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.2.24 Bluetooth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.2.25 Controller area network (CAN) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.2.26 SD card support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

●5

Practical Audio DSP Projects with the ESP32 - UK.indd 5 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

1.3 ESP32 development boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Chapter 2 • The ESP32 DevKitC Development Board . . . . . . . . . . . . . . . . . . . . . . . 20

2.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.2 ESP32 DevKitC hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

Chapter 3 • Using the Arduino IDE with the ESP32 DevKitC . . . . . . . . . . . . . . . . . . 23

3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

3.2 Installing the Arduino IDE for the ESP32 DevKitC . . . . . . . . . . . . . . . . . . . . . . . . 23

Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC . 30

4.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4.2 Project 1: Alternately flashing LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4.3 Project 2: Binary up/down counter with LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

4.4 Project 3: Changing the brightness of an LED . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4.5 Project 4: Thermometer with output displayed on Serial Monitor . . . . . . . . . . . . . 41

4.6 Project 5: LCD-based event counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

4.7 Project 6: Generating waveforms — Sawtooth . . . . . . . . . . . . . . . . . . . . . . . . . . 50

4.8 Project 7: Using SD cards — Writing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

4.9 Project 8: Using SD cards — Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

4.10 ESP32 DevKitC network programming with the Arduino IDE . . . . . . . . . . . . . . . . 62

4.10.1 Project 9: Scanning the surrounding WiFi networks . . . . . . . . . . . . . . . . . . . . 62

4.10.2 Project 10: Controlling LEDS connected to ESP32 DevKitC from a mobile phone 64

4.11 Project 11: Bluetooth classic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

Chapter 5 • Sound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

5.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

5.2 Audible sound waves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

5.3 Analog and digital audio sound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

5.4 Digital audio sound file formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

5.4.1 Uncompressed audio file formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

5.4.2 Audio files with lossy compression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

5.4.3 Audio files with lossless compression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

5.4.4 Which audio file format to choose? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

5.5 High-quality digital audio sound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

Chapter 6 • Audio DSP Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

●6

Practical Audio DSP Projects with the ESP32 - UK.indd 6 06-07-2023 10:40
Contents

6.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

6.2 The I2S bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

6.3 I2S support of popular microcontroller development boards . . . . . . . . . . . . . . . . . 85

6.4 The ESP32 DevKitC I2S bus pins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

6.5 Project 1: Using a digital microphone to capture audible sound . . . . . . . . . . . . . . 86

6.6 Project 2: Using an amplifier and loudspeaker . . . . . . . . . . . . . . . . . . . . . . . . . . 93

6.7 Project 3: Playing MP3 music stored on an SD card . . . . . . . . . . . . . . . . . . . . . . 102

6.8 Project 4: Playing a list of music files (playlist) . . . . . . . . . . . . . . . . . . . . . . . . . 106

6.9 Project 5: Internet radio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

6.10 Project 6: Text to speech (TTS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

6.11 Project 7: Play all songs on the SD card . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

6.12 Project 8: Play all songs on the SD card — using an external volume control . . . 119

6.13 Project 9: Internet radio in stereo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

6.14 Project 10: Internet radio in stereo with volume control . . . . . . . . . . . . . . . . . 122

6.15 Project 11: Playing an MP3 file stored in the flash memory . . . . . . . . . . . . . . . 123

6.16 Project 12: List of files stored in the flash memory . . . . . . . . . . . . . . . . . . . . . 128

6.17 Project 13: Speaking event counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Chapter 7 • Discrete-Time Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

7.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

7.2 The sampling process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

7.3 Some digital signal types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

7.3.1 Unit step function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

7.3.2 Sinusoidal signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

7.3.3 Exponential signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

7.3.4 Exponential sinusoidal decay signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

7.4 Block diagram representation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

7.4.1 Block diagram manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

7.5 The convolution process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

Chapter 8 • The Z-Transform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

8.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

8.2 Unit step function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

8.3 Unit ramp function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

●7

Practical Audio DSP Projects with the ESP32 - UK.indd 7 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

8.4 Sine function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

8.5 Discrete impulse function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

8.6 The z-Transform of a function expressed as a Laplace Transform . . . . . . . . . . . . 146

8.7 Inverse z-transforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

8.7.1 Coefficients of partial fraction expansion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

Chapter 9 • Digital Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

9.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

9.2 FIR Filters and IIR Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

9.3 The Digital Filter Design Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

Chapter 10 • Designing FIR Digital Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

10.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

10.2 Truncation and windowing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

10.2.1 Rectangular window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

10.2.2 Hamming window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

10.2.3 Hanning Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

10.2.4 Blackman Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

10.2.4 Kaiser window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

10.2.5 Remez Exchange-based design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

10.3 Using computer-aided techniques for the design of FIR filters . . . . . . . . . . . . . 168

10.3.1 ScopeFIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

10.3.2 Dr A R Collins FIR filter design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

10.4 FIR digital filter structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

10.4.1 Direct FIR structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

10.4.2 Cascade FIR structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

Chapter 11 • Design Of IIR Digital Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

11.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

11.2 IIR filter transfer function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

11.3 Analog filter design review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

11.4 Butterworth filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

11.4.1 Bilinear transformation method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182

11.5 Chebyshev filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

●8

Practical Audio DSP Projects with the ESP32 - UK.indd 8 06-07-2023 10:40
Contents

11.6 Elliptic filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190

11.7 Computer-aided design tools for the design of IIR digital filters . . . . . . . . . . . . 191

11.7.1 The ScopeIIR filter design program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

11.7.2 The Digital Filter Analyzer IIR design program . . . . . . . . . . . . . . . . . . . . . . . 192

11.8 IIR filter structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

11.8.1 Direct structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

11.8.2 Cascade structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC . . . . . . . . . . . 196

12.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196

12.2 The PCSGU250 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196

12.3 Arduino Audio Tools library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197

12.4 Project 1: Sinewave generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198

12.5 Project 2: Signal input-output with two independent I2S ports . . . . . . . . . . . . . 202

12.6 Project 3: Signal input-output using a shared I2S port . . . . . . . . . . . . . . . . . . . 207

12.7 Project 4: Designing a FIR low-pass digital filter . . . . . . . . . . . . . . . . . . . . . . . 210

12.8 Project 5: Design of a FIR band-pass filter . . . . . . . . . . . . . . . . . . . . . . . . . . . 215

12.9 Project 6: Design of a FIR high-pass filter . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

12.10 Design of FIR digital filters from the first principles (without using a library) . . 218

12.10.1 ESP32 timers and timer interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219

12.10.2 Project 7: Flashing an LED using timer interrupts . . . . . . . . . . . . . . . . . . . . 222

12.10.3 Project 8: Timer interrupt-driven FIR low-pass filter program . . . . . . . . . . . 223

12.10.4 More efficient FIR digital filter program . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

12.10.5 Project 9: An efficient FIR low-pass filter . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Chapter 13 • Designing IIR Digital Filters with the ESP32 DevKitC . . . . . . . . . . . 235

13.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

13.2 Project 1: Design of an IIR low-pass filter . . . . . . . . . . . . . . . . . . . . . . . . . . . 235

13.3 IIR filters of any order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238

13.4 Design of IIR filters without using a filter library . . . . . . . . . . . . . . . . . . . . . . . 239

13.4.1 The IIR filter algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239

13.4.2 Project 2: Design of IIR low-pass filter from the first principles . . . . . . . . . . . 239

Chapter 14 • Fast Fourier Transform (FFT) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

●9

Practical Audio DSP Projects with the ESP32 - UK.indd 9 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

14.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

14.2 Why FFT? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

14.3 Project 1: FFT of an input signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

Appendix A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248

Bill of Materials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248

Appendix B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

● 10

Practical Audio DSP Projects with the ESP32 - UK.indd 10 06-07-2023 10:40
Preface

Digital Signal Processing (DSP) is the process of capturing, analyzing, and manipulating
analog or digital signals by any type of digital processor including digital computers and
microcontrollers.

The theory of DSP is quite complex and requires a good understanding of higher-level
mathematics and discrete time systems. Students new to DSP are usually taught the the-
ory in great detail with very few or no practical applications. For example, in many cases a
student can derive complex equations for digital filters or Fast Fourier Transforms (FFT) but
is unable to implement a simple digital filter in real life. Some institutions use tools such
as MATLAB to derive the coefficients of digital filters and then to simulate the behavior of
these filters on a PC. Although simulation can be an invaluable tool in teaching, it is never
the same as real-time or real-life implementations.

The aim of this book is to teach the basic principles of DSP and to introduce DSP from a
practical point of view using the bare minimum of mathematics. The level of discrete-time
systems theory is sufficient to permit implementing DSP applications in real time. The
emphasis of the book is on practical aspects of DSP such as design issues and real-time
implementation issues. The practical implementation is described using the highly popular
and widely available, low-cost, ESP32 DevKitC microcontroller development board enabling
readers to easily and quickly design as well as implement DSP applications running in real
time. The architectures of dedicated DSP processors are complex and this adds additional
exertion to students who may want to implement DSP applications using such tools.

Using the ESP32 microcontroller, readers should be able to implement DSP applications
with sampling frequencies within the audio range. Programming is accomplished using the
well-liked and widely available Arduino IDE and the C language compiler. The DSP pro-
jects given in the book are based on using the I2S bus. The standard ESP32 processor is
equipped with two independent I2S bus modules that can easily be interfaced to I2S-com-
patible digital microphones or amplifiers.

The early sections of the book include simple projects using basic electronic components
such as LEDs, LCD, sensors, and pushbuttons. These sections are aimed to provide a review
of the basic programming concepts of the ESP32 processor using the Arduino IDE.

Later sections of the book include audio-based sound and DSP projects, including the fol-
lowing:

• Using I2S-based digital microphone to capture audio sound


• Using I2S-based class D audio amplifier and speaker
• Playing MP3 music stored on an SD card via I2S-based amplifier and speaker
• Playing a list of MP3 music files stored on an SD card via I2S-based amplifier
and speaker
• Playing MP3 music files stored in ESP32 flash memory via I2S-based amplifier
and speaker

● 11

Practical Audio DSP Projects with the ESP32 - UK.indd 11 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

• Internet radio with I2S-based amplifier and speaker


• Internet radio in stereo with dual I2S-based amplifiers and speakers
• Text-to-speech with I2S-based amplifier and speaker
• Using volume control in I2S-based amplifier and speaker systems
• Speaking event counter with I2S-based amplifier and speaker
• Sinewave generator with desired frequency on I2S-based amplifier and speaker
• Digital low-pass and band-pass FIR design using external ADC and DAC
• Digital low-pass and band-pass IIR filter design using external ADC and DAC
• Fast Fourier Transform (FFT)

This book is primarily intended for students and practicing engineers who may want to
learn the practical implementation of audio sound projects and DSPs in real time. Some
working knowledge of MATLAB will be useful, especially in understanding the theory of dis-
crete-time systems, Z-transforms, digital filters, and FFT. Previous knowledge of advanced
electronics is not necessary but readers should have a basic understanding of electronics
and electronic systems. Also, previous knowledge of the C programming language, espe-
cially in an Arduino IDE environment with an ESP32 processor will be invaluable.

We hope that you find the book useful and enjoyable, and swiftly get to developing your
next audio-based projects based on the ideas given in this book.

Prof Dr Dogan Ibrahim, BSc MSc PhD CEng FIET


Ahmet Ibrahim, BSc MSc
London, June 2023

● 12

Practical Audio DSP Projects with the ESP32 - UK.indd 12 06-07-2023 10:40
Chapter 1 • The ESP32 Processor

Chapter 1 • The ESP32 Processor

1.1 Overview
The ESP8266 from Espressif has been a highly popular processor costing less than $10.
It is basically a WiFi enabled microcontroller with GPIOs that can be used in small moni-
toring and control applications. The ESP8266 has been developed by Shanghai-based Chi-
nese manufacturer Espressif Systems and incorporates a full TCP/IP stack. There is a vast
amount of information, tutorials, datasheets, applications notes, books, and projects based
on the ESP8266. Several companies have created small development boards based on this
processor, such as the ESP8266 Arduino and NodeMCU series.

Espressif has released a new and more powerful processor than the ESP8266, called the
ESP32. Although ESP32 has not been developed to replace the ESP8266, it improves on it
in many aspects. The new ESP32 processor not only has WiFi support but it also has a Blue-
tooth communications module, making the processor communicate with Bluetooth-compat-
ible devices. The ESP32 CPU is the 32-bit Xtensa LX6 which is very similar to the ESP8266
CPU, but in addition it has two cores, more data memory, more GPIOs, higher CPU speed,
ADC converters with higher resolution, DAC converter, and CAN bus connectivity.

The basic specifications of the ESP32 processor are summarized below:


• 32-bit Xtensa RISC CPU: Tensilica Xtensa LX6 dual-core microcontroller
• Operation speed 160 to 240 MHz
• 520 KB SRAM memory
• 448 KB ROM
• 16 KB SRAM (in RTC)
• IEEE 802.11 b/g/ne/I Wi-Fi
• Bluetooth 4.2
• 18 12-bit ADC channels
• 2 8-bit DAC channels
• 10 touch sensors
• Temperature sensor
• 36 GPIOs
• 4 × SPI
• 2 × I2C
• 2 × I2S
• 3 × UART
• 1 × CAN bus 2.0
• SD memory card support
• 2.2 V – 3.36 V operation
• RTC timer and watchdog
• Hall sensor
• 16 channels PWM
• Ethernet interface
• Internal 8 MHz, and RC oscillator
• External 2 MHz – 60 MHz and 32 kHz oscillator
• Cryptographic hardware acceleration (AES, HASH, RSA, ECC, RNG)

● 13

Practical Audio DSP Projects with the ESP32 - UK.indd 13 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

• IEEE 802.11 security features


• 5 µA sleep current

Table 1.1 shows comparison of the basic features of ESP32 and ESP8266 processors.

Specifications ESP32 ESP8266


CPU 32-bit Xtensa L106 dual-core 32-bit Xtensa LX6 dual-core
Operating frequency 160 MHz 80 MHz
Bluetooth Bluetooth 4.2 None
Wi-Fi Yes (HT40) Yes (HT20)
SRAM 512 KB 160 KB
GPIOs 36 17
Hardware PWM 1 None
Software PWM 16 8
SPI/I2C/I2S/UART 4/2/2/2 2/1/2/2
CAN 1 None
ADC 12-bit 10-bit
Touch sensor 10 None
Temperature sensor 1 None
Ethernet MAC interface 1 None

1.2 The ESP32 architecture


Figure 1.1 shows the functional block diagram of the ESP32 processor (see ESP32 Data-
sheet, Espressif Systems). At the heart of the block is the dual-core Xtensa LX6 processor
and memory. On the left-hand side, you can see the peripheral interface blocks such as
SPI, I2C, I2S, SDIO, UART, CAN, ETH, IR, PWM, temperature sensor, touch sensor, DAC,
and ADC. The Bluetooth and WiFi modules are situated on the top middle part of the block
diagram. The clock generator and the RF transceiver are located on the top right-hand of
the block. The middle right hand is reserved for the cryptographic hardware accelerator
modules such as the SHA, RSA, AES, and RNG. Finally, the bottom middle part is where the
RTC, PMU, co-processor, and the recovery memory are.

● 14

Practical Audio DSP Projects with the ESP32 - UK.indd 14 06-07-2023 10:40
Chapter 1 • The ESP32 Processor

Figure 1.1: Functional block diagram of the ESP32 processor.

Figure 1.2 shows the system structure, consisting of two core Harvard architecture CPUs
named PRO_CPU (for Protocol CPU) and APP_CPU (for Application CPU). The modules in the
middle of the two CPUs are common to both CPUs. Detailed information about the internal
architecture of the ESP32 can be obtained from the ESP32 Technical Reference Manual,
Espressif Systems. Some information about the internal modules is given below.

Figure 1.2: System structure.

1.2.1 The CPU


The CPU can operate at up to 240 MHz and supports 7-stage pipelining with a 16/24-bit
instruction set. Floating-Point Unit and DSP instructions such as a 32-bit multiplier, 32-bit
divider, and 40-bit MAC are supported. Up to 70 external and internal interrupt sources with
32 interrupt vectors are available. Debugging can be done with the JTAG interface.

● 15

Practical Audio DSP Projects with the ESP32 - UK.indd 15 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

1.2.2 Internal memory


In terms of memory, 520 KB SRAM and 448 KB ROM (for booting) are available on-chip.
The Real-Time Clock module contains 8 KB slow memory and 8 KB fast memory. 1 Kbit of
eFuse is available with 256 bits used for the MAC address and chip configuration, and the
remaining 768 bits reserved for customer applications.

1.2.3 External memory


Up to four 16 MB external flash and SRAM memory devices are supported which can be
accessed through a high-speed cache. Up to 16 MB of the external flash are mapped onto
the CPU code space and up to 8 MB of the external flash/SRAM are mapped onto the CPU
data space. Although data reading is supported both on flash and SRAM, data writing is
supported on SRAM only.

1.2.4 General purpose timers


Four 64-bit general purpose software controllable timers are supported by the ESP32 pro-
cessor. The timers have 16-bit prescalers (2 to 65535) and auto-reload up/down counters.
The timers can generate interrupts if configured.

1.2.5 Watchdog timers


Three watchdog timers with programmable timeout values are available. Two watchdog
timers, called the main Watchdog Timers are inside the general purpose timers, while the
third one, called the RTC Watchdog Timer, is inside the RTC module. The actions taken when
a watchdog timer resets can be one of: interrupt, CPU reset, core reset, and system reset.

1.2.6 The system clock


An external crystal clock controls the system timing when the processor is reset. The clock
frequency is typically 160 MHz configured with the help of a PLL.

An 8 MHz accurate internal clock is also available. The programmer can either select the
external or the internal clock.

1.2.7 Real-time clock (RTC)


An RTC is provided that can be clocked using an external 32 kHz crystal, an internal RC
oscillator (typically 150 kHz), an internal 8 MHz oscillator, or an internal 31.25 kHz clock
derived by dividing the 8 MHz internal oscillator by 256.

1.2.8 General purpose input-outputs (GPIOs)


There are 34 GPIOs that can be configured as digital, analog, or as a capacitive touch
screen. Digital GPIOs can be configured to have internal pull-up resistors or pull-down re-
sistors or set to a high impedance state. Input pins can be configured to accept interrupts
on either edge or on level changes.

1.2.9 Analog to digital converter (ADC)


The ESP32 processor includes 18 channels of 12-bit ADC. Small analog voltages can be
measured by configuring some of the pins as programmable gain amplifiers.

● 16

Practical Audio DSP Projects with the ESP32 - UK.indd 16 06-07-2023 10:40
Chapter 1 • The ESP32 Processor

1.2.10 Digital to analog converter (DAC)


The ESP32 processor includes two independent 8-bit DACs.

1.2.11 Hall sensor


A Hall effect sensor is available on the processor based on a resistor. A small voltage that
can be measured by the ADC is developed when the sensor is inside a magnetic field.

1.2.12 Built-in temperature sensor


An analog internal temperature sensor is available that can measure the temperature in the
range of –40 ºC to +125 ºC. The measured temperature is converted into digital form using
an ADC. The measurement is affected by the temperature of the chip and the modules
active inside the chip and thus, the temperature sensor is only suitable to measure tem-
perature changes rather than measuring the absolute temperature.

1.2.13 Touch sensor


Up to 10 capacitive touch sensors are provided that can detect the capacitive changes when
a GPIO pin is in direct contact with a finger or any other suitable object.

1.2.14 UART
Three UARTs with speeds up to 5 Mbps are provided for RS232, RS485 and IrDA serial
communications.

1.2 15 I2C interface


The ESP32 processor supports up to two I2C bus interfaces that can be configured in "mas-
ter" or "slave" modes. The interface supports 400 Kbits/s fast transfer mode with 7-bit/10-
bit addressing mode. External devices compatible with the I2C bus can be connected to
these pins.

1.2.16 I2S interface


ESP32 processor supports up to two I2S bus interfaces that can be configured in master or
slave modes, in full or half duplex. The clock frequency can be from 10 kHz to 40 MHz. The
I2S interface is used in digital audio processing applications and will be used in all of the
audio DSP projects in this book.

1.2.17 Infrared controller


Up to 8 channels of programmable infrared remote controller transmissions are supported
by ESP32. The transmitting and receiving waveforms can be stored in shared 512 × 32-bit
memory.

1.2.18 Pulse width modulation


Pulse Width Modulation (PWM) is used to control devices such as motors, electric heaters,
smart lights and so on. ESP32 offers one programmable hardware PWM module and 16
software configurable PWM modules.

● 17

Practical Audio DSP Projects with the ESP32 - UK.indd 17 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32 Chapter 1 • The ESP32 Processor

1.2.19 LED PWM


The LED PWM can be used to generate up to 16 independent digital waveforms with con-
figurable duty cycles and periods. The duty cycle can be changed by software in a step-by-
step mode.

1.2.20 Pulse counter


Up to 8 channels of pulse counters are provided to capture pulses and count pulse edges.
An interrupt can be generated when the count reaches a pre-defined value.

1.2.21 SPI interface


Up to 4 SPI interfaces are supported by ESP32 in master and slave modes. External devices
compatible with the SPI bus interface can be connected to these pins.

1.2.22 Hardware accelerators


ESP32 supports hardware accelerators for implementing mathematical operations on algo-
rithms such as AES, SHA, RSA and ECC. These accelerators help to increase the operation
speed and also reduce the software complexity.

1.2.23 Wi-Fi
ESP32 includes a WiFi module that can be used in projects to communicate with other WiFi
devices, such as mobile phones, PCs, laptops, iPads, etc., through a network router.

1.2.24 Bluetooth
A Bluetooth module is included on the ESP32 processor. With the help of this module, you
can develop projects to communicate with other Bluetooth-compatible devices, such as
mobile phones, PCs, iPads, and others.

1.2.25 Controller area network (CAN)


ESP32 includes a CAN bus controller that can be programmed to communicate with other
ESP32 processors or other CAN bus-compatible devices.

1.2.26 SD card support


ESP32 supports SD memory cards, thus making it possible to store data, for example, on
a memory card.

1.3 ESP32 development boards


The ESP32 chip is highly complex and cannot easily be used on its own. There are several
development boards available in the marketplace based on the ESP32 chip. These devel-
opment boards incorporate the ESP32 chip and associated hardware to simplify the task of
project development based on the ESP32.

● 18

Practical Audio DSP Projects with the ESP32 - UK.indd 18 06-07-2023 10:40
Chapter 1 • The ESP32 Processor

Some popular ESP32 development boards available at the time of authoring this book in-
clude:
• SparkFun ESP32 thing
• Geekcreit ESP32 Development Board
• HiLetgo ESP-WROOM-32 Development Board
• LoLin32 ESP32 Development Board
• Pycom LoPy Development Board
• ESP32 OLED Development Board
• Makerfocus ESP32 Development Board
• ESPS32 Test Board
• ESP32-EVB
• ESP32 Development Board by Pesky Products
• MakerHawk ESP32 Development Board
• Huzzah32 Development Board
• ESPea32
• NodeMCU-32s
• Node32S
• ESP32 DevKitC

● 19

Practical Audio DSP Projects with the ESP32 - UK.indd 19 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 2 • The ESP32 DevKitC Development Board

2.1 Overview
In the last chapter, you had a look at the architecture of the ESP32 processor and its basic
features and advantages. You have also read about some of the popular ESP32 develop-
ment boards available in the marketplace.

Currently, ESP32 DevKitC is one of the most popular development boards based on the
ESP32 processor. In this book, all projects to replicate at home or in your lab are based on
this development board. It is therefore important that you learn the architecture and the
features of this board in detail.

In this chapter, you will be looking at the features of the ESP32 DevKitC development board
in greater detail.

2.2 ESP32 DevKitC hardware


The ESP32 DevKitC is a small ESP32 processor-based board developed manufactured by
Espressif. As shown in Figure 2.1, the board is breadboard compatible and has the dimen-
sions 55 mm × 27.9 mm. The one used in this book had the marking ESPRESSIF ESP32-
WROOM-32D on its metal plate.

Figure 2.1: ESP32 DevKitC development board.

The board has two connectors located along each side of the board for GPIO, clock, and
power line interfaces. Each connector has 19 pins. As shown in Figure 2.2, the two connec-
tors carry the following signals:

Left Connector Right Connector


+3.3V GND
EN IO23
SVP IO22
SVN TXD0
IO34 RXD0
IO35 IO21
IO32 GND
IO33 IO19
IO25 IO18

● 20

Practical Audio DSP Projects with the ESP32 - UK.indd 20 06-07-2023 10:40
Chapter 2 • The ESP32 DevKitC Development Board

IO26 IO5
IO27 IO17
IO14 IO16
IO12 IO4
GND IO0
IO13 IO2
SD2 IO15
SD3 SD1
CMD SD0
+5V CLK

Figure 2.2: ESP32 DevKitC connectors.

The board has a mini USB connector for connection to a PC. The board also receives its
power from the USB port. Standard +5 V from the USB port is converted into +3.3 V on
the board. In addition, two buttons are provided on the board named EN and BOOT, with
the following functions:

EN: This is the Reset button. Pressing this button resets the board.

BOOT: This is the Download button. The board is normally in operation mode where the
button is not pressed. Pressing and holding down this button and at the same time pressing
the EN button starts the firmware download mode allowing firmware to be downloaded to
the processor through the USB serial port.

The pins on the ESP32 DevKitC board have multiple functions. Figure 2.3 shows the func-
tions of each pin. For example, pin 10 is shared with functions GPIO port 26, DAC channel
2, ADC channel 19, RTC channel 7, and RX01.

● 21

Practical Audio DSP Projects with the ESP32 - UK.indd 21 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 2.3: Multiple functions of each pin. Source: www.cnx-software.com

Note that GPIO34, GPIO35, GPIO36, GPIO37, GPIO38 and GPIO39 ports are input only
and cannot be used as output ports (GPIO37 and GPIO38 are not available on the ESP32
board).

The board operates at a typical power supply of +3.3 V although the absolute maximum
is specified as +3.6 V. It is recommended that the current capacity of each pin should not
exceed 6 mA, although the absolute maximum current capacity is specified as 12 mA. It
is therefore important to use current limiting resistors while driving external loads such as
LEDs. Depending upon the configuration, the RF power consumption during reception is
around 80 mA, and it can be in excess of 200 mA during a transmission.

Programming of the ESP32 DevKitC requires the board to be connected to a PC through


its mini USB port. The communication between the board and the PC takes place using the
standard serial communication protocol. ESP32 DevKitC is preloaded with firmware that
can be used to test the board. This firmware is activated by default when power is applied
to the board. Before communicating with this firmware you have to run a terminal emula-
tion program on your PC, such as the HyperTerm, Putty, X-CTU, and others.

● 22

Practical Audio DSP Projects with the ESP32 - UK.indd 22 06-07-2023 10:40
Chapter 3 • Using the Arduino IDE with the ESP32 DevKitC

Chapter 3 • U
 sing the Arduino IDE with the
ESP32 DevKitC

3.1 Overview
By default, the ESP32 DevKitC is distributed with no programming firmware installed. It is
therefore necessary to install a programming language firmware on the processor permit-
ting user programs to be developed and uploaded to the processor. Just like the ESP8266,
the ESP32 processor is compatible with various programming languages such as C, Micro-
Python, and others.

The Arduino IDE is currently one of the most commonly used development environments
for microcontrollers, especially for the Arduino family of microcontrollers. This IDE is easy
to use, supports many microcontrollers, and includes a very rich library of functions that
make programming easier. Most electrical/electronic engineering students and people
whose hobbies are electronics are familiar with the Arduino IDE. In this chapter, you will be
learning how to incorporate the ESP32 processor software interface into the Arduino IDE
running on a Windows PC.

3.2 Installing the Arduino IDE for the ESP32 DevKitC


At the time of writing this book, the Arduino IDE had two current versions: Version 1
(more specifically 1.8.19), and Version 2 (more specifically 2.0.4). The steps for installing
the ESP32 support on both versions of the Arduino IDE on a Windows PC are given in this
section. If you already have installed ESP32 on Arduino IDE, then you must delete the Es-
pressif folder from your Arduino directory before re-installing it.

Installing on version 1.8.19 of Arduino IDE


The steps to install the ESP32 on Arduino IDE version 1.8.19 are as follows.

• Download and install the latest version of Arduino IDE 1.8.19 from the following
website:

https://www.arduino.cc/en/Main/Software

• Open your Arduino IDE and click File  Preferences to open the Preferences
window. Locate the text box Additional Board Manager URLs at the bottom
of the window and enter the following text as shown in Figure 3.1. If the text
box contains another URL, add the new URL after separating it with a comma:

https://espressif.github.io/arduino-esp32/package_esp32_index.json

● 23

Practical Audio DSP Projects with the ESP32 - UK.indd 23 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 3.1: Preferences window.

• Click OK.

• Click Tools  Boards  Board Managers window and search for ESP32 as
shown in Figure 3.2. Select the latest version.

Figure 3.2: Search for ESP32.

• Click Install button. You should see the Installed message as shown in Figure
3.3. Close the window. At the time of writing this book, the version was 2.09.

Figure 3.3: ESP32 installed.

• You should now test the installation to make sure that all the necessary
files have been loaded. You can make use of one of the supplied example
applications to make sure that a program can be uploaded to the ESP32
processor and is working correctly.

● 24

Practical Audio DSP Projects with the ESP32 - UK.indd 24 06-07-2023 10:40
Chapter 3 • Using the Arduino IDE with the ESP32 DevKitC

• Plug in your ESP32 DevKitC to your PC. You should see the red power LED on
the development board to turn ON. Start the Arduino IDE.

• Select Tools  Board  ESP32 Dev Module as shown in Figure 3.4.

Figure 3.4: Select the ESP32 Dev Module.

• Select the serial port number (Tools  Port). In this example, this is COM5 as
shown in Figure 3.5.

Figure 3.5: Select the serial port.

• Open the example program in File  Examples  WiFi (in ESP32)  WiFi
Scan as shown in Figure 3.6.

● 25

Practical Audio DSP Projects with the ESP32 - UK.indd 25 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 3.6: Open the example program Wi-Fi Scan.

• You should see the program as in Figure 3.7.

Figure 3.7: Example program to test the installation.

Now, you will upload the program to your ESP 32 DevKitC. First of all, you have to put the
device into firmware upload mode. Press the Sketch  Upload button on Arduino IDE to
compile and upload your program to the ESP32 DevKitC (on some devices, you may have to
keep the BOOT button pressed during the entire upload process). Wait until finished. After a
successful process, you should see a screen similar to the one shown in Figure 3.8 Release
the BOOT button if it was pressed during the upload.

● 26

Practical Audio DSP Projects with the ESP32 - UK.indd 26 06-07-2023 10:40
Chapter 3 • Using the Arduino IDE with the ESP32 DevKitC

Figure 3.8: End of uploading.

• Now, open the Arduino IDE Serial monitor by clicking Tools  Serial Monitor.
Make sure that the communication baud rate is set to 115200. You should see
a list of the access points close to you as shown in Figure 3.9 (You may have
to press the Reset button at the left of the board). The list is updated every 5
seconds.

• At this point, you have successfully installed the ESP32 processor into your
Arduino 1.8.19 IDE.

Figure 3.9: List of close access points.

Installing on version 2.0.4 of Arduino IDE


The steps to install the ESP32 on Arduino IDE version 2.0.4 are as follows.

• Open your Arduino IDE and click File  Preferences to open the Preferences
window. Locate the text box Additional Board Manager URLs at the bottom
of the window and enter the following text (Figure 3.10):

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/
package_esp32_index.json

● 27

Practical Audio DSP Projects with the ESP32 - UK.indd 27 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 3.10: Preferences window.

• Click OK.

• Open the Boards Manager as Tools  Board  Boards Manager.

• Search for ESP32 and press the install button for esp32 by Espressif Systems.
At the time of writing this book, the version was 10.6.

• Click File  New to create a new file.

• Click Unknown Board on the top drop-down menu.

• Select DOIT ESP32 DEVKIT V1 and port COM5. Click OK (Figure 3.11).

Figure 3.11: Program to flash the on-board LED.

• To test the installation, you can write the program shown in Figure 3.12 and
upload it to the ESP32. This program will count up by one every 2 seconds and
display the result on the Serial Monitor.

● 28

Practical Audio DSP Projects with the ESP32 - UK.indd 28 06-07-2023 10:40
Chapter 3 • Using the Arduino IDE with the ESP32 DevKitC

Figure 3.12: Program to count up and display on Serial Monitor.

• Click Sketch  Upload (on some devices, you may have to keep the BOOT
button pressed during the entire upload process). The program will be compiled
and uploaded to your ESP32.

• Click Serial Monitor icon at the top right-hand side of the screen and set the
speed to 115200. You should see the program counting up and displaying on
the Serial Monitor as shown in Figure 3.13 (You may have to press the left
RESET button for the program to start).

Figure 3.13: Program counting up.

Which Arduino IDE version to use?


Version 2.0.4 is a major release and is faster, more powerful, and has a better editor com-
pared to the older 1.8.19. The new version also includes a live debugger. The choice is up
to the reader, as both versions function perfectly well.

This book uses the older, more familiar version 1.8.19 in all projects discussed.

● 29

Practical Audio DSP Projects with the ESP32 - UK.indd 29 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 4 • E
 lementary Projects using
The Arduino IDE and the ESP32 DevKitC

4.1 Overview
In the previous chapter, you have seen how to update the Arduino IDE so that the pro-
grams developed using this IDE can be compiled and downloaded to the ESP32 DevKitC
development board.

This chapter is a review of using some of the basic features of the ESP32 processor with
the Arduino IDE. Readers familiar with developing basic projects using the ESP32 can skip
it if they want. In this chapter, projects will be developed to show how commonly required
operations can be programmed with the Arduino IDE. The example projects given cover
the following concepts:
• Using external LEDs (or buzzers, etc.)
• Using external pushbutton
• Using the PWM (Pulse Width Modulation) of the ESP32
• Using the ADC (Analog-to-Digital Converter) of the ESP32
• Using I2C LCD in a project
• Using the DAC (Digital-to-Analog Converter) of the ESP32
• Writing and reading from an SD card
• WiFi network programming
• Bluetooth programming

Interested readers can find many more useful working projects in the following Elektor
book (some of the projects in this book are taken from the following book):

The Complete ESP32 Projects Guide, by Dogan Ibrahim

All the projects given in this book have been tested and are fully working. The following
sub-headings will be used for each project wherever it is possible so that the projects can
be further developed if required by the readers:
• Project title
• Project description
• Aim of the project
• Project block diagram
• Project circuit diagram
• Project construction
• Project program listing
• Full description of the project program
• Suggestion for further work

4.2 Project 1: Alternately flashing LEDs


Description: In this project, two LEDs are connected to GPIO ports 22 and 23 of the ESP32
DevKitC.

● 30

Practical Audio DSP Projects with the ESP32 - UK.indd 30 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

The aim: The aim of this project is to show how external LEDs can be connected to a GPIO
port and how they can be turned on and off alternately.

Block diagram: The block diagram of the project is shown in Figure 4.1.

4.1: Block diagram of the project.

Circuit diagram: The circuit diagram of the project is shown in Figure 4.2. LED1 is con-
nected to GPIO port 22 and LED2 to GPIO port 23. The LEDs are connected to the port pins
through 330-Ohm current limiting resistors (higher or lower value resistors could also have
been connected for lower or higher light intensities, respectively). Assuming the voltage
drop across the LED is 2 V, the current through the LED will be:

I = V / R = (3.3 V – 2 V) / 330 ohm = 3.9 mA

Figure 4.2: Circuit diagram of the project.

Construction: A breadboard was used to construct the project. The LEDs are connected to
the ESP32 DevKitC through the current limiting resistors as shown in Figure 4.3.

● 31

Practical Audio DSP Projects with the ESP32 - UK.indd 31 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 4.3: Project built on a breadboard.

Program listing: The program listing of the project is very simple and is shown in Figure
4.4 (Program: Altflash). At the beginning of the program, variable names LED1 and LED2
are assigned to GPIO ports 22 and 23 respectively. Then the port pins are configured as
outputs. The main program is run continuously in a loop, where inside this loop LED1 and
LED2 are turned ON and OFF alternately with a one-second delay between each output.

/****************************************************************
* ALTERNATE FLASHING LEDs
* =======================
*
* In this program two LEDs are connected to port GPIO22 and
* GPIO23 of the ESP32 DevKitC. The program flashes the LEDs
* alternately with one second delay between each output
*
* Program: Altflash
* Date : April, 2023
**************************************************************/
#define LED1 22
#define LED2 23
#define ON HIGH
#define OFF LOW

● 32

Practical Audio DSP Projects with the ESP32 - UK.indd 32 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

void setup()
{
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
}

void loop()
{
digitalWrite(LED1, HIGH);
digitalWrite(LED2, LOW);
delay(1000);
digitalWrite(LED1, LOW);
digitalWrite(LED2, HIGH);
delay(1000);
}

Figure 4.4: Program: Altflash.

4.3 Project 2: Binary up/down counter with LEDs


Description: In this project, 8 LEDs are connected to the ESP32 DevKitC. In addition, a
pushbutton switch (or simply a button) is connected to GPIO port 17. When the button
is not pressed, the program counts up, and when the button is held pressed the program
counts down.

The Aim: The aim of this project is to show how a pushbutton switch can be connected to
an ESP32 DevKitC GPIO port and how the port can be configured as an input.

Block diagram: The block diagram of the project is shown in Figure 4.5.

Figure 4.5: Block diagram of the project.

Circuit diagram: The circuit diagram of the project is shown in Figure 4.6. 8 LEDs are
connected to the GPIO ports through 330-Ohm current limiting resistors as follows:

● 33

Practical Audio DSP Projects with the ESP32 - UK.indd 33 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

GPIO23 (MSB)
GPIO22
GPIO1
GPIO3
GPIO21
GPIO19
GPIO18
GPIO5 (LSB)

The button is connected to GPIO pin 17.

Notice that a button can be connected in two different ways to a GPIO port. In Figure 4.7,
the output of the button is at logic 1 and goes to logic 0 when the button is pressed. In
Figure 4.8, the output of the button goes from logic 0 to logic 1 when the button is pressed.
In this example, the second method is used. Thus, GPIO pin is normally at logic 0 and goes
to logic 1 when the button is pressed.

Figure 4.6: Circuit diagram of the project.

Figure 4.7: Button normally at logic 1.

● 34

Practical Audio DSP Projects with the ESP32 - UK.indd 34 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Figure 4.8: Button normally at logic 0.

Construction: The project was built on a breadboard as shown in Figure 4.9.

Figure 4.9: Constructing the project on a breadboard.

Program listing: The program listing of the project is very simple and is shown in Figure
4.10 (Program: UpDown). At the beginning of the program, an array called LEDs is set up
to store the port numbers of the LEDs used in the project. The name Button is assigned to
GPIO port 17, and the names UP and DOWN are assigned to 0 and 1 respectively. Global
variable Count is initialized to zero. Then, the GPIO ports where the LEDs are connected
are configured as output ports, and the GPIO port where the Button is connected is con-
figured as an input port. Inside the main program, function Display is called, and Count is
sent as the argument. Then, the state of the Button is read: if the Button is not pressed
(Button_State equal to UP) then an UP count is performed. If on the other hand, the
Button is pressed (Button_State equal to DOWN) then a DOWN count is performed.
Notice that variable Count is reset at the end of the counts. i.e., during an UP count when
the count reaches 255, it is reset to 0 on the next cycle. Similarly, on a DOWN count when
the count reaches 0, it is reset to 255 on the next cycle.

● 35

Practical Audio DSP Projects with the ESP32 - UK.indd 35 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

/****************************************************************
* BINARY UP/DOWN COUNTER
* ======================
*
* In this program 8 LEDs are connected to port pins GPIO23,
* GPIO22, GPIO1, GPIO3, GPIO21, GPIO19, GPIO18, and GPIO5
* of the ESP32 DevKitC. In addition, a push-button switch
* is connected to port pin 17. Normally the switch output is
* at logic 0 and when the switch is pressed its output goes
* to logic 1. The program normally counts up. When the switch
* is pressed and held down then the program starts to count
* down from its last value. The appropriate LEDs are turned
* ON/OFF
*
*
* Program: UpDown
* Date : April, 2023
**************************************************************/
#define Button 17
#define UP 0
#define DOWN 1
int LEDs[] = {23, 22, 1, 3, 21, 19, 18, 5};
unsigned char Count = 0;
unsigned char Button_State;

//
// Set GPIO pins 23,22,1,3,21,19,18,5 as outputs and GPIO pin 17
// as input
//
void setup()
{
unsigned char i;
for(i=0; i < 8; i++)
{
pinMode(LEDs[i], OUTPUT);
}
pinMode(Button, INPUT);
}

//
// Turn ON the appropriate LED
//
void Display(unsigned char No, unsigned char L)
{
unsigned char j, m, i;

● 36

Practical Audio DSP Projects with the ESP32 - UK.indd 36 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

m = L - 1;
for(i = 0; i < L; i++)
{
j = pow(2, m);
digitalWrite(LEDs[i], (No & j));
m--;
}
}

//
// When the button is not pressed increment Count every second
// and send Count to GPIO pins. When the button is pressed
// count down from the last value and send Count to GPIO pins
// Notice that the width is 8-bits (i.e. there are 8 LEDs)
//
void loop()
{
Display(Count, 8);
Button_State = digitalRead(Button); // Read Button state
if(Button_State == UP) // If UP count
{
if(Count == 255)
Count = 0; // Reset Count
else
Count++; // Increment Count
}
else if(Button_State = DOWN) // If DOWN count
{
if(Count == 0)
Count = 255; // Reset Count
else
Count--; // Decreament Count
}
delay(1000); // Wait 1 second
}

Figure 4.10: Program: UpDown.

4.4 Project 3: Changing the brightness of an LED


Description: In this project, an LED is connected to the ESP32 DevKitC. The program
changes the brightness of the LED by changing the voltage applied to the LED.

The aim: The aim of this project is to show how PWM type waveform can be generated in
a program and how this waveform can be used to effectively vary the voltage applied to
an LED.

● 37

Practical Audio DSP Projects with the ESP32 - UK.indd 37 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Block diagram:
The block diagram of the project is shown in Figure 4.11.

Figure 4.11: Block diagram of the project.

Circuit diagram: The circuit diagram of the project is shown in Figure 4.12. An LED is
connected to the GPIO port 23 through a 330-ohm current limiting resistor.

Figure 4.12: Circuit diagram of the project.

Program listing: The program listing of the project is very simple and is shown in Figure
4.13 (Program: FadeLED). The fading of the LED is done by applying a PWM waveform to
the LED and then changing the duty cycle of this waveform, which effectively changes the
average voltage applied to the LED.

/****************************************************************
* CHANGING THE LED BRIGHTNESS
* ===========================
*
* In this program an LED is conencted to GPIO port pin 23.
* The program changes the brightness of the LED by varying
* the voltage applied to the LED. The LED PWM function is used
* in this project where the duty cycle of the PWM waveform is

● 38

Practical Audio DSP Projects with the ESP32 - UK.indd 38 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

* varied from 0 to its full value of 255


*
* Program: FadeLED
* Date : April, 2023
**************************************************************/
int LED = 23;
int frequency = 1000;
int resolution = 8;
int channel = 0;

//
// Set GPIO pin 23 as output. Setup the PWM channel 0 and attach
// GPIO pin 23 to this channel
//
void setup()
{
pinMode(LED, OUTPUT);
ledcSetup(channel, frequency, resolution);
ledcAttachPin(LED, channel);
}

//
// Change the brightness of the LED by varying the duty cycle
// from 0% (0) to 100% (255)
//
void loop()
{
for(int duty = 0; duty < 255; duty +=5)
{
ledcWrite(channel, duty);
delay(50);
}

for(int duty = 255; duty >= 0; duty -=5)


{
ledcWrite(channel, duty);
delay(50);
}
delay(500);
}

Figure 4.13: Program: FadeLED.

Figure 4.14 shows a typical PWM waveform. The duty cycle is defined as the ratio of the
ON time to the period:

● 39

Practical Audio DSP Projects with the ESP32 - UK.indd 39 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

or

Figure 4.14: A typical PWM waveform.

Thus, for example, when the duty cycle is 0% the ON time is 0, and when the duty cycle is
100% the OFF time is 0.

The program uses the LED PWM function of the ESP32 which consists of 16 independent
channels with configurable duty cycles, frequencies, and resolutions. A channel from 0 to
15, and a resolution from 1 to 16 bits can be selected. The PWM setup function is called
ledcSetup and it has the following format with integer parameters:

ledcSetup(channel, frequency, resolution)

After the setup, you have to attach the GPIO pin that you will be using as the PWM pin to
the selected channel. This is done using function ledcAttach, which has the format:

ledcAttachPin(GPIO pin, channel)

The PWM waveform is then sent to the selected GPIO pin using function ledcWrite which
has the format:

ledcWrite(channel, duty cycle)

where, for an 8-bit resolution, the duty cycle is 0 for 0% and 255 for 100%.

In this project, the frequency is set to 1000 Hz, and channel 0 is used with the GPIO pin
23. The resolution is set to 8 bits. The duty cycle is changed from 0 to 100% in steps of 5%
every 50 milliseconds. The effect is that the brightness of the LED changes from no light
(0% duty cycle) to full brightness (100% duty cycle) where the brightness is increased by
5% every 50 ms. Similarly, after the full brightness is reached the program waits for 500
ms and starts to fade the LED from full brightness to no light, again by 5% every 50 ms.

● 40

Practical Audio DSP Projects with the ESP32 - UK.indd 40 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Suggestions: In Figure 4.13, the delay time is set to 50 ms and the duty cycle step is
set to 5. Try modifying both of these values and watch their effects on the LED bright-
ness.

4.5 Project 4: Thermometer with output displayed on Serial Monitor


Description: In this project, an analog temperature sensor chip is used to get the ambi-
ent temperature. The temperature is displayed every second on the PC screen using the
Arduino IDE Serial Monitor.

The aim: The aim of this project is to show how an analog input (ADC) of the ESP32
DevKitC can be used to read analog data. In addition, it shows how to display data on the
PC screen.

Block diagram: Figure 4.15 shows the block diagram of the project.

Figure 4.15: Block diagram of the project.

Circuit Diagram: In this project, the TMP36 analog temperature chip is used to get the
ambient temperature. The TMP36 temperature sensor chip is a 3-pin device having the pin
layout as shown in Figure 4.16. The device operates with a power supply in the range of
2.7 V to 5.5 V and can measure the temperature in the range of –40 ºC to +125 ºC. The
output voltage of the device is proportional to the measured temperature and is given by:

C = (V – 500) / 10

Where C is the measured temperature in ºC, V is the output voltage of the sensor chip in
mV. Thus, for example, an output voltage of 800 mV corresponds to 30 ºC, and so on.

● 41

Practical Audio DSP Projects with the ESP32 - UK.indd 41 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 4.16: Pin layout of TMP36 temperature sensor chip.

Figure 4.17 shows the circuit diagram of the project. Two pins of the TMP36 are connected
to the +3.3 V power supply and the ground. The output pin of the TMP36 temperature sen-
sor chip is connected to GPIO4 which is also the ADC2_0 of the ESP32 DevKitC. The ADC is
12-bits wide and has a reference voltage of +3.3 V.

Figure 4.17: Circuit diagram of the project.

Construction: The ESP32 DevKitC board is mounted on a breadboard as shown in Figure


4.18. The output of the TMP36 is connected to GPIO pin 4.

● 42

Practical Audio DSP Projects with the ESP32 - UK.indd 42 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Figure 4.18: Project built on a breadboard.

Program Listing: The program listing of the project is shown in Figure 4.19 (Program:
TMP36).

/****************************************************************
* THERMOMETER WITH SERIAL MONITOR
* ===============================
*
* In this program a TMP36 type analog temperature sensor chip
* is connected to GPIO pin 4 which is also an analog input.
* The program reads the ambient temperature every second and
* sends the readings to the Serial Monitor
*
*
* Program: TMP36
* Date : April, 2023
**************************************************************/
#define TMP36 4

void setup()
{
Serial.begin(9600);
}

//
// Read the ambient temperaure, convert into Degrees Centigrade
// and send the readings to the Serial Monitor. Repeat this
// process every second

● 43

Practical Audio DSP Projects with the ESP32 - UK.indd 43 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

//
void loop()
{
int Temp = analogRead(TMP36);
float mV = Temp * 3300.0 / 4096.0;
float Temperature = (mV - 500.0) / 10.0;
Serial.println(Temperature);
delay(1000);
}

Figure 4.19: Program: TMP36.

At the beginning of the program, TMP36 is defined as port GPIO4, which is one of the
analog input ports of the ESP32 DevKitC, and the Serial Monitor baud rate is set to 9600.
The remainder of the program is executed in an endless loop. Inside this loop, the analog
output of the TMP36 is read using the analogRead library function. The reading is then
converted into absolute millivolts. Notice that the ADC reference voltage is 3300 mV and
the ADC is 12-bits wide (0 to 4095). The reading is then converted into Degrees Centigrade
by subtracting 500 and dividing by 10. The temperature values are then sent to the Serial
Monitor so that they can be displayed on the PC screen. To do this, click Tools  Serial
Monitor and select the baud rate as 9600. A typical output from the Serial Monitor is
shown in Figure 4.20. You can make the display more user-friendly by displaying the text
Temperature before its value by modifying the code as follows. The resultant display is
shown in Figure 4.21.

float Temperature = (mV - 500.0) / 10.0;


int len = Serial.write("Temperature = ");
Serial.println(Temperature);

Figure 4.20: Typical output from the Serial Monitor.

● 44

Practical Audio DSP Projects with the ESP32 - UK.indd 44 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Figure 4.21: User-friendly display.

It is important to mention at this point that the ESP32 DevKitC used by the author (any
many others as reported on the Internet) has ADC linearity problems which may result in
inaccurate readings. In order to get accurate results from the ADC, it is recommended to
carry out an experiment and create a table or an equation showing the actual relationship
between the analog input voltages and the digital values returned by the ADC. This table
or the equation can then be used to correct the ADC readings.

4.6 Project 5: LCD-based event counter


Description: This is an event counter project with LCD readout. The project counts exter-
nal events occurring on one of the GPIO ports and displays the results on an LCD. In this
project, an event is said to occur if the state of GPIO port 23 changes from logic 1 to logic
0. Here, a pushbutton switch is used to simulate the occurrence of external events.

The aim: The aim of this project is to show how a character-based LCD can be interfaced
and used in an ESP32 DevKitC project and how numbers can be displayed on the LCD. An
I2C-compatible 16-character by 2-row LCD is used here.

Block diagram: The block diagram of the project is shown in Figure 4.22, A pushbutton
switch and an I2C LCD are connected to DevKitC

Figure 4.22: Block diagram of the project.

● 45

Practical Audio DSP Projects with the ESP32 - UK.indd 45 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The LCD used in this project is based on the I2C interface. I2C is a multi-slave, multi-master,
single-ended serial bus used to attach low-speed peripheral devices to microcontrollers.
The bus consists of only two wires called SDA and SCL where SDA is the data line and SCL
is the clock line and up to 1008 slave devices can be supported on the bus. Both lines must
be pulled up to the supply voltage by suitable resistors. The clock signal is always generat-
ed by the bus master. The devices on the I2C bus can communicate at 100 kHz or 400 kHz.

GPIO ports 21 and 22 are available for use by the I2C bus interface on the ESP32 DevKitC,
where port 21 is the data line (SDA) and port 22 is the clock line (SCL).

Figure 4.23 shows the front and back of the I2C-based LCD. Notice that the LCD has a
small board mounted on its back to control the I2C interface. The LCD contrast is adjusted
through the small potentiometer mounted on this board. A jumper is provided on this board
to disable the backlight if required.

Figure 4.23: I2C compatible LCD (front and back views).

The I2C LCD used in this project has the address: 0x27.

Circuit diagram: The schematic (circuit diagram) of the project is shown in Figure 4.24.
The SDA and CL pins of the I2C LCD are connected to GPIO ports 21 and 22 respectively.
The pushbutton switch is connected to GPIO port 23 through a 10 k-ohm pull-up resistor to
simulate the occurrence of external events.

Figure 4.24: Circuit diagram of the project.

Construction: The ESP32 DevKitC board is mounted on a breadboard with the pushbutton
switch. The I2C LCD is connected to DevKitC through jumper wires as shown in Figure 4.25.

● 46

Practical Audio DSP Projects with the ESP32 - UK.indd 46 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Figure 4.25: The project built on a breadboard.

Program listing: Before programming the ESP32 for the I2C LCD, it is necessary to down-
load and include the I2C LCD library in your Arduino IDE folder. The steps to do this are
given below:

• Create a folder named LiquidCrystal_I2C under the folder named libraries in


your Arduino IDE folder (see Figure 4.26).

Figure 4.26: Create folder LiquidCrystal_I2C.

• Go to the following link to download the I2C LCD library:

https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library

• Click the button Code (see Figure 4.27) and click Download ZIP. The library
ZIP file will be copied to your Downloads folder.

● 47

Practical Audio DSP Projects with the ESP32 - UK.indd 47 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 4.27: Download the I2C library files.

• Open your Arduino IDE. Click Sketch  Include Library and select Add .ZIP
Library…

• Browse to the above-downloaded file and click Open. You should see the
message Library added to your libraries message at the bottom of the IDE
screen.

• Start the Arduino IDE. Go to File  Examples and you should see Arduino-
LiquidCrystal_I2C examples in the drop-down menu if the library has been
installed correctly (Figure 4.28)

Figure 4.28: Files in the LiquidCrystal_I2C folder.

● 48

Practical Audio DSP Projects with the ESP32 - UK.indd 48 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

The program listing is shown in Figure 4.29 (program: LCDCounter). At the beginning of
the program, EVENTS is assigned to GPIO port 23 and I2C and LCD libraries are included in
the program. Variable Count is cleared to zero. In the setup routine, port 23 is configured
as input, LCD is initialized, and the text message Event Counter is displayed on the LCD.

The remainder of the program runs in an endless loop where the program waits until an
event occurs. A small delay is then introduced to the program to wait until the switch
contacts stop bouncing (called contact debouncing). The program then clears the LCD,
increments Count by one, converts it into a string using function snprintf and displays the
value of Count on the LCD.

/*************************************************************
* LCD EVENT COUNTER
* =================
*
* This is an event counter program with an LCD. Events are
* assumed to occur on GPIO port 23 where an event is the HIGH
* to LOW transition of this pin. In this project events are
* simulated using a push-button switch connected to GPIO23 and
* pulled high. An I2C LCD is connected to the ESP32 Devkitc.
*
* File: LCDCounter
* Date: April, 2023
* Author: Dogan Ibrahim
*************************************************************/
#define EVENTS 23
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int Count = 0;
char Res[4];
//
// Set the LCD address to 0x27 and the configuration to
// 16 chars and 2 rows display. Also configure port 23 as
// an input
//
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD address 0x27

void setup()
{
pinMode(EVENTS, INPUT);
lcd.begin(); // Initialize LCD
lcd.backlight(); // Turn ON backlight
lcd.print("Event Counter"); // Display Text
}

● 49

Practical Audio DSP Projects with the ESP32 - UK.indd 49 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

void loop()
{
while(digitalRead(EVENTS) == 1); // Wait until event
delay(150); // Contact debounce
lcd.clear(); // Clear LCD
Count++; // Incement Count
snprintf(Res, 4, "%d", Count); // Covert to string
lcd.print(Res); // Display on LCD
}

Figure 4.29: Program: LCDCounter.

LCD functions
The I2C LCD library supports the following functions:

clear() clear the LCD and position cursor to first position


home() home the cursor to first position
setCursor(x, y) set cursor to column x, row y (index starts from 0)
print() display on LCD
display() show characters on the display (default)
noDisplay() do not show any characters on the display
blink() start blinking the cursor
noBlink() stop blinking the cursor
cursor() display the cursor indicator
noCursor() do not show the cursor indicator
scrollDisplayLeft() scroll the display left by one character position
scrollDisplayRight() scroll the display right by one character position
leftToRight()  text to flow to the right from the cursor, as if the display is
left-justified (default)
rightToLeft() text to flow to the left from the cursor, as if the display is right-jus-
tified.
noBacklight() disable backlight
backlight() enable backlight
getBacklight() get backlight value
autoscroll() moves all the text one space to the left each time a letter is add-
ed (default)
noAutoscroll() disabled auto scrolling

4.7 Project 6: Generating waveforms — Sawtooth


Description: This project shows how a sawtooth waveform can be generated using the
ESP32 DevKitC.

The aim: The aim of this project is to show how the DAC on the ESP32 DevKitC can be used
to generate a sawtooth waveform.

● 50

Practical Audio DSP Projects with the ESP32 - UK.indd 50 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Block diagram: Figure 4.30 shows the block diagram of the project. Here, the ESP32
processor generates the required sawtooth waveform as a digital signal, and then, the DAC
outputs this signal through the GPIO port reserved for the DAC. A PC-based oscilloscope
PSCGU250 is used in this project.

Figure 4.30: Block diagram of the project.

Basically, two methods can be used for waveform generation:

• The processor calculates the waveform points in real time and sends them to
the DAC

• The waveform points are stored in a look-up table. The processor reads these
points from the table and sends them to the DAC (this method is used to
generate any arbitrary waveform, or to generate higher frequency waveforms).

The rate at which the waveform points are sent to the DAC determines the frequency of
the waveform.

The DAC
A DAC converts digital signals to analog. Although a DAC can be an external component,
most microcontrollers have built-in DACs. For example, the ESP32 processor has two 8-bit
DACs. In external DACs, the digital input can either be in serial or parallel form. In external
parallel converters, the width of the digital input is equal to the width of the converter. For
example, 10-bit DACs have 10 input bits. External serial DACs in general use the SPI or the
I2C bus, and a clock and a data line are used to send the data to be converted to the DAC.
Parallel converters provide much faster conversion times, but they are housed in larger
packages.

DACs are manufactured as either unipolar or bipolar as far as the output voltages are con-
cerned. Unipolar converters can only output positive voltages, whereas bipolar converters
can output both positive and negative voltages.

● 51

Practical Audio DSP Projects with the ESP32 - UK.indd 51 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The relationship between the digital input-output and the voltage reference of a DAC is
given by:

Where VO is the output voltage, Vref is the reference voltage, and n is the width of the con-
verter. For example, in an 8-bit converter with a +3.3 V reference voltage,

Thus, for example, if the input digital value is 00000001, the analog output voltage will be
12.89 mV, if the input digital value is 00000010, the analog output voltage will be 25.78
mV, and so on.

In this project, you will be generating a sawtooth waveform with the following specifica-
tions:

• Output voltage: 0 to +3.3 V


• Frequency: 100 Hz (period = 10 ms)
• Step size: 0.1 ms

Circuit diagram: The circuit diagram of the system is shown in Figure 4.31. The ESP32
processor has two built-in 8-bit DACs on GPIO ports 25 and 26. In this project, you shall be
using the one at GPIO port 25.

Figure 4.31: Circuit diagram of the project.

Program listing: The program listing of the project is shown in Figure 4.32 (Program:
Sawtooth). At the beginning of the program, the sawtooth is assigned to GPIO port 25 and
it is configured as an analog port. Inside the main program, 11 steps are continuously sent
to the DAC with a 909-µs delay between each step. Function dacWrite is used to send the
steps to the DAC. This function has two arguments: DAC port number, and the digital value
to be converted into analog.

● 52

Practical Audio DSP Projects with the ESP32 - UK.indd 52 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

/*************************************************************
* SAWTOOTH WAVEFORM GENERATION
* ============================
*
* In this project a Sawtooth waveform is generated through the
* DAC at GPIO port 25 of teh ESP32 Devkitc.
*
* The specifications of the generated waveform are:
* Output voltage: 0 to +3.3V
* Frequency: 100 Hz (period 10 ms)
* Step size: 0.1 ms
*
* File: Sawtooth
* Date: April, 2023
* Author: Dogan Ibrahim
*************************************************************/
#define Sawtooth 25
int DAC_Value;

void setup()
{
pinMode(Sawtooth, ANALOG); // Configure as analog
}

void loop()
{
for(float i = 0; i <= 1; i=i+0.1)
{
DAC_Value = i * 255;
dacWrite(Sawtooth, DAC_Value); // Send to DAC
delayMicroseconds(909); // 909 us delay
}
}

Figure 4.32: Program: Sawtooth.

Figure 4.33 shows the generated sawtooth waveform, captured on the PSCGU250 PC-
based oscilloscope. In this figure, the horizontal axis was 5 ms/division, and the vertical
axis was 1V /division.

● 53

Practical Audio DSP Projects with the ESP32 - UK.indd 53 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 4.33: Generated sawtooth waveform.

4.8 Project 7: Using SD cards — Writing


Description: In this project, an SD card module is connected to the ESP32 DevKitC. The
Program generates integer random numbers every second and writes them to the SD card
for 10 seconds (i.e., 10 numbers are written to the file) with a heading. The data is written
to a file called TEST.TXT under directory NUM.

The aim: The aim of this project is to show how an SD card can be interfaced to the ESP32
DevKitC and how data can be written to the SD card.

Block diagram: The block diagram of the project is shown in Figure 4.34. In this project,
a micro size SD card (microSD) adapter is used as shown in Figure 4.35. This card adapter
has the following specifications:

• Supports 3.3 V and 5 V


• SPI interface
• Brand: AZDelivery
• Dimensions: 9 × 7.1 × 2 cm
• Weight: 18.1 g

Figure 4.34: Block diagram of the project.

● 54

Practical Audio DSP Projects with the ESP32 - UK.indd 54 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Figure 4.35: SD card module used in the project.

SDcards are non-volatile memory card formats developed by the SD Card Association
(SDA) for use in portable devices like mobile phones, cameras, etc. The family includes the
following members:

SDSC: Standard Capacity SD with a capacity of 2 GB, using FAT-12 and FAT-16.
SDHC: High Capacity SD with a capacity from 2 GB to 32 GB, using FAT-16 or
FAT-32 file system
SDXC: eXtended Capacity SD with a capacity from 32 GB to 2 TB, using the exFAT
file system.

The Arduino library supports only FAT-16 and FAT-32 formatted SD cards. A standard-size
SD card has 9 pins, while a microSD card has 8 pins (Figure 4.36).

Figure 4.36: Standard size SD card and microSD card.

Circuit Diagram: SD card adapters are controlled using the SPI bus of the processor. The
cardholder used in this project has the following 6 pins:

CS
SCK
MOSI
MISO
VCC
GND

● 55

Practical Audio DSP Projects with the ESP32 - UK.indd 55 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The circuit diagram of the project is shown in Figure 4.37. SD card adapter is connected to
DevKitC through the standard SPI interface. The connections between the SD card module
and the DevKitC GPIO ports are as follows:

SD card adapter pin DevKitC pin


GND GND
VCC +5V
SCK GPIO18 (SPI SCK)
MISO GPIO19 (SPI MISO)
MOSI GPIO23 (SPI MOSI)
CS GPIO5 (SPI SS)

Figure 4.37: Circuit diagram of the project.

Construction: ESP32 DevKitC is mounted on a breadboard together with the SD card


module as shown in Figure 4.38. Jumper wires are used to connect the SD card adapter to
the DevKitC development board.

Figure 4.38: Project on a breadboard.

● 56

Practical Audio DSP Projects with the ESP32 - UK.indd 56 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Program Listing: The program listing of the project is shown in Figure 4.39 (Program:
SD-CARD).

/****************************************************************
* WRITE TO SD CARD
* ================
*
* In this program a microSD card adapter is connected to the
* ESP32 DevKitC. The program generates random numbers every second
* and stored them on the SD card over 10 seconds (i.e. 10 numbers)
* are stored on the SD card. The data is stored in file TEST.TXT
* under directory called NUM
*
* Program: SD-CARD
* Date : April, 2023
* Author : Dogan Ibrahim
**************************************************************/
#include "SD.h"
#define SD_CS 5 // SD card CS pin

void setup()
{
Serial.begin(9600);
Serial.println(""); // New line
if(!SD.begin(SD_CS)) // Initialize SD card
{
Serial.println("Initialization failed");
while(1);
}
else
Serial.println("Initialization done");
}

//
// This is the main program. A file called TEST.TXT is created in
// directory NUM on the SD card. The program stores 10 integer random
// integer numbers in this file on the SD card
//
void loop()
{
File MyFile;
unsigned int RandomNumber;
char k;

if(SD.cardType() == CARD_NONE)

● 57

Practical Audio DSP Projects with the ESP32 - UK.indd 57 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

{
Serial.println("SD card is not found");
while(1);
}

SD.mkdir("/NUM"); // Create directory NUM


MyFile = SD.open("/NUM/TEST.TXT", FILE_WRITE); // Open file TEST.TXT
if(MyFile) // If file opened
{
Serial.println("Writing to SD card"); // Write heading
MyFile.println("Random Numbers"); // Write heading
MyFile.println("=============="); // Write heading

for(k = 0; k < 10; k++) // Do 10 times


{
RandomNumber = random(0, 255); // Generate number
MyFile.println(RandomNumber); // Save the number
delay(1000); // Wait one second
}

MyFile.close(); // Close the file


Serial.println("Data written"); // Display message
}
else
Serial.println("Error in opening file"); // Display message
while(1); // Stop
}

Figure 4.39: Program: SD-CARD.

The SD card should be formatted before it is used with the ESP32. The steps are as follows:

• Make sure that your SD card is not write-protected.


• Insert the SD card into your computer (you may need an SD card adapter).
• Go to My Computer.
• Right-click on the SD card and select Format.
• Select FAT32 and press Start to format the card.

At the beginning of the program, the header file SD.h is included in the program and the
SD card chip select pin (SD_CS) is assigned to GPIO pin 5. Inside the setup routine, the SD
card library is initialized. Notice that the chip select pin must be specified as the argument
of library function SD.begin. The serial PC USB interface (Serial.begin) is also enabled so
that messages can be displayed on the PC screen while the program is running.

Inside the main program loop, the program checks if there is an SD card in the card
module. The program then creates a directory called NUM on the SD card using library

● 58

Practical Audio DSP Projects with the ESP32 - UK.indd 58 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

function SD.mkdir. Function SD.open creates a new file or opens an existing file. This
function has two arguments: the name of the file to be created or opened, and the mode.
The mode can either be FILE_WRITE or FILE_READ. When the FILE_WRITE mode is
used, data is added to the end of the file if the file exists, otherwise a new file is created.
Mode FILE_READ opens an existing file in read mode. Full path must be given to the file
including its directory name. In this program, the full path to the file was: /NUM/TEST.
TXT. Variable MyFile is set true if a new file has been created or an existing file is opened.
Message Random Numbers with an underline is written to the SD card as the heading. A
for loop is then set up which iterates 10 times. Inside this loop, integer random numbers
are generated and stored in the newly created file on the SD card. The program then waits
for one second. The file is closed at the end of the for loop. Closing the file physically saves
the data on the SD card. Notice that the function SD.flush() can also be used to save the
data physically on the SD card.

Figure 4.40 shows the SD card file structure after the program is run. The following data is
displayed on the PC screen on Serial Monitor while the program is running:

Initialization done
Writing to SD card
Data written

The data stored on the SD card is displayed on the PC as shown in Figure 4.41.

Figure 4.40: SD card file structure.

Figure 4.41: Data stored on the SD card.

● 59

Practical Audio DSP Projects with the ESP32 - UK.indd 59 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Some of the commonly used SD card library functions are (see website: https://www.arduino
.cc/en/Reference/SD for a full explanation of each function and for additional functions):

begin(): initialize the SD card library


exists(): check if a file exists on the SD card
mkdir(): create a new directory on the SD card
remove(): delete a file from the SD card
rmdir(): delete a directory on the SD card (the directory must be empty)
name(): returns the filename
available(): check if there is any data available to read from a file
close(): close a file. Closing a file physically saves data on the card
flush(): physically save data on the card
size(): get the size of the file
read(): read from the file
write(): write to the file

4.9 Project 8: Using SD cards — Reading


Description: In this project, an SD card module is connected to the ESP32 DevKitC as in
the previous project. The program opens the file TEST.TXT under directory NUM, created
in the previous project, and displays the contents of this file on the PC screen.

The aim: The aim of this project is to show how an SD card can be interfaced to the ESP32
DevKitC and how data can be read from the SD card.

Block diagram: The block diagram of the project is shown in Figure 4.34.

Circuit diagram: The circuit diagram of the project as shown in Figure 4.37.

Program listing: The program listing of the project is shown in Figure 4.42 (Program:
SD-READ).

/****************************************************************
* READ FROM SD CARD
* =================
*
* In this program a microSD card module is connected to the
* ESP32 DevKitC. The program opens file TEST.TXT in directory NUM
* on the SD card and then reads and displays the contents (random
* numbers) of this file on the PC screen.
*
* Program: SD-READ
* Date : April, 2023
* Author : Dogan Ibrahim
**************************************************************/
#include "SD.h"
#define SD_CS 5 // SD card CS pin

● 60

Practical Audio DSP Projects with the ESP32 - UK.indd 60 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

void setup()
{
Serial.begin(9600);
Serial.println(""); // New line
if(!SD.begin(SD_CS)) // Initialize library
{
Serial.println("Initialization failed");
while(1);
}
else
Serial.println("Initialization done");
}

//
// This is the main program. File TEST.TXT is opened in directory
// NUM of the SD card and its contents are displayed on the PC screen
//
void loop()
{
File MyFile;

if(SD.cardType() == CARD_NONE)
{
Serial.println("SD card is not found");
while(1);
}

MyFile = SD.open("/NUM/TEST.TXT", FILE_READ); // Open file TEST.TXT


if(MyFile) // If file opened
{
Serial.println("File opened"); // Display message
while(MyFile.available()) // While there is data
{
Serial.write(MyFile.read()); // Write file contents
}
MyFile.close(); // Close the file
}
else
Serial.println("Error in opening file"); // Display message
while(1); // Stop
}

Figure 4.42: Program: SD-READ.

● 61

Practical Audio DSP Projects with the ESP32 - UK.indd 61 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

In this program, the file TEST.TXT in directory NUM on the SD card is opened in read mode
(FILE_READ). Then a while loop is formed to read all the data from the file and display it
on the PC screen. Figure 4.43 shows the output of the program.

Figure 4.43: Output of the program.

4.10 ESP32 DevKitC network programming with the Arduino IDE


WiFi capability is one of the powerful features and advantages of the ESP32 processor. In
this section, you will be learning how to do network programming using the Arduino IDE
environment.

4.10.1 Project 9: Scanning the surrounding WiFi networks


Description: In some applications, you may want to scan the surrounding environment in
order to find out about the nearby WiFi networks. Function WiFi.scanNetworks() is used
to scan the surrounding networks. If any networks are found, this function returns the fol-
lowing parameters:

• Total number of networks found


• Network names (SSID)
• Network signal strengths (RSSI)
• MAC addresses (BSSIDstr)
• Encryption types

The aim: The aim of this project is to show how WiFi network programming is carried out
using the ESP32 DevKitC development board.

Program listing: Figure 4.44 shows a program (Program: SCAN) that scans the surround-
ing WiFi networks and returns the various network parameters.

● 62

Practical Audio DSP Projects with the ESP32 - UK.indd 62 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

/*************************************************************
* SCAN WI-FI NETWORK
* ==================
*
* This program does a scan and displays the surrounding Wi-Fi
* networks. The following parameters of the found networks
* are displayed: Network name (SSID), signal strength (RSSI),
* and MAC address (BSSIDstr).
*
* File: SCAN
* Author: Dogan Ibrahim
* Date: April, 2023
*
**************************************************************/
#include «WiFi.h»

//
// Set mode to station, scan the surrounding Wi-Fi networks and
// display their details on the Serial Monitor
//
void setup()
{
Serial.begin(9600);
WiFi.mode(WIFI_STA); // Mode station

int N = WiFi.scanNetworks(); // Scan networks


if(N > 0) // If networks found
{
Serial.println(«»);
Serial.print(N);
Serial.println(« Networks found»);
for (int i = 0; i < N; ++i)
{
Serial.print(i + 1);
Serial.print(«: «);
Serial.print(«Network Name: «);
Serial.print(WiFi.SSID(i));
Serial.print(« «);
Serial.print(«Signal Strength: «);
Serial.print(WiFi.RSSI(i));
Serial.print(« «);
Serial.print(«MAC Address: «);
Serial.println(WiFi.BSSIDstr(i));
delay(50);
}
}

● 63

Practical Audio DSP Projects with the ESP32 - UK.indd 63 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

void loop()
{
// no code
}

Figure 4.44: WiFi network scan program.

In the above program, the returned data is displayed on the Serial Monitor. A sample out-
put is shown in Figure 4.45 (only a part of the output is shown here).

Figure 4.45: Sample output from the program.

4.10.2 Project 10: Controlling LEDS connected to ESP32 DevKitC from


a mobile phone
In this section, you will be developing an interesting application. Here, the system will re-
motely control two LEDs connected to an ESP32 DevKitC development board using a mobile
phone. The idea here is that the DevKitC will be configured as an UDP client. Then, UDP
packets will be sent from a smartphone to control these LEDs. As mentioned earlier, these
LEDs can be replaced by relays and the project can be used to control any kind of electrical
equipment connected to the ESP32 DevKitC.

The LEDs are named LED1 and LED2 and valid commands are as follows (any other com-
mands are ignored by the program):

1=ON Turn ON LED1


1=OFF Turn OFF LED1
2=ON Turn ON LED2
2=OFF Turn OFF LED2

Block diagram: The block diagram of the project is shown in Figure 4.46.

● 64

Practical Audio DSP Projects with the ESP32 - UK.indd 64 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Figure 4.46: Block diagram of the project.

Circuit diagram: The circuit diagram is as in Figure 4.2, where the LEDs are connected to
ports 22 (LED1) and 23 (LED2) through 330-Ohm current limiting resistors. The LEDs are
turned ON when the port output is at logic 1 (high) and turned OFF when the port output
is at logic 0 (low).

Smartphone application
In this project, an Android-based smartphone is used to send the UDP commands. Although
one could develop a mobile application to send the UDP commands, there are many freely
available UDP app in the Play Store that can be used to send and/or receive UDP packets.
The one used in this project is called UDP RECEIVER and SENDER by Wezzi Studios (ver-
sion 4.0). This application can send and receive UDP packets from any other device running
the UDP protocol. The screen is in two parts: the upper Sender part and the lower Receiver
part (see Figure 4.47). Before sending a packet, the user must enter the destination IP ad-
dress, port number, and the message to be sent. Clicking the SEND UDP MESSAGE button
will send the packet to its destination. In the Receiver part, the local IP address is given.
The user must specify the required port number. Received packets will then be displayed
on the screen.

● 65

Practical Audio DSP Projects with the ESP32 - UK.indd 65 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 4.47: Android UDP send/receive app.

In this program, the IP address of the ESP32 DevKitC was 192.168.1.156.

ESP32 DevKitC program listing


Figure 4.48 shows the complete program (Program: UDPControl). At the beginning of
the program, the WiFi library headers are included in the program, LED1 and LED2 are
assigned to GPIO ports 22 and 23 respectively, local port number is defined, and the local
WiFi name and password are defined. Function Connect_WiFi connects to the local WiFi
network.

Inside the setup routine, the LED ports are configured as outputs and both LEDs are turned
OFF to start with. Then function Connect_WiFi is called to connect to local WiFi and UDP
is started on the local port.

The remainder of the program is executed in an endless loop. Inside this loop, the program
waits to receive a packet (command) from the UDP server (smartphone here). The received
packet is stored in the character array Packet and the program checks the command and
if this is a valid command, turns ON/OFF the LEDs as required.

The following code is used to decode the received command:

if(Packet[1] == '=')
{
if(Packet[0] == '1')
{
if(Packet[2] == 'O' && Packet[3] == 'N')
{
digitalWrite(LED1, HIGH);
}
else if(Packet[2] == 'O' && Packet[3] == 'F' && Packet[4] == 'F')
{
digitalWrite(LED1, LOW);

● 66

Practical Audio DSP Projects with the ESP32 - UK.indd 66 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

}
}
else if(Packet[0] == '2')
{
if(Packet[2] == 'O' && Packet[3] == 'N')
{
digitalWrite(LED2, HIGH);
}
else if(Packet[2] == 'O' && Packet[3] == 'F' && Packet[4] == 'F')
{
digitalWrite(LED2, LOW);
}
}

/*************************************************************
* UDP BASED CONTROL FROM MOBILE PHONE
* ===================================
*
* This is an UDP based control program where 2 LEDs are connected
* to GPIO ports 22 and 23 of the ESP32 devkitc board, and named
* as LED1 and LED2. Commands are sent from an Android type
* mobile phone to turn the LEDs ON/OFF. The ESP32 Devkitc is
* configured as an UDP client in this application. The format of
* the commands are as follows:
*
* 1=ON turn ON LED1
* 1=OFF turn OFF LED1
* 2=ON turn ON LED2
* 2=OFF turn OFF LED2
*
*
* File: UDPControl
* Author: Dogan Ibrahim
* Date: April, 2023
*
**************************************************************/
#include "WiFi.h"
#include <WiFiUdp.h>
//
// LED assignments
//
#define LED1 22
#define LED2 23
WiFiUDP udp;

● 67

Practical Audio DSP Projects with the ESP32 - UK.indd 67 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

//
// Use local port 5000
//
const int Port = 5000;
char Packet[80];

//
// Local Wi-Fi name and password
//
const char* ssid = "BTHomeSpot-XNH";
const char* password = "493105abxyz";

//
// This function connects the ESP32 Devkitc to the local Wi-Fi
// network. The network name and passwors are as specifed earlier
void Connect_WiFi()
{
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED)
{
delay(1000);
}
}

//
// Configure LEDs as outputs, turn OFF the LEDs to start with,
// Connect to the local Wi-Fi. Also, UDP is started in local port
//
void setup()
{
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
Connect_WiFi();
udp.begin(Port);
}

//
// This is the main program loop. Inside the main program we read
// UDP packets and then control the LEDs as requested. The format
// of the control commands are:
//
// 1=ON or 1=OFF for LED1
// 2=ON or 2=OFF for LED2

● 68

Practical Audio DSP Projects with the ESP32 - UK.indd 68 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

//
// Any other commands are simply ignored by the program
//
void loop()
{
int PacketSize = udp.parsePacket();
if(PacketSize)
{
udp.read(Packet, PacketSize);

if(Packet[1]=='=')
{
if(Packet[0]=='1')
{
if(Packet[2]=='O' && Packet[3]=='N')
{
digitalWrite(LED1, HIGH);
}
else if(Packet[2]=='O' && Packet[3]=='F' && Packet[4]=='F')
{
digitalWrite(LED1, LOW);
}
}
else if(Packet[0]=='2')
{
if(Packet[2]=='O' && Packet[3]=='N')
{
digitalWrite(LED2, HIGH);
}
else if(Packet[2]=='O' && Packet[3]=='F' && Packet[4]=='F')
{
digitalWrite(LED2, LOW);
}
}
}
}
}

Figure 4.48: Program: UDPControl.

As an example, Figure 4.49 shows the command sent from the smartphone application to
turn on LED1 (command: 1=ON).

● 69

Practical Audio DSP Projects with the ESP32 - UK.indd 69 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 4.49: Command to turn ON LED1.

4.11 Project 11: Bluetooth classic


The Bluetooth module is one of the important modules of the ESP32 DevKitC development
board. Using the Bluetooth interface, you can transfer files between devices, or control de-
vices remotely without Wi-Fi. An example project is given in this section.

Description: In this project, a 4-channel relay board is connected to the ESP32 DevKitC
and the relay is controlled by sending commands from a Bluetooth classic app running on
an Android mobile phone. The following commands can be sent from the smartphone (#
character is the command terminator):

1=ON# Activate Relay1


1=OFF# De-activate Relay1
2=ON# Activate Relay2
2=OFF# De-activate Relay2
3=ON# Activate Relay3
3=OFF# De-activate Relay3
4=ON# Activate Relay4
4=OFF# De-activate Relay4

The aim: The aim of this project is to show how a 4-channel relay board can be connected
to the ESP32 DevKitC and also how it can be controlled using the Bluetooth classic commu-
nication feature with a mobile phone.

Block diagram: The block diagram of the project is given in Figure 4.50.

● 70

Practical Audio DSP Projects with the ESP32 - UK.indd 70 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

Figure 4.50: Block diagram of the project.

In this project, a 4-channel relay board (see Figure 4.51) from Elegoo (www.elegoo.com) is
used. This is an opto-coupled relay board having 4 inputs, one for each channel. The relay
inputs are at the bottom right-hand side of the board, while the relay outputs are located
at the top side of the board. The middle position of each relay is the common point, the
connection to its left is the normally closed (NC) contact, while the connection to the right
is the normally open (NO) contact. The relay contacts support AC 250 V at 10 A and 30 V
DC at 10 A. IN1, IN2, IN3 and IN4 are the active LOW inputs, which means that a relay
is activated when a logic LOW signal is applied to its input pin. Relay contacts are normally
closed (NC). Activating the relay changes the active contacts such that the common pin
and NC pin become the two relay contacts and at the same time the LED at the input cir-
cuit of the relay board corresponding to the activated relay is turned ON. The VCC can be
connected to either +3.3 V or +5 V. Jumper JD is used to select the voltage for the relay.

Caution Because the current drawn by a relay can be in excess of 80 mA, you must
remove this jumper and connect an external power supply (e.g., +5 V) to pin JD-VCC.

Figure 4.51: 4-channel relay board.

● 71

Practical Audio DSP Projects with the ESP32 - UK.indd 71 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Circuit diagram: The circuit diagram of the project is shown in Figure 4.52 where the
4-channel relay inputs IN1, IN2, IN3 and IN4 are connected to GPIO pins 5, 17, 16 and 4
respectively.

Figure 4.52: Circuit diagram of the project.

Program listing: The program listing is shown in Figure 4.53 (Program: BTRELAY).

/***********************************************************************
* BLUETOOTH CLASSIC 4-CHANNEL RELAY CONTROL
* =========================================
*
* In this program a 4-channel relay board is connected to input pins
* 5,17,16, and 4 of the ESp32 DevKitC. The program receives commands from
* a Bluetooth classic compatible mobile phone and controls the relays
*
* Program: BTRELAY
* Date : April, 2023
* Author : Dogan Ibrahim
**********************************************************************/
#include"BluetoothSerial.h"
BluetoothSerial BT;

char rcv[10]; // Receive buffer


byte RelayArray[] = {5, 17, 16, 4}; // Relay interface

//
// This function activates or de-activates the relays depending on
// received command in character array rcv. Command n=ON# activates
// Relayn, command n=OFF# de-activates Relayn. # is the terminator
//
void RelayControl()
{
if(rcv[1] == '=' && rcv[2] == 'O' && rcv[3] == 'N')
{

● 72

Practical Audio DSP Projects with the ESP32 - UK.indd 72 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

for(int i = 0; i < 4; i++)


{
if(rcv[0] == i+1+'0')
{
digitalWrite(RelayArray[i], LOW);
BT.printf("Relay%d is activated\n\r", i+1);
}
}
}
else if(rcv[1] == '=' && rcv[2] == 'O' && rcv[3] == 'F' && rcv[4] == 'F')
{
for(int i = 0; i < 4; i++)
{
if(rcv[0] == i+1+'0')
{
digitalWrite(RelayArray[i], HIGH);
BT.printf("Relay%d is de-activated\n\r", i+1);
}
}
}
}

//
// Configure Relays as outputs, turn OFF the Relays to start with.
// Notice that a relay is turned OFF when logic HIGH is applied to its input
//
void setup()
{
for(int k = 0; k < 4; k++)
{
pinMode(RelayArray[k], OUTPUT); // Relays are outputs
digitalWrite(RelayArray[k], HIGH); // De-activate relays
}
BT.begin("ESPRelays"); // Initialize
}

void loop()
{
int dummy, k = 0, flag = 0;

while(1)
{
while(flag == 0) // while not terminator
{

● 73

Practical Audio DSP Projects with the ESP32 - UK.indd 73 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

if(BT.available()) // If data available


{
rcv[k] = BT.read(); // Read byte
if(rcv[k] == '#')flag = 1; // If terminator
k++; // Increment buffer count
}
}
k = 0; // Zero for next command
if(flag == 1)
{
while(BT.available())dummy = BT.read(); // Flush receive buffer
flag = 0; // Ready for next command
RelayControl(); // Decode command
}
}
}

Figure 4.53: Program: BTRELAY.

At the beginning of the program, the header file BluetoothSerial.h is included in the pro-
gram, receive buffer rcv is defined, and connections between the relay board and ESP32
DevKitC are defined in byte array RelayArray. Inside the setup routine, all the relays are
configured as outputs, and they are de-activated. The serial Bluetooth is then initialized
to the name ESPRelays. Inside the main program loop, the program reads data from the
smartphone until the terminator character # is detected. The input buffer is then flashed so
that any remaining characters in the input buffer are deleted. The program then calls func-
tion RelayControl to activate or de-activate the relays based on the received command in
buffer rcv. Every valid command is confirmed by sending a message to the mobile phone.
For example, if the received command is 1=ON# then Relay1 is activated and message
Relay1 is activated is sent to the mobile phone. Similarly, command 1=OFF# de-activat-
ed Relay1 and so on for all the other relays. The main program loop then repeats, waiting
for a new command from the smartphone.

Testing the program on a smartphone

• The Android app installed in the previous project can also be used in this
project.

• Connect your ESP32 DevKitC to a power supply (e.g., PC USB port or a portable
power supply).

• Open the Bluetooth folder on your smartphone and pair the phone with
ESPRelay if requested. Delete any older pairings if not needed.

• Install and open the Serial Bluetooth Terminal on your mobile phone.

● 74

Practical Audio DSP Projects with the ESP32 - UK.indd 74 06-07-2023 10:40
Chapter 4 • Elementary Projects using The Arduino IDE and the ESP32 DevKitC

• Click Devices from the menu and then click on device ESPRelays. You should
see the Connected message displayed.

• Press and hold button M1 to save a command on the mobile phone. Enter the
command, e.g., 1=ON# as shown in Figure 4.54 and click the tick at the top
right-hand side of the screen. Repeat to save other commands in M2, M3, M4,
etc.

Figure 4.54: Save 1=ON# command in button M1.]

• Click button M1 to send command 1=ON# to the ESP32 DevKitC. Notice that
a confirmation message is displayed on the smartphone screen for every
command sent.

Figure 4.55, finally, shows some example commands sent to the ESP32 DevKitC.

Figure 4.55: Example commands.

● 75

Practical Audio DSP Projects with the ESP32 - UK.indd 75 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 5 • Sound

5.1 Overview
Sound waves are created by the vibration of objects, for example, the string of a guitar,
the speaker of a radio, a person's vocal tract, and so on. You can hear sounds because the
air movement causes eardrum vibrations, which in turn are converted into nervous signals
sent to the brain.

There are two types of waves: transverse waves and longitudinal waves. In longitudinal
waves, the vibrations are parallel to the direction of wave travel. Some examples of longi-
tudinal waves include ultrasound waves, sound waves, and seismic P-waves. In transverse
waves, the vibrations are at right angles to the direction of wave travel. Some examples of
transverse waves include ripples on the surface of water, electromagnetic waves (e.g., light
waves, radio waves, etc.), seismic S-waves, and others.

Amplitude and frequency


Two key features of a wave are its amplitude and its frequency. As shown in Figure 5, the
amplitude is the excursion of the wave from the middle point to its highest point. The am-
plitude of a sound wave determines its volume such that sound waves having higher am-
plitudes are "louder." For example, a person shouting generates sound waves with higher
amplitudes than a person whispering. Similarly, the amplitude of the wave produced by a
whispering person is very low. The time between two wave peaks is known as the period
of the wave, and the frequency of the wave is found by taking the reciprocal of its period.
Mathematically, this is represented as:

Time period = 1 / frequency

or T=1/f

where the time period is measured in seconds and frequency is measured in Hz (hertz). For
example, the period of a sound wave having a frequency of 50 Hz is given by:

T = 1 / 50 = 0.02 seconds, or 20 ms

Figure 5.1: A typical wave.

● 76

Practical Audio DSP Projects with the ESP32 - UK.indd 76 06-07-2023 10:40
Chapter 5 • Sound

The frequency of a sound wave tells you about the pitch of that sound. A sound wave with
a higher frequency has a higher pitch. You should realize that most sound waves are made
up of combinations of lots of waves with different frequencies and amplitudes. For example,
in a conversation, people generate many sound waves with many combined frequencies
and amplitudes.

Of course, most sound waves are not pure like the ones shown above but made up of
combinations of lots of waves. Let's look at the sound waves corresponding to whistling,
speech, and music.

Wave speed
The wave speed is another feature of a wave. This is shown by the following mathematical
expression:

Where v is the wave speed in m/s, f is the frequency in Hz, and λ is the wavelength meas-
ured in metres (m).

For example, the wave speed of a wave with the frequency of 50 Hz and wavelength of 6
metres is given by:

v = 50 × 6 = 300 m/s

The speed of sound depends on the medium where it is created, its temperature and den-
sity. Some examples at 25 ºC are:

Medium Speed of sound


Air 330 m/s
A solid (steel) 6,000 m/s
A liquid (water) 1,500 m/s

5.2 Audible sound waves


This book is about audible sound waves. Adult humans can hear in a frequency range from
about 20 Hz to 20 kHz (20,000 Hz). Children and babies can hear frequencies slightly
higher than 20 kHz. Some animals, on the other hand, can hear sounds at higher than 20
kHz or lower than 20 Hz. For example, some bats can hear sounds as high as 200 kHz, but
their lower limits are around 20 kHz. The hearing frequency ranges of some animals are
given below:

Animal Hearing frequency range (Hz)


Dog 67 – 45,000
Horse 55 – 33,500
Rat 200 – 76,000
Elephant 16 – 10,500

● 77

Practical Audio DSP Projects with the ESP32 - UK.indd 77 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chicken 125 – 2,000


Sheep 125 – 42,500
Mouse 900 – 79,000
Rabbit 96 – 49,000

The human audio spectrum is divided into 7 bands with the following frequencies:

Band Frequency range


Brilliance 6 – 20 kHz
Presence 4 – 6 kHz
Upper midrange 2 – 4 kHz
Midrange 500 Hz – 2 kHz
Lower midrange 250 – 500 Hz
Bass 60 – 250 Hz
Sub-bass 20 – 60 Hz

5.3 Analog and digital audio sound


Analog audio processing has been around for many years and predates any form of digital
audio. In analog audio recording, a microphone is used to convert the sound signals into
electrical analog signals and then save these audio signals on a medium such as a tape (or
tape cassette) or a vinyl record with spiral grooves. Most of the early music and speech re-
cordings and playing devices were analog, with tape cassettes used by the public to record
their private messages or to play pre-recorded music.

In digital audio recording, a microphone is still used to convert the sound signals into
electrical signals, but then these analog signals are converted into digital forms using
analog-to-digital converter hardware. The resulting digital signals are saved as files in
computer memory. Nowadays, it is also possible to use digital microphones and record
signals directly in digital form.

A concise comparison between key aspects of analog and digital audio signals is given
below.

Degradation of quality: the quality of analog audio degrades as tape cassettes or vinyl
record age. This degradation is also noticeable when a recording gets copied or played back
many times. Digital signals on the other hand do not degrade by aging. Digital signals can
be copied to other mediums without using their qualities.

Signal to noise ratio (SNR): SNR is the amount of noise generated when a recording is
played. In other words, it describes how much unwanted noise signal is present in a played
sound signal. SNR is measured in decibels (dB). The higher the value the less noise there is
in the signal. For example, if an audio signal has an SNR of 50 dB, it means that the level
of the desired signal is 50 dB higher than the level of noise. Analog audio signals have low
SNR when played. Digital signals on the other hand achieve higher SNR and hence sound
clearer when played back.

● 78

Practical Audio DSP Projects with the ESP32 - UK.indd 78 06-07-2023 10:40
Chapter 5 • Sound

Audio bandwidth: The audio bandwidth is the range of signals permitted to be recorded
or played back. The higher the bandwidth the higher will be the maximum signal that can
be recorded correctly. Analog recordings in general have higher and bandwidths which cor-
respond to higher resolutions without compromising the audio quality.

Media type: digital audio signals can be stored in digital memories. Nowadays, smart-
phones, iPads, and tablets can store thousands of digital audio files in very small places.
This is not the case with analog media. Tape cassettes or vinyl records are bulky and they
can store only a limited amount of data.

In this book, the coverage is mainly using digital audio files and carrying out digital audio
signal processing (DSP) using digital audio files.

5.4 Digital audio sound file formats


Digital audio files can be in various formats. Some of the popular file formats are given in
this section.

5.4.1 Uncompressed audio file formats


Uncompressed audio files are not processed and they are available as captured and con-
verted to digital format. As a result of this, uncompressed audio files are large and take up
a lot of disk space. Some uncompressed audio file formats are:

PCM: This stands for Pulse-Code Modulation and there is no compression. The digital re-
cording is very close to its exact representation of analog sound. The average size of a PCM
file is about 10 MB per second. Therefore, a 3-minute PCM music file can take up to 30 MB
of disk space.

WAV: This stands for Waveform Audio file format, developed by Microsoft and IBM. Al-
though not all WAV files are uncompressed, most are and they are in PCM format with
wrappers, making them suitable for Windows systems. The average size of a WAV file is
about 10 MB per second. Therefore, a 3-minute WAV music file can take up to 30 MB of
disk space.

AIFF: This stands for Audio Interchange File Format and is similar to WAV. AIFF was de-
veloped by Apple for their MAC systems. AIFF is basically PCM-type files with wrappers,
making them suitable for MAC systems (they can be opened in Windows systems). Al-
though most AIFF audio files are uncompressed PCM files, there are compressed versions
as well called AIFF-C. The average size of a AIFF file is about 10 MB per second. Therefore,
a 3-minute AIFF music file can take up to 30 MB of disk space.

5.4.2 Audio files with lossy compression


These files are compressed and some data is lost during the compression process. The rea-
son for compression is to minimize the disk usage since uncompressed files take up a lot
of disk space. As a result, the sound quality is sacrificed for smaller file sizes. Some lossy
compressed audio file formats are:

● 79

Practical Audio DSP Projects with the ESP32 - UK.indd 79 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

MP3: This stands for MPEG-1 Audio Layer 3. This format is very popular for music files. In
this format, the quality of sound is reduced beyond the hearing range of normal ear. Also,
the quality of the sound is reduced for sounds that are not easy to hear. Almost all digital
devices nowadays with audio playback capabilities (e.g., PCs, smartphones, tablets, smart
TVs, etc.) can play MP3 audio files. The average bitrate for an MP3 file is 128 kbits per
second which requires about 1 Megabytes of data per minute of audio. Note: do not mix up
MP3 and MP4. MP3 is audio only, while MP4 supports both audio and video.

AAC: This stands for Advanced Audio Coding. Although it was developed as a competitor
to MP3, it never became as popular as MP3 even though it uses a much more advanced
compression algorithm than the MP3. AAC is currently used by YouTube, iOS, Android, and
by PlayStations. AAC files are slightly smaller than MP3 files.

WMA: This stands for Windows Media Audio. It was developed as a competitor to MP3 and
its compression algorithm is very similar to AAC, giving higher-quality audio sound. WMA
is a proprietary format created by Microsoft and as such it has not become very popular.
WMA files are slightly larger than MP3 files.

5.4.3 Audio files with lossless compression


In these file formats, the file size is reduced with compression without any data quality loss.
These files are larger than the lossy compressed files and smaller than uncompressed files.
Some lossless compressed audio file formats are:

FLAC: This stands for Free Lossless Audio Codec and it is a popular file format that can
compress a file by up to 60% without losing its quality. FLAC is the main competitor of MP3
for music files and it is currently regarded as the best audio file format as far as size and
sound quality are concerned. For example, a 3-minute FLAC music file takes about 15 MB
as compared to MP3 which takes only 3 MB.

ALAC: This stands for Apple Lossless Audio Codec and it is similar to FLAC, although it is
less efficient as far as compression is concerned. Apple products such as iOS and iTunes
support ALAC. ALC file size is similar to those of FLAC.

There is also a lossless version of the WMA file format, but it is not as efficient as the FLAC
or ALAC.

5.4.4 Which audio file format to choose?


The choice depends on the sound quality you are after and the amount of disk space you
can spare. If you wish to listen to high-quality raw music and not worried about the disk
space it will occupy, you should choose an uncompressed file. If at the same time you wish
to use less disk space then a file with lossless compression, such as FLAC or ALAC could
be a viable choice. If you wish to listen to music at ordinary quality and worried about disk
space, then MP3 or another file format with lossy compression could be a desirable choice.

● 80

Practical Audio DSP Projects with the ESP32 - UK.indd 80 06-07-2023 10:40
Chapter 5 • Sound

5.5 High-quality digital audio sound


In general terms, high-quality digital audio refers to music files that have high ADC sam-
pling rates and large bit depths than standard CD music files. CD music files are specified at
16-bit, 44.1 kHz sampling rate. With a 44.1 kHz sampling rate, all the audible frequencies
are covered. Higher-quality (Hi-res) audio files are sampled with 24-bit and 48 kHz sam-
pling rate, or 24-bit 96 kHz sampling, or even 24-bit 192 kHz sampling. In most cases, the
human ear cannot differentiate a music sampled higher than 16-bit and 44.1 kHz sampling
rate. One disadvantage of sampling at higher than 16-bit is that more disk space is required
to save the file.

● 81

Practical Audio DSP Projects with the ESP32 - UK.indd 81 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 6 • Audio DSP Projects

6.1 Overview
The acronym DSP stands for one of two things: Digital Signal Processor, or Digital Signal
Processing. A Digital Signal Processor refers to specialized microcontroller hardware de-
signed to execute specialized instructions in real time.

The topic of this book is Digital Signal Processing — or DSP from here on in this book. DSP
is a very broad field covering signals from very low frequencies to very high frequencies.
In this book, we are only interested in audio signals covering the frequency range of 20
Hz to 20 kHz. In a typical DSP application, the input signal (e.g., from a microphone) can
either be digital or analog. In the case of analog input, the signal is converted into digital
form using an ADC (analog-to-digital converter) and is fed to a microcontroller for further
processing. The signal is then processed in one of these ways:

• filtered to remove unwanted high-frequency noise;


• noise is cancelled using special noise cancelling algorithms;
• the frequency spectrum of the signal is extracted and analyzed;
• the signal shape is modified;
• audio signals are synthesized;
• and so on.

The resulting digital signal is converted back into analog using a DAC (digital-to-analog
converter) and sent to a loudspeaker or some other output device. All of the signal process-
ing is conducted using software algorithms running on the target microcontroller. It is much
easier to edit and manipulate digital signals than analog signals. DSP is used extensively
nowadays by professional music makers. Not surprisingly, many plugins are available on
PCs which simplify the editing and processing of already recorded music files.

The global audio DSP market size was valued at $11.06 billion in 2019 and is projected to
reach $23.43 billion by 2027 (Allied Market Research).

This book is about using the ESP32 DevKitC microcontroller development board in audio
DSP applications. Many working projects are given in the book to illustrate how simple
hardware can be set up around the ESP32 processor and how programs can be developed
to achieve audio DSP processing in real time.

6.2 The I2S bus


The I2S (Inter-Integrated Circuit Sound Protocol) is a serial bus interface standard used to
connect digital audio devices together. It was introduced in 1986 by Philips Semiconductors
(now NXP Semiconductors) and then revised in 1996 and 2022. The I2S protocol sends
pulse-code modulation (PCM) digital audio data from a controller to a target. The bus has at
least three lines: bit clock, word select, and data line. Word select is used to specify which
of the stereo channel, left or right, the data should be sent to. Readers should understand
that the I2C and I2S are completely different bus protocols and they are unrelated.

● 82

Practical Audio DSP Projects with the ESP32 - UK.indd 82 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.1 shows the block diagram of a conventional audio DSP system that does not
use the I2bus. Here, the audio signal is received from an analog microphone. This signal
is then converted into digital form using an ADC. The resulting digital signal is then fed
to a microcontroller which processes this digital signal. At the end, the signal is converted
back into analog using a DAC converter and is fed to a speaker. An analog amplifier (not
shown) is typically used to increase the signal level for the loudspeaker. In most low-fre-
quency applications, the ADC and DAC can be part of the microcontroller. In high-speed
and high-quality applications, it may be necessary to use external, professional-quality ADC
and DAC converters.

Figure 6.1: Conventional audio DSP system.

Figure 6.2 shows the block diagram of a digital audio DSP system using the I2S bus inter-
face. Here, a digital microphone is used and compatible with the I2S bus. The output of
the microphone, which is a digital signal, is fed to the microcontroller I2S bus input. The
signal is processed by the microcontroller as required and gets sent to an I2S-compatible
amplifier module in digital form. The output of the amplifier is an analog signal which drives
the speaker.

As you will be seeing in the example projects in this chapter, the microcontroller used in all
the projects is the ESP32 DevKitC.

Figure 6.2: Digital audio DSP system.

The line definitions of the I2S bus are summarized below.

Bit Clock: this pin is the serial clock line, usually denoted as BCLK. The clock runs contin-
uously.

Word Select: this pin is usually denoted by WS and it selects the channels. 0 corresponds
to left channel, while 1 corresponds to the right channel.

● 83

Practical Audio DSP Projects with the ESP32 - UK.indd 83 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Data: This pin is usually denoted by SD, or SDATA and is the serial data line. The data is
sent out in 2's complement format with the MSB bit first. The transmitter and receiver do
not need to have an agreed-upon word length; the transmitter sends what it has, and the
receiver takes what it can use. New data bits can be clocked out on the rising or falling edge
of the clock. However, they must be clocked in on the rising edge.

The bit clock is sent out for each bit of data on the data line. The frequency of this clock is
the given by the product of the sample rate, the number of bits per channel, and the num-
ber of channels. In a typical audio CD, the standard is the 44.1 kHz sample rate with 16 bits
of data. Assuming 2 channels (i.e., stereo), the bit clock frequency will be:

44.1 kHz × 16 × 2 = 1.4112 MHz

Therefore, if you want to send two channels of high-quality audio, you will need a clock rate
of 1.4112 MHz.

The telephone quality sound is sampled at 8 kHz with 8 bits and there is only one channel.
Therefore, to send telephone-quality audio you will need a clock frequency of:

8 kHz × 8 × 1 = 64 kHz

The maximum clock frequency is 3.125 MHz.

I2S allows up to 2 channels to be used on the same data line and this is selected by the
Word select bit. For 2 channel stereo operation the left audio is transmitted on the low cycle
of the Word select, and the right channel is transmitted on the high cycle. The I2S bus is not
like the I2C bus where multiple devices can be connected on the same bus line. In I2S only
two channels of a device can be used, and multiple devices cannot be connected to the bus.
The maximum length of the I2S bus is specified as 3 meters.

The bit clock and Word select signals can be generated with a receiver, transmitter, or a
third-party controller (see Figure 6.3).

Figure 6.3: I2S configurations (taken from the I2S specification).

● 84

Practical Audio DSP Projects with the ESP32 - UK.indd 84 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.4 shows the timing diagram of the I2S bus.

Figure 6.4: I2S bus timing (taken from the I2S specification).

The advantages of the I2S bus are:


• There are no data synchronization issues since there is a single master device.
• I2S output-based microphone does not require an analog front end.
• Separate clock and data lines are used which results in low jitter.
• ADC and DAC are not required since the signals are digital.

The disadvantages of the I2S bus are:


• There is no error detection or correction and therefore errors can occur on the
line.
• As a result of the propagation delays, synchronization problems may arise at
high clock rates.
• There is no standard I2S cabling or connector procedure; different
manufacturers use different cables and connectors.

6.3 I2S support of popular microcontroller development boards


At the time of authoring the book, the following microcontroller development boards were
found to provide I2S support (this list is not exhaustive):
• Arduino MKR Zero
• ESP32 DevKitC
• ESP32-C3
• Teensy
• STM32
• PIC32MX
• LPC1776FET180
• Kinetis KL46 Sub-Family
• etc.

In this book, you will be using the ESP32 DevKitC development board.

6.4 The ESP32 DevKitC I2S bus pins


The ESP32 (not the ESP32-C3) has two I2S interfaces: I2S0 and I2S1. Each interface can
be configured as a controller (or target) and each can be an audio receiver or transmitter.
Each I2S can operate in half-duplex mode: DMA (Direct Memory Access) is also supported
which allows data to be streamed without requiring the CPU to process each data sample.

● 85

Practical Audio DSP Projects with the ESP32 - UK.indd 85 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

This feature can be very useful in high-quality audio processing applications.

A useful mode is also supported where the output of I2S0 can be internally routed to the in-
ternal ESP32 DAC (internal DAC is 8 bits wide) so that direct analog output can be obtained
without any external I2S device.

There are no dedicated I2S pins on the ESP32. Instead, you configure/enable the
pins in your code using the supplied I2S library functions.

In the remaining sections of this chapter, projects are given using the I2S bus interface
of the ESP32 DevKitC for audio digital DSP. The following sub-sections are given for each
project where applicable:
• Title
• Description
• Block diagram
• Circuit diagram
• Construction (wherever possible)
• Program listing and full description
• Suggestions for further work (wherever possible)

6.5 Project 1: Using a digital microphone to capture audible sound


Description: In this project, a digital microphone is connected to the ESP32 DevKitC
development board through the I2S interface. The sound signals captured by the digital
microphone are displayed on the Arduino Serial Monitor.

The aim: The aim of this project is to show how a digital microphone can be connected to
the ESP32 processor and how audio signals can be captured and displayed.

Block diagram: Figure 6.5 shows the block diagram of the project.

Figure 6.5: Block diagram of the project.

In this project, a Youmile INMP441 omnidirectional I2S-compatible microphone is used


(Figure 6.6).

● 86

Practical Audio DSP Projects with the ESP32 - UK.indd 86 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.6: INMP digital microphone.

The INMP441 digital microphone has the following features:


• High-performance, low-power, digital output, omnidirectional MEMS
microphone. The complete INMP441 consists of a MEMS sensor, signal
conditioning, analog to digital converter, anti-aliasing filter, power management
and industry-standard 24-bit I2S interface. The I2S interface allows the
INMP441 to be directly connected to digital processors such as DSPs and
microcontrollers without the need for an audio codec for use in the system.
• Omnidirectional and highly sensitive with 26 dBFS audio sensitivity, having flat
wideband frequency response from 60 Hz to 15 kHz, thus capturing natural
sound.
• High signal to noise ratio quoted as 61 dBA
• Power consumption: only 1.4 mA
• Operating voltage: +1.8 V to +3.3 V
• Weight: only 20 g
• Color: black
• Material: metal and PVC

The INMP441 is a 6-pin, round shaped device with the following pin definitions:

VDD: +3.3 V
GND: power supply GND
SD: serial data
SCK: serial clock
WS: Word Select
L/R: left/right channel selection. When LOW, the microphone outputs signals
on the left channel. When HIGH, the microphone outputs signals on the
right channel

The microphone device is shipped with the pins unconnected. Six pins and a 6-way Dupont
cable are supplied with the microphone. You should use a fine-tip soldering iron to connect
the supplied pins to the microphone holes. The Dupont cable should then be connected to
the microphone pins.

Circuit diagram: Figure 6.7 shows the circuit diagram of the project. The connections
between the microphone and the ESP32 DevKitC are as follows:

● 87

Practical Audio DSP Projects with the ESP32 - UK.indd 87 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Microphone pin ESP32 pin


VDD +3.3 V (pin 1)
GND GND (pin 38)
SD GPIO32 (pin 7)
SCK GPIO33 (pin 8)
WS GPIO25 (pin 9)
L/R GND (pin 38)

Figure 6.7: Circuit diagram of the project.

Notice that the microphone L/R pin is connected to GNS+D as you will be using the Left
channel only. Notice that there is a hole on the microphone device where the pin names are
written and this is where the actual microphone is.

Program listing: The program listing is shown in Figure 6.8 (Program: DigMic). At the
beginning of the program, the I2S library is included in the program and the GPIO connec-
tions between the ESP32 and INMP441 microphone are defined. Since you will be using the
I2S0, this is defined. The input buffer and its length are then defined. Function i2s_set-
pin() sets the pin configuration as defined earlier.

i2s_config_t is a structure defined as follows:

typedef struct
{
i2s_mode_t mode; /*I2S work mode*/
int sample_rate; /*I2S sample rate*/
i2s_bits_per_sample_t bits_per_sample; /*I2S bits per sample*/
i2s_channel_fmt_t channel_format; /*I2S channel format */
i2s_comm_format_t communication_format; /*I2S communication format
*/
int intr_alloc_flags; /*Flags used to allocate
interrupt*/
int dma_buf_count; /*I2S DMA Buffer Count */
int dma_buf_len; /*I2S DMA Buffer Length */
} i2s_config_t;

● 88

Practical Audio DSP Projects with the ESP32 - UK.indd 88 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Function i2s_install() configures the I2S0 as follows:

• Master in receive mode


• Sample rate 44100 Hz
• 16 bits per sample
• Only left channel data
• No interrupt flags
• DMA buffer count 8
• DMA buffer length 64

Function setup() sets the Serial Monitor baud rate to 115200, calls functions i2s_install()
and i2s_setpin() and then starts the i2sport.

Function loop() is the main program loop. Here, data is received from the I2S interface by
calling function i2s_read(). The received samples are averaged and sent to the Serial Plot-
ter of the Arduino IDE. Notice that another function to receive samples is: i2s_pop_sam-
ple(), but this function may be removed in future releases of the I2S library.

A list of the I2S functions is given on the following website:


https://docs.espressif.com/projects/esp-idf/en/v3.3/api-reference/peripherals/
i2s.html

Some of the commonly used I2S functions are (see the above link for the function argu-
ments):

i2s_set_pin(): Set I2S pin number


i2s_set_dac_mode(): Set I2S DAC mode (built in DAC is disabled by default)
i2s_driver_install(): Install and start I2S driver
i2s_driver_uninstall(): Uninstall I2S driver
i2s_write(): Write data to I2S DMA transmit buffer
i2s_read(): Read data from I2S DMA receive buffer
i2s_set_sample_rates(): Set sample rate used for TX and RX
i2s_stop(): Stop I2S driver
i2s_start(): Start I2S driver
i2s_set_clk(): Set clock and bit width used for I2S RX and TX

/****************************************************************
* DIGITAL MICROPHONE SOUND CAPTURE
* ================================
*
* In this program an INMP441 digital microphone is used to capture
* sound signals using the I2S interface of the ESP32 DevKitC
* microcontroller development system. The captured waveform is
* displayed on the Serial Monitor
*

● 89

Practical Audio DSP Projects with the ESP32 - UK.indd 89 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

* Author : Dogan Ibrahim


* Program: DigMic
* Date : April, 2023
**************************************************************/
#include <driver/i2s.h>

int16_t i, samples_read;
int bytes_read;
size_t bytesIn;

#define buffer_Len 64
int16_t i2s_Buffer[buffer_Len];
float mean_samples;

//
// INMP441 I2S microphone connections
//
#define I2S_WS 25 // WS pin
#define I2S_SD 32 // SD pin
#define I2S_SCK 33 // SCK pin

#define I2S_PORT I2S_NUM_0 // Use I2S0

//
// I2S pin configuration
//
void i2s_setpin()
{
const i2s_pin_config_t pin_config =
{
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE, // Not used (output only)
.data_in_num = I2S_SD
};
i2s_set_pin(I2S_PORT, &pin_config);
}

//
// Configure I2S
//
void i2s_install()
{
const i2s_config_t i2s_config =

● 90

Practical Audio DSP Projects with the ESP32 - UK.indd 90 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

{
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 44100,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format=i2s_comm_format_t(I2S_COMM_FORMAT_I2S |
I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 8,
.dma_buf_len = buffer_Len,
.use_apll = false
};
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}

void setup()
{
Serial.begin(115200); // Serial Monitor
i2s_install(); // Install i2s
i2s_setpin(); // COnfigure pins
i2s_start(I2S_PORT); // Start i2s
delay(500); // Small delay
}

//
// Read audio samples into i2s_Buffer, find the mean and send to plotter.
// bytesIn is the number of bytes read, i2s_Buffer stores the samples read
// buffer_Len is teh length of the buffer
//
void loop()
{
bytesIn = 0;
bytes_read = i2s_read(I2S_PORT,&i2s_Buffer,buffer_Len,&bytesIn,portMAX_DELAY);

samples_read = bytesIn / 8;
if(samples_read > 0)
{
mean_samples = 0;
for(i=0; i < samples_read; i++)
{
mean_samples = mean_samples + i2s_Buffer[i];
}
mean_samples = mean_samples / samples_read;
Serial.println(mean_samples); // Send to Serial Monitor (plotter)

● 91

Practical Audio DSP Projects with the ESP32 - UK.indd 91 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 6.8: Program: DigMic.

Compile and upload your program to the ESP32 DevKitC. Start the Serial Plotter, making
sure that the baud rate is set to 115,200. You should see a sound waveform similar to the
one shown in Figure 6.9 when it is quiet. Playing music near the microphone should change
the waveform. An example is shown in Figure 6.10.

Figure 6.9: Waveform when there is no noise.

● 92

Practical Audio DSP Projects with the ESP32 - UK.indd 92 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.10: Waveform when music is played.

Figure 6.11 shows the SCK signal captured using a digital oscilloscope.

Figure 6.11: SCK signal.

6.6 Project 2: Using an amplifier and loudspeaker


Description: This project is similar to the previous one but here an I2S-compatible class-D
amplifier module and a speaker are connected to the ESP32 DevKitC development board.
Any audio signals received by the digital microphone are amplified and made audible on
the loudspeaker.

The aim: The aim of this project is to show how an I2S-compatible digital microphone as
well as an I2S-compatible class-D amplifier module and a speaker can be connected to the
ESP32 processor.

● 93

Practical Audio DSP Projects with the ESP32 - UK.indd 93 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Block diagram: Figure 6.12 shows the block diagram of the project.

Figure 6.12: Block diagram of the project.

In this project, a Youmile INMP441 omnidirectional I2S-compatible microphone is used as in


the previous project. Additionally, MAX98357A-type I2S-compatible 3-watt, class-D ampli-
fier module is used (manufactured by TECNOIOT). The amplifier drives a 3-watt standard
loudspeaker.

Figure 6.13 shows the MAX98357A amplifier module. This module has the following fea-
tures:
• 3 W output power (into 4 ohms at 5 V). 4 ohm or 8 ohm speakers with voice
coils must be used (no dynamic speakers)
• Class-D amplifier module with on-board DAC decoder module
• 2.5 V to +5.5 V operation
• 2.4 mA quiescent current consumption
• 92% efficiency
• Only 25 μV RMS output noise
• 8 kHz to 96 kHz sampling
• 77 dB PSRR at 1 kHz
• Space-saving module (1.345 mm × 1.435 mm)

The amplifier module has the following pins:

+ –: Speaker connection
LRC: I2S WS
BCLK: I2S SCK
DIN: I2S SD (this is the data input, not the SD pin)
GAIN: Gain set with a resistor
SD: L/R output select
GND: Power supply GND
VIN: Power (+3.3 V)

● 94

Practical Audio DSP Projects with the ESP32 - UK.indd 94 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

The SD pin is for L/R output selection and shutdown mode. The various settings of the SD
pin are:
• Connect SD to GND (less than 0.16 V) to shut down the amplifier.
• Connect SD to a voltage between 0.16 V and 0.77 V for stereo average output
(i.e., Right + Left / 2).
• Connect SD between 0.77 V and 1.4 V for the Right channel only.
• Connect SD to higher than 1.4 V for the Left channel only.

The output signal of the amplifier is a 330-KHz PWM square wave with a duty cycle pro-
portional to the audio signal. The high-frequency component(s) of the signal are effectively
filtered out by the inductance of the speaker coil.

The output power of the amplifier at different power supply voltages is (for 10% THD. For
lower THD, the output power will be less):

4 ohm speaker, 5 V supply: 3 W


4 ohm speaker 3.3 V supply: 1.3 W
8 ohm speaker, 5 V supply: 1.8 W
8 ohm speaker, 3.3 V supply: 0.8 W

The gain of the amplifier can be set at: 3 dB, 6 dB, 9 dB, 12 dB, and 15 dB using a resistor
as follows (the module should be powered down and up for the new gain to take effect):

15 dB: Connect a 100 k-ohm resistor between GAIN and GND


12 dB: Connect GAIN to GND
9 dB: Leave GAIN unconnected (default state)
6 dB: Connect GAIN to VIN
3 dB: Connect a 100 k-ohm resistor between GAIN and VIN

The amplifier module can be connected to any pins of the ESP32 DevKitC development
board. Also, the amplifier power supply VIN can be connected to +5 V for higher power
output.

Figure 6.13: MAX98357A amplifier module.

● 95

Practical Audio DSP Projects with the ESP32 - UK.indd 95 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Circuit diagram: The circuit diagram of the project is shown in Figure 6.14. the connec-
tions between the ESP32, INMP441, and MAX98357A are as follows. Notice here that the
amplifier gain is set to 15 dB:

Microphone pin ESP32 pin


VDD +3.3 V (pin 1)
GND GND (pin 38)
SD GPIO32 (pin 7)
SCK GPIO33 (pin 8)
WS GPIO25 (pin 9)
L/R GND (pin 38)

Amplifier pin ESP32 pin


VIN +5 V (pin 19)
GND GND (pin 14)
GAIN 100 K to GND (pin 14) for 15 dB gain
DIN (SD) GPIO22 (pin 36)
BCLK (SCK) GPIO23 (pin 37)
LRC (WS) GPIO21 (pin 33)

Figure 6.14: Circuit diagram of the project.

Program listing: Figure 6.15 shows the program listing (Program: DigAmp). Part of this
program is similar to Figure 6.8. At the beginning of the program, the buffer size is set to
64 and buffer i2s_Buffer is declared. Then the microphone the amplifier connections are
defined as the GPIO ports of ESP32 as follows:

//
// INMP441 I2S microphone connections
//
#define I2S_WS_MIC 25
#define I2S_SD_MIC 32
#define I2S_SCK_MIC 33

//

● 96

Practical Audio DSP Projects with the ESP32 - UK.indd 96 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

// MAX98357A amplifier connections


//
#define I2S_WS_AMP 21
#define I2S_SD_AMP 22
#define I2S_SCK_AMP 23

The two I2S modules I2S0 and I2S1 of ESP32 are assigned to I2S_PORT0 and I2S_PORT1,
respectively. I2S_PORT0 is used for the microphone and I2S_PORT1 is used for the am-
plifier. The program then configures the microphone and amplifier pins as follows. Notice
that the microphone has input and no output, and the amplifier has output and no input:

//
// I2S microphone pin configuration
//
void i2s_setpin_MIC()
{
const i2s_pin_config_t pin_config =
{
.bck_io_num = I2S_SCK_MIC,
.ws_io_num = I2S_WS_MIC,
.data_out_num = I2S_PIN_NO_CHANGE, // No output
.data_in_num = I2S_SD_MIC // Input from microphone
};
i2s_set_pin(I2S_PORT0, &pin_config);
}

//
// I2S amplifier pin configuration
//
void i2s_setpin_AMP()
{
const i2s_pin_config_t pin_config =
{
.bck_io_num = I2S_SCK_AMP,
.ws_io_num = I2S_WS_AMP,
.data_out_num = I2S_SD_AMP, // Output to amplifier
.data_in_num = I2S_PIN_NO_CHANGE // No input
};
i2s_set_pin(I2S_PORT1, &pin_config);
}

The program then installs the I2S0 for the microphone using a sampling rate of 44100 Hz,
16 bits and in RX mode:

● 97

Practical Audio DSP Projects with the ESP32 - UK.indd 97 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

//
// Configure I2S0 for microphone
//
void i2s_install_MIC()
{
const i2s_config_t i2s_config =
{
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 44100,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S |
I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 8,
.dma_buf_len = buffer_Len,
.use_apll = false
};
i2s_driver_install(I2S_PORT0, &i2s_config, 0, NULL);
}

v1 is also installed for the amplifier, where the sample rate and bit count is same as for the
microphone, but the mode is set to TX:

//
// Configure I2S1 for amplifier
//
void i2s_install_AMP()
{
const i2s_config_t i2s_config =
{
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 44100,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S |
I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 8,
.dma_buf_len = buffer_Len,
.use_apll = false
};
i2s_driver_install(I2S_PORT1, &i2s_config, 0, NULL);
}

● 98

Practical Audio DSP Projects with the ESP32 - UK.indd 98 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Inside the setup() function I2S is installed for the microphone and the amplifier, pins are
configured, and both I2S channels are started.

The main program runs continuously inside the loop() function, Here, function i2s_read()
captures audio data from the microphone. This data is then sent to the amplifier using
function i2s_write():

/****************************************************************
* DIGITAL MICROPHONE, AMPLIFIER AND SPEAKER
* =========================================
*
* In this program an INMP441 digital microphone is used to capture
* sound signals using the I2S interface of the ESP32 DevKitC
* microcontroller development system. Additionally, a MAX98357A
* class D amplifier module and a speaker are used in the project
* The program captures the audio signals, amplifies them and
* sends to the speaker
*
* Author : Dogan Ibrahim
* Program: DigAmp
* Date : April, 2023
**************************************************************/
#include <driver/i2s.h>

int bytes_read;
size_t bytesIn, bytesWritten;

#define buffer_Len 64
int16_t i2s_Buffer[buffer_Len];

//
// INMP441 I2S microphone connections
//
#define I2S_WS_MIC 25
#define I2S_SD_MIC 32
#define I2S_SCK_MIC 33

//
// MAX98357A amplifier connections
//
#define I2S_WS_AMP 21
#define I2S_SD_AMP 22
#define I2S_SCK_AMP 23

#define I2S_PORT0 I2S_NUM_0 // I2S0


#define I2S_PORT1 I2S_NUM_1 // I2S1

● 99

Practical Audio DSP Projects with the ESP32 - UK.indd 99 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

//
// I2S microphone pin configuration
//
void i2s_setpin_MIC()
{
const i2s_pin_config_t pin_config =
{
.bck_io_num = I2S_SCK_MIC,
.ws_io_num = I2S_WS_MIC,
.data_out_num = I2S_PIN_NO_CHANGE, // Not used (output only)
.data_in_num = I2S_SD_MIC
};
i2s_set_pin(I2S_PORT0, &pin_config);
}

//
// I2S amplifier pin configuration
//
void i2s_setpin_AMP()
{
const i2s_pin_config_t pin_config =
{
.bck_io_num = I2S_SCK_AMP,
.ws_io_num = I2S_WS_AMP,
.data_out_num = I2S_SD_AMP,
.data_in_num = I2S_PIN_NO_CHANGE
};
i2s_set_pin(I2S_PORT1, &pin_config);
}

//
// Configure I2S0 for microphone
//
void i2s_install_MIC()
{
const i2s_config_t i2s_config =
{
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 44100,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S |
I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 8,

● 100

Practical Audio DSP Projects with the ESP32 - UK.indd 100 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

.dma_buf_len = buffer_Len,
.use_apll = false
};
i2s_driver_install(I2S_PORT0, &i2s_config, 0, NULL);
}

//
// Configure I2S1 for amplifier
//
void i2s_install_AMP()
{
const i2s_config_t i2s_config =
{
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 44100,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S |
I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 8,
.dma_buf_len = buffer_Len,
.use_apll = false
};
i2s_driver_install(I2S_PORT1, &i2s_config, 0, NULL);
}

void setup()
{
Serial.begin(115200);
i2s_install_MIC();
i2s_install_AMP();
i2s_setpin_MIC();
i2s_setpin_AMP();
i2s_start(I2S_PORT0);
i2s_start(I2S_PORT1);
}

//
// Read audio samples into i2s_Buffer from the microphone
// send the captured data to the amplifier and then to the
// speaker
//
void loop()

● 101

Practical Audio DSP Projects with the ESP32 - UK.indd 101 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

{
bytesIn = 0;
bytes_read = i2s_read(I2S_PORT0,&i2s_Buffer,buffer_Len,&bytesIn,portMAX_DELAY);
if(bytesIn > 0)
{
i2s_write(I2S_PORT1,&i2s_Buffer,bytesIn,&bytesWritten,portMAX_DELAY);
}
}

Figure 6.15: Program: DigAmp.

Increasing the gain by software


The gain can be increased in software before sending the audio samples to the amplifier.
This requires the audio samples to be multiplied by a constant gain factor which is a simple
modification to the program given in Figure 6.15.

As an example, to increase the gain by a factor of 3, you will have to modify the code in-
side the program loop() as follows. The modified program is named as DigAmp2 on the
website of the book:

void loop()
{
bytesIn = 0;
bytes_read = i2s_read(I2S_PORT0,&i2s_Buffer,buffer_Len,&bytesIn,portMAX_DELAY);
if(bytesIn > 0)
{
for(int i=0; i < bytesIn; i++)i2s_Buffer[i]=3*i2s_Buffer[i];
i2s_write(I2S_PORT1,&i2s_Buffer,bytesIn,&bytesWritten,portMAX_DELAY);
}

6.7 Project 3: Playing MP3 music stored on an SD card


Description: In this project, you will be playing pre-recorded MP3 music stored on an SD
card connected to the ESP32 DevKitC.

The aim: The aim of this project is to show how MP3-compatible music stored on an SD
card can be played using your ESP32. It is assumed that you have already downloaded and
stored MP3-compatible music on your SD card.

Block diagram: Figure 6.16 shows the block diagram. In this project, you will be using the
MAX98357A I2S-compatible amplifier and a microSD card.

● 102

Practical Audio DSP Projects with the ESP32 - UK.indd 102 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.16: Block diagram of the project.

Circuit diagram: You have already used a microSD card-based projects in Sections 4.8
and 4.9. Here, the same circuit diagram as the one in Figure 4.37 is used, but additionally,
the MAX98357A amplifier module and a speaker are added to the circuit.

Figure 6.17 shows the circuit diagram. The connections between the microSD card and
ESP32 DevKitC, as well as between the amplifier and the ESP32 are as follows:

SD card adapter pin DevKitC pin


GND GND (pin 38)
VCC +5 V (pin 19)
SCK GPIO18 (pin 30)
MISO GPIO19 (pin 31)
MOSI GPIO23 (pin 37)
CS GPIO5 (pin 29)

Amplifier pin DevKitC pin


VIN +5 V (pin 19)
GND GND (pin 14)
GAIN 100 k to GND (pin 14) for 15 dB gain
DIN (SD) GPIO22 (pin 36)
BCLK (SCK) GPIO4 (pin 26)
LRC (WS) GPIO21 (pin 33)

● 103

Practical Audio DSP Projects with the ESP32 - UK.indd 103 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 6.17: Circuit diagram of the project.

Program listing: In this project you will be using the ESP32-Audio I2S library to simplify
programming. The steps to load this library to your Arduino IDE are:

• Go to this website:

https://github.com/schreibfaul1/ESP32-audioI2S

• Click Code (green button) and save the .zip file in a folder on your hard disk.
The file is named: ESP32-audioI2S-master.zip.

• Start your Arduino IDE.

• Click Sketch  Include Library and select Add .ZIP library…

• Browse to the library you just downloaded and click Open. You should see the
message Library added to your libraries. Check "include library" menu
at the bottom of the IDE screen.

Figure 6.18 shows the program listing (Program: SDMusic). It is assumed that a music file
called: sample-15s.mp3 (taken from website: https://samplelib.com/sample-mp3.html)
has already been stored on your microSD card. At the beginning of the program the library
headers used in te program are included. Then, the connections between the microSD card
adapter and ESP32, and between the amplifier and ESP32 are defined. CS of the card is
configured as output and set HIGH so that it is disabled to start with. The SPI bus is then
configured for the card and the card is started. If the microSD card is not accessible (e.g.,
wrong connections, card not in the header, or card not formatted correctly) the message
Error in microSD card is displayed and the program stops (waits forever). Otherwise, the
audio volume is set to 10 and the music file on the microSD card is opened. the volume
can be set to 21 in 22 steps (i.e., the maximum volume is 21). The number of steps can be
changed with function setVolumeSteps(). The loop() is called repeatedly. If everything
is correct, you should hear the music on your speaker. If there is no music, start the Serial
Monitor and check to make sure that the microSD card is accessed correctly (i.e., message
microSD card accessed correctly is displayed).

● 104

Practical Audio DSP Projects with the ESP32 - UK.indd 104 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

/****************************************************************
* PLAY MUSIC STORED ON SD CARD THROUGH AMPLIFIER
* ==============================================
*
* In this program MP3 compatible music file is stored on microSD
* card. The program opens the file and plays the music on the
* speaker through the MAX98357A amplifier
*
* Author : Dogan Ibrahim
* Program: SDMusic
* Date : April, 2023
**************************************************************/
#include "Arduino.h"
#include "Audio.h"
#include "SD.h"
#include "FS.h"

//
// microSD card to ESP32 connections
//
#define CARD_MOSI 23
#define CARD_MISO 19
#define CARD_SCK 18
#define CARD_CS 5

//
// Define MAX98357A amplifier connections
//
#define I2S_BCLK 4
#define I2S_LRC 21
#define I2S_DOUT 22

Audio audio; // Audio object

void setup()
{
pinMode(CARD_CS, OUTPUT); // CS is output
digitalWrite(CARD_CS, HIGH); // CS HIGH
SPI.begin(CARD_SCK,CARD_MISO,CARD_MOSI); // Init SPI bus

Serial.begin(115200); // Serial Monitor


if(!SD.begin(CARD_CS)) // Start SD card
{
Serial.println("Error in microSD card"); // card error
while(true);

● 105

Practical Audio DSP Projects with the ESP32 - UK.indd 105 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

}
Serial.println("microSD card accessed correctly");

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); // Setup I2S


audio.setVolume(10); // Set volume
audio.connecttoFS(SD,"sample-15s.mp3"); // Open file
}

void loop()
{
audio.loop();
}

Figure 6.18: Program: SDMusic.

Figure 6.19 shows the project built on a breadboard.

Figure 6.19: Project built on a breadboard.

6.8 Project 4: Playing a list of music files (playlist)


Description: This project is very similar to the previous one but here, a list of different
music files are played one after the other one continuously. The files are stored on the
microSD card.

The aim: The aim of this project is to show how more than one MP-compatible music
stored on the SD card can be played one after the other one.

The block diagram and circuit diagram of the project are in Figure 6.16 and Figure 6.17,
respectively.

● 106

Practical Audio DSP Projects with the ESP32 - UK.indd 106 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Program listing: Figure 6.20 shows the program listing (Program: SDMusic2). Four short
MP3-compatible music files with the names: sample-15s.mp3, sample-12s.mp3, sam-
ple-9s.mp3 and sample-6s.mp3 are taken from this website:

https://samplelib.com/sample-mp3.html

The first file is played inside the setup() routine. At the end of a file, the program jumps
to function called audio_eof_mp3(). Inside this file, the files in the playlist are defined so
that at the end of a file the program jumps here and continues with the next music file. The
integer variable PlayList chooses which file is to play next. This variable changes from 0 to
the maximum number of files, which is 4 in this example project. Initially, PlayList is set
to 1 so that the first time round the second file plays after the first one.

The playlist is selected as follows:

void audio_eof_mp3(const char *info)


{
static int PlayList = 1;
if(PlayList == 0)audio.connecttoFS(SD,"sample-15s.mp3");
if(PlayList == 1)audio.connecttoFS(SD,"sample-12s.mp3");
if(PlayList == 2)audio.connecttoFS(SD,"sample-9s.mp3");
if(PlayList == 3)audio.connecttoFS(SD,"sample-6s.mp3");
PlayList++;
if(PlayList == No_Of_Files)PlayList = 0;
}

/****************************************************************
* PLAY LIST OF MUSIC FILES STORED ON SD CARD
* ==========================================
*
* In this program a list of MP3 compatible music files are stored
* on microSD card.The program opens these files and plays them
* continuously one after the other one
*
* Author : Dogan Ibrahim
* Program: SDMusic2
* Date : April, 2023
**************************************************************/
#include "Arduino.h"
#include "Audio.h"
#include "SD.h"
#include "FS.h"

//
// microSD card to ESP32 connections

● 107

Practical Audio DSP Projects with the ESP32 - UK.indd 107 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

//
#define CARD_MOSI 23
#define CARD_MISO 19
#define CARD_SCK 18
#define CARD_CS 5

//
// Define MAX98357A amplifier connections
//
#define I2S_BCLK 4
#define I2S_LRC 21
#define I2S_DOUT 22

int No_Of_Files = 4;

Audio audio; // Audio object

void setup()
{
pinMode(CARD_CS, OUTPUT); // CS is output
digitalWrite(CARD_CS, HIGH); // CS HIGH
SPI.begin(CARD_SCK,CARD_MISO,CARD_MOSI); // Init SPI bus

Serial.begin(115200); // Serial Monitor


if(!SD.begin(CARD_CS)) // Start SD card
{
Serial.println("Error in microSD card"); // card error
while(true);
}
Serial.println("microSD card accessed correctly");

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); // Setup I2S


audio.setVolume(10); // Set volume
audio.connecttoFS(SD,"sample-15s.mp3"); // First music
}

//
// Program jumps here at the end of a music file
//
void audio_eof_mp3(const char *info)
{
static int PlayList = 1;
if(PlayList == 0)audio.connecttoFS(SD,"sample-15s.mp3");
if(PlayList == 1)audio.connecttoFS(SD,"sample-12s.mp3");
if(PlayList == 2)audio.connecttoFS(SD,"sample-9s.mp3");
if(PlayList == 3)audio.connecttoFS(SD,"sample-6s.mp3");

● 108

Practical Audio DSP Projects with the ESP32 - UK.indd 108 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

PlayList++;
if(PlayList == No_Of_Files)PlayList = 0;
}

void loop()
{
audio.loop();
}

Figure 6.20: Program: SDMusic2.

Useful information about the file played

The library provides a number of useful functions that can be used in your programs. Some
of these functions are listed here.

void audio_info(const char *info)

This function is called automatically when a music file is closed and a new one is opened. It
displays useful information about the file. The information is displayed on the Serial Monitor
which must already be opened. The function is called as follows:

void audio_info(const char *info)


{
Serial.println(info);
}

An example output from this call is shown in Figure 6.21.

Figure 6.21: Example info output.

● 109

Practical Audio DSP Projects with the ESP32 - UK.indd 109 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Some other useful functions that can be called are:

void audio_bitrate(const char *info) Display bitrate

void audio_id3data(const char *info) Display information about artists,


albums or bands

Further information on the audio library functions can be obtained from the following au-
dioI2S FAQ:

https://github.com/schreibfaul1/ESP32-audioI2S/wiki

6.9 Project 5: Internet radio


Description: In this project, you will log in to your local home W-Fi router and then access
an Internet radio station over the Internet. The output will be sent to a speaker through an
amplifier module as in the previous project.

The aim: The aim of this project is to show how you can access Internet radio stations with
your ESP32 DevKitC.

Block diagram: Figure 6.22 shows the block diagram of the project.

Figure 6.22: Block diagram of the project.

Circuit diagram: The circuit diagram, shown in Figure 6.23, is similar to Figure 6.17, but
there is no microSD card.

● 110

Practical Audio DSP Projects with the ESP32 - UK.indd 110 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.23: Circuit diagram of the project.

Program listing: Figure 6.24 shows the program listing (Program: IRadio). At the be-
ginning of the program, the library headers used are included in the program. Then the
local Wi-Fi name (ssid) and password (pwd) are specified. The program then defines the
connection between the MAX98357A amplifier module and ESP32 DevKitC. Connection to
the local Wi-Fi is then done. If the Serial Monitor is opened, then the message Wi-Fi is
connected… will be displayed after successful access of the Wi-Fi router. The program sets
the volume and connects to a radio station over the Internet. In this project, connection is
made to the classic music station Klassik1 which has the following web link:

http://tuner.classical102.com/listen.pls

Two event-driven library functions are defined in the program. Function audio_showsta-
tion() displays the station name. Function audio_showstreamtitle() displays the name
of the current stream playing (this changes automatically as the stream is changed). Figure
6.25 is a typical display on the Serial Monitor.

/****************************************************************
* INTERNET RADIO
* ==============
*
* This is an Internet radio project. This program accesses
* an Internet radio station and sends its audio to a speaker
* through the I2S compatible amplifier
*
* In this program connection is made to the following station:
*
* http://tuner.classical102.com/listen.pls
*
* which is station: Klassik1
*
* Author : Dogan Ibrahim

● 111

Practical Audio DSP Projects with the ESP32 - UK.indd 111 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

* Program: IRadio
* Date : April, 2023
**************************************************************/
#include "Arduino.h"
#include "Audio.h"
#include "WiFi.h"

//
// Local Wi-Fi details
//
String ssid = "BTHomeSpot-XNH";
String pwd = "4934675t";

//
// Define MAX98357A amplifier connections
//
#define I2S_BCLK 4
#define I2S_LRC 21
#define I2S_DOUT 22

Audio audio; // Audio object

void setup()
{
Serial.begin(115200); // Serial Monitor
WiFi.disconnect();
delay(500);
WiFi.mode(WIFI_STA);
Serial.println("Connecting to internet...");
WiFi.begin(ssid.c_str(), pwd.c_str());
while(WiFi.status() != WL_CONNECTED) delay(1000);
Serial.println("Wi-Fi is connected...");

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);


audio.setVolume(5);
audio.connecttohost("http://tuner.classical102.com/listen.pls");
}

//
// Display station information
//
void audio_showstation(const char *info)
{
Serial.print("Station: ");
Serial.println(info);
}

● 112

Practical Audio DSP Projects with the ESP32 - UK.indd 112 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

//
// Display stream title
//
void audio_showstreamtitle(const char *info)
{
Serial.print("Stream title: ");
Serial.println(info);
}

void loop()
{
audio.loop();
}

Figure 6.24: Program: Iradio.

Figure 6.25: Displaying the station name and stream title on Serial Monitor.

Table 6.1 below lists some of the UK-based Internet radio stations that you may find inter-
esting (this table is taken from the Garfnet website at: https://garfnet.org.uk/cms/tables/
radio-frequencies/internet-radio-player/

● 113

Practical Audio DSP Projects with the ESP32 - UK.indd 113 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Table 6.1: Some UK-based Internet radio stations.

6.10 Project 6: Text to speech (TTS)


Description: In this project, a text message entered in the program is played on the loud-
speaker. The program uses the ESP32 audio library, as in the previous project.

The aim: The aim of this project is to show how text can be made audible on the loud-
speaker.

The block diagram and circuit diagram of the project are as in Figure 6.22 and Figure 6.23,
respectively.

Program listing: Figure 6.26 shows the program listing (Program: TTS). The program is
essentially the same as Figure 6.24, but here the following line of code is added to speak
the message Testing the device in the English language. Note that other languages can
also be used. e.g., use de instead of en for German etc:

audio.connecttospeech("Testing the device", "en");

/****************************************************************
* TEXT TO SPEECH
* ==============
*
* This is an In Internet based text-to-speech (TTS) application.
* The text entered is spoken on teh speaker
*
* Author : Dogan Ibrahim

● 114

Practical Audio DSP Projects with the ESP32 - UK.indd 114 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

* Program: TTS
* Date : April, 2023
**************************************************************/
#include "Arduino.h"
#include "Audio.h"
#include "WiFi.h"

//
// Local Wi-Fi details
//
String ssid = "BTHomeSpot-XNH";
String pwd = "49356ytw";

//
// Define MAX98357A amplifier connections
//
#define I2S_BCLK 4
#define I2S_LRC 21
#define I2S_DOUT 22

Audio audio; // Audio object

void setup()
{
Serial.begin(115200); // Serial Monitor
WiFi.disconnect();
delay(500);
WiFi.mode(WIFI_STA);
Serial.println("Connecting to internet...");
WiFi.begin(ssid.c_str(), pwd.c_str());
while(WiFi.status() != WL_CONNECTED) delay(1000);
Serial.println("Wi-Fi is connected...");

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);


audio.setVolume(5);
audio.connecttospeech("Testing the device", "en");
}

void loop()
{
audio.loop();
}

Figure 6.26: Program: TTS.

● 115

Practical Audio DSP Projects with the ESP32 - UK.indd 115 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

6.11 Project 7: Play all songs on the SD card


Description: In this project, all the MP3-compatible music files on the microSD card are
played on the microphone one after the other one continuously. There is no need for the
user to hardcode the music file names into the program. The program reads all the file
names and then plays the songs automatically.

The aim: The aim of this project is to show how all the file names on the SD card can be
read and then how these files can be played.

The block diagram and circuit diagram of the project are in Figure 6.16 and Figure 6.17,
respectively.

Program listing: Figure 6.27 shows the program listing (Program: PLAYALL). This pro-
gram is similar to Figure 6.20. At the beginning of the program, the library header files of
the libraries used are included in the program. The connections between the microSD card
and ESP32, and between the amplifier and ESP32, are then defined. Function getFiles()
reads the names of all the files on the microSD card and stores them in character array au-
diofilenames. This array is currently set to 20 but it can be increased if required. Variable
No_Of_Files stores the number of files on the card.

Inside the setup() routine, the microSD card is accessed. An error message is displayed
if the card is not inserted into its adapter, or if the card is not formatted correctly. The
program then plays the first music file on the card. The index number of the file and its
title are displayed on the Serial Monitor if it has been opened. Function audio_eof_mp3()
is called automatically when playing the first song is completed. Inside this function, the
remaining music files are played one after the other one, starting from the second file. The
index numbers and titles of the files are displayed on the Serial Monitor as they are played.
This process continues forever until stopped by the user, where all the files from the first
one to the last one are played consecutively.

/****************************************************************
* PLAY ALL THE MUSIC FILES ON THE SD CARD
* =======================================
*
* In this program all the music files stored on the microSD
* card are played one after the other one contunuously. There
* is no need to hardcode the names of the files. They are read
* automatically by the program at the start
*
* Author : Dogan Ibrahim
* Program: PLAYALL
* Date : April, 2023
**************************************************************/
#include "Arduino.h"
#include "Audio.h"
#include "SD.h"

● 116

Practical Audio DSP Projects with the ESP32 - UK.indd 116 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

#include "FS.h"

//
// microSD card to ESP32 connections
//
#define CARD_MOSI 23
#define CARD_MISO 19
#define CARD_SCK 18
#define CARD_CS 5

//
// Define MAX98357A amplifier connections
//
#define I2S_BCLK 4
#define I2S_LRC 21
#define I2S_DOUT 22

String audiofilenames[20];
char * files;
int No_Of_Files = 0;

Audio audio; // Audio object

//
// Get the names of all the files on the card
//
void getFiles(File dir)
{
while(1)
{
File entry = dir.openNextFile();
if(!entry)break;
audiofilenames[No_Of_Files] = entry.name();
Serial.println(audiofilenames[No_Of_Files]);
No_Of_Files++;
entry.close();
}
}

//
// Setup routine. Access the card play the firsy file
//
void setup()
{
pinMode(CARD_CS, OUTPUT); // CS is output

● 117

Practical Audio DSP Projects with the ESP32 - UK.indd 117 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

digitalWrite(CARD_CS, HIGH); // CS HIGH


SPI.begin(CARD_SCK,CARD_MISO,CARD_MOSI); // Init SPI bus

Serial.begin(115200); // Serial Monitor


if(!SD.begin(CARD_CS)) // Start SD card
{
Serial.println("Error in microSD card"); // card error
while(true);
}
Serial.println("microSD card accessed correctly");

//
// Get all file names stored on the card
//
File root = SD.open("/MyMusic");
getFiles(root);
root.close();
delay(1000);
SD.begin(CARD_CS);

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); // Setup I2S


audio.setVolume(10); // Set volume
Serial.print("Next playing: 0");
Serial.print(" Title: ");
Serial.println(audiofilenames[0]);
const char* f=audiofilenames[0].c_str();
audio.connecttoFS(SD, f); // Play first file
}

//
// Program jumps here at the end of a music file
//
void audio_eof_mp3(const char *info)
{
static int PlayList = 1; // Second file
Serial.print("Next playing: "); // Display
Serial.print(PlayList); // Play index
Serial.print(" Title: "); // Display title
Serial.println(audiofilenames[PlayList]);
const char* f=audiofilenames[PlayList].c_str();
audio.connecttoFS(SD, f); // Play a file
PlayList++;
if(PlayList == No_Of_Files)PlayList = 0; // Back to first file
}

void loop()

● 118

Practical Audio DSP Projects with the ESP32 - UK.indd 118 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

{
audio.loop();
}

Figure 6.27: Program: PLAYALL.

Figure 6.28 shows the data displayed on the Serial Monitor as the music files are played.
Notice that in this example project, there were 5 files in directory /MyMusic of the mi-
croSD card with the following names:

sample-12s.mp3
sample-15s.mp3
sample-143172.mp3
sample-6s.mp3
sample-9s.mp3

Figure 6.28: Data displayed on the Serial Monitor.

Note: All the music files must have extension names .mp3 and they must all be saved in
directory /MyMusic of the microSD card.

6.12 Project 8: Play all songs on the SD card — using an external


volume control
Description: There are applications where you may want to change the signal volume on
the speaker using external control. In this project, an external potentiometer is used as a
volume control.

The aim: The aim of this project is to show how a potentiometer can be used as a volume
control by connecting it to the amplifier module.

● 119

Practical Audio DSP Projects with the ESP32 - UK.indd 119 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Circuit diagram: The circuit diagram is shown in Figure 6.29. There are several methods
that can be used to change the volume of the output signal. Perhaps the easiest method
is to connect a 100-kohm potentiometer between the SD pin and the VIN pin. As was de-
scribed earlier in this chapter, connecting SD to a voltage has the following results:

• Connect SD to GND (less than 0.16 V) to shut down the amplifier.

• Connect SD to a voltage between 0.16 V and 0.77 V for stereo average output.
i.e., (Right + Left) / 2.

• Connect SD between 0.77 V and 1.4 V for the Right channel only.

• Connect SD to higher than 1.4 V for the Left channel only.

By default, the SD pin is pulled down internally with a 100 k-ohm resistor and the voltage
at the SD pin is between 0.16 V and 0.77 V so that the output is a mixture of left and right
channels. An external resistor can be used to change the voltage at the SD pin so that the
volume of the amplifier can be changed. By varying the potentiometer arm, you can change
the voltage at the SD pin and hence control the volume of the amplifier.

Figure 6.29: Circuit diagram of the project.

Program listing: The program listing is same as the one in Figure 6.27 (Program: PLAY-
ALL). You may have to experiment with setting the volume in software before using the
external potentiometer-based volume control.

6.13 Project 9: Internet radio in stereo


Description: Many people prefer to listen to music in stereo. In this project, you will be
using two MAX98357A type I2S-compatible amplifier modules in parallel. A speaker is con-
nected to each amplifier module for stereo output.

The aim: The aim of this project is to show how two identical MAX98357A amplifier mod-
ules can be connected in parallel for stereo output.

● 120

Practical Audio DSP Projects with the ESP32 - UK.indd 120 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Block diagram: Figure 6.30 shows the block diagram of the project.

Figure 6.30: Block diagram of the project.

Circuit diagram: The circuit diagram is shown in Figure 6.31. Essentially, the circuit di-
agram is very similar to Figure 6.23, but here two amplifier modules are used in parallel
with two speakers.

Figure 6.31: Circuit diagram of the project.

Program listing: The program listing is exactly the same as in Figure 6.24 (Program:
IRadio).

Figure 6.32 shows the project built on a breadboard (the SD card is not used in this pro-
ject).

● 121

Practical Audio DSP Projects with the ESP32 - UK.indd 121 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 6.32: Project built on a breadboard.

6.14 Project 10: Internet radio in stereo with volume control


Description: This project is the same as the previous one, but here additionally a volume
control potentiometer is connected to the circuit.

The aim: The aim of this project is to show how a potentiometer can be connected to con-
trol the left and right channel volumes.

Circuit diagram: Figure 6.33 shows the circuit diagram of the project. A 100 k-ohm po-
tentiometer is connected from the SD pin to the VIN pin. The potentiometer controls the
left and right channel volumes.

Figure 6.33: Circuit diagram of the project.

Program listing: The program listing is exactly the same as in Figure 6.24 (Program:
IRadio). You should experiment with different software and hardware volume settings.

● 122

Practical Audio DSP Projects with the ESP32 - UK.indd 122 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

6.15 Project 11: Playing an MP3 file stored in the flash memory
Description: In this project, an MP3 music file is stored in the flash memory of the ESP32
processor. This project shows how the file can be stored and then played on the loudspeak-
er through an amplifier.

The aim: The aim of this project is to show how a file can be stored in the flash memory
of the ESP32 and then how it can be played.

Block diagram: Figure 6.34 shows the block diagram of the project.

Figure 6.34: Block diagram of the project.

Circuit diagram: The circuit diagram, shown in Figure 6.35, consists of the ESP32 DevKitC
development board, the MAX98357A amplifier and a speaker.

Figure 6.35: Circuit diagram of the project.

The SPIFFS: This stands for Serial Peripheral Interface Flash File System. The ESP32 con-
tains a file system where a file can be stored in the flash memory of the processor. SPIFFS
allows part of the flash memory to be used as if it is a normal file system, where files can
be written to, read from, or deleted. This file system, however, does not support any direc-
tory structure, i.e., it is a flat structure (this was the case at the time of writing this book).

● 123

Practical Audio DSP Projects with the ESP32 - UK.indd 123 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

This actually means that if you create a file called /dir/myfile.txt, a file with the name /
dir/myfile.txt will be created, not a file called myfile.txt in folder dir. You can think of
the SPIFFS as a small SD card internal to ESP32. By default, the size of this file system is
several MB.

Arduino IDE supports a plugin where with the help of this you can upload files directly to
the ESP32 file system from a folder on your PC. This way for example, you copy your MP3
music file to a folder on your PC, and then copy this file to the file system on your ESP32.
This makes it very easy to manipulate files in the ESP32 file system.

The steps to install this plugin are as follows (note that at the time of writing this book,
version 2 of the Arduino IDE did not support this plugin):

• Go to the following website and download the zip file: ESP32FS-1.0.zip to a


folder on your PC:

https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/

• Start your Arduino IDE and locate your Sketchbook location (if you are not
sure, go to File  Preferences). If you have a default IDE installation, it
should be located at: C:\Users\Username\Documents\Arduino. See
Figure 6.36 for the author's location:

Figure 6.36: Sketchbook location.

• Go to your Sketchbook location, and then create a folder under this location
called: tools.

• Unzip the downloaded .zip folder and copy the ESP32FS folder to the tools
folder that you just created (Figure 6.37).

● 124

Practical Audio DSP Projects with the ESP32 - UK.indd 124 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.37: Folder ESP32FS inside tools.

• To check that the plugin has been installed correctly, restart your Arduino IDE.
Make sure that the option: ESP32 Sketch Data Upload exists under IDE
option Tools (Figure 6.38).

Figure 6.38: Checking that the plugin is installed correctly.

• To check the ESP32 processor memory partition with the allocated SPIFFS,
choose the options: Tools  Partition scheme, as shown in Figure 6.39.

Figure 6.39: ESP32 memory partition.

● 125

Practical Audio DSP Projects with the ESP32 - UK.indd 125 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Copying a music MP3 file to flash memory


You will be using one of the MP3 music files you have used earlier with the name: sam-
ple-12s.mp3. This file occupies about 200 KB. The steps to copy this file to the flash
memory are as follows:

• Create an empty IDE file with a name, for example, MyMP3 and save it.

• Locate where your Sketch folder is saved. Click Sketch  Show Sketch
Folder. This is where your Sketch folder is (see Figure 6.40).

Figure 6.40: Location of sketch folder.

• Create a folder called: data inside your sketch folder. You should have the
following folder structure:

MyMp3/data

• Copy your MP3 music file to the folder data. The folder structure should now
be:

MyMP3/data/sample-12s.mp3

• You are now ready to upload your music file to ESP32. Connect your ESP32
DevKitC development board to your PC.

• On your IDE, click: Tools  ESP32 Sketch Data Upload.

• Wait until the file is uploaded. The message SPIFFS Image Uploaded will be
displayed on your IDE (Figure 6.41).

● 126

Practical Audio DSP Projects with the ESP32 - UK.indd 126 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Figure 6.41: Successful uploading of the MP3 file.

Now that you have uploaded your MP3 music file to the flash memory of the ESP32 proces-
sor, you are ready to write the program to play this music file.

Program listing: The program listing is shown in Figure 6.42 (Program: MyMP3). At
the beginning of the program, header files Arduino, Audio, and SPIFFS are included in the
program. The connections between the MAX98357A amplifier and the ESP32 are defined.
Inside the setup routine, the Serial Monitor is initialized to 115200 baud. SPIFFS is then
accessed. The message Error in SPIFFS is displayed on the Serial Monitor if there is an
error, otherwise, the message SPIFFS accessed correctly is displayed. The remainder
of the program configures the I2S bus, sets the amplifier volume to 10, and then plays the
music file.

/******************************************************************
* PLAY MUSIC STORED IN FLASH MEMORY
* =================================
*
* In this program an MP3 compatible music file is stored in the
* flah memory of the ESP32 processor.The program opens the file
* and plays the music on the speaker through the MAX98357A amplifier
*
* Author : Dogan Ibrahim
* Program: MyMP3
* Date : April, 2023
*******************************************************************/
#include "Arduino.h"
#include "Audio.h"
#include "SPIFFS.h"

//
// Define MAX98357A amplifier connections
//
#define I2S_BCLK 4
#define I2S_LRC 21
#define I2S_DOUT 22

Audio audio; // Audio object

void setup()

● 127

Practical Audio DSP Projects with the ESP32 - UK.indd 127 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

{
Serial.begin(115200); // Serial Monitor
if(!SPIFFS.begin(true)) // Start SPIFFS
{
Serial.println("Error in SPIFFS"); // SPIFFS error
while(true);
}
Serial.println("SPIFFS accessed correctly");

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); // Setup I2S


audio.setVolume(10); // Set volume
audio.connecttoFS(SPIFFS,"sample-12s.mp3"); // Open file
}

void loop()
{
audio.loop();
}

Figure 6.42: Program: MyMP3.

6.16 Project 12: List of files stored in the flash memory


Description: In this project, the list of files in the flash memory of the ESP32 processor
are listed.

The aim: The aim of this project is to show how the files in the flash memory of the ESP32
processor can be listed.

Program listing: Figure 6.43 shows the program listing (Program: SPIFFSfiles). The
program opens the SPIFFS file structure and then lists the files on the Serial Monitor. Figure
6.44 shows an example output displayed on the Serial Monitor. Compile and upload the
program to the ESP32. Open the Serial Monitor making sure that the baud rate is set to
115200. Press the Reset button on the development board.

/****************************************************************
* LIST OF FILES IN FLASH MEMORY
* =============================
*
* This program lists the files in the flash memory of ESP32
*
* Author : Dogan Ibrahim
* Program: SPIFFSfiles
* Date : April, 2023
**************************************************************/
#include "SPIFFS.h"

● 128

Practical Audio DSP Projects with the ESP32 - UK.indd 128 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

void setup()
{
Serial.begin(115200);
Serial.println("");
if (!SPIFFS.begin(true))
{
Serial.println("Error in SPIFFS");
while(1);
}
else
{
Serial.println("SPIFSF accessed correctly");
Serial.println("");
}

File root = SPIFFS.open("/");


File file = root.openNextFile();

while(file)
{
Serial.print("FILE name: ");
Serial.println(file.name());
file = root.openNextFile();
}
}

void loop()
{}

Figure 6.43: Program: SPIFFSfiles.

Figure 6.44: Display on the Serial Monitor.

● 129

Practical Audio DSP Projects with the ESP32 - UK.indd 129 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

6.17 Project 13: Speaking event counter


Description: This is an even counter project with sound output. Every time an external
event occurs, a counter is incremented, and the total count so far is displayed on the Serial
Monitor. At the same time, the audio library is used to sound the total number through a
speaker connected to the development board through an amplifier. External events are
simulated by pressing a button. Normally, the output of the button is at logic 1 and goes to
0 when the button is pressed.

The aim: the aim of this project is to show how a speaking event counter can be devel-
oped.

Block diagram: Figure 6.45 shows the block diagram of the project.

Figure 6.45: Block diagram of the project.

Circuit diagram: The circuit diagram is shown in Figure 6.46. A button is connected to
port pin GPIO36 (pin 3) such that normally the input is at logic 1 and goes to logic 0 when
the button is pressed.

Figure 6.46: Circuit diagram of the project.

● 130

Practical Audio DSP Projects with the ESP32 - UK.indd 130 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

Program listing: Figure 6.47 shows the program listing (Program: EventSpeak). This
program uses the text-to-speech of the audio library and therefore the ESP32 is connected
to the local Wi-Fi router so that the Google TTS engine can be used by the audio library.
At the beginning of the program, the Wi-Fi name and password are defined and the con-
nections between the amplifier and ESP32 are defined. GPIO15 (pin 23) is defined to be
the button and is configured as an INPUT with its internal pull-up resistor enabled. As a
result, GPIO15 is at logic 1 unless the button is pressed. Inside the setup() routine, the
connection is made to Wi-Fi and the I2S bus is configured. The volume is set to 10 and the
message This is an event counter project is spoken on the speaker.

The remainder of the program runs inside the loop(). Here, the state of the button is
checked. If the button is pressed (Event_Button is at logic 0) then variable Count is in-
cremented by one and its final value is displayed on the Serial Monitor. At the same time,
the TTS engine is called and the final count is spoken on the speaker. Therefore, the user
should hear the sounds like ONE, TWO, THREE, etc. being spoken on the speaker as ex-
ternal events occur. A 30-ms delay is inserted inside the loop to disable contact bouncing
problems. The program runs forever until stopped by the user.

/****************************************************************
* SPEAKING EVENT COUNTER
* ======================
*
* This is a speaking event counter project.Events on port pin
* GPIO36 are counter and displayed dynamically on the Serial
* Monitor. At the same time the total is spoken on the speaker
*
* Author : Dogan Ibrahim
* Program: EventSpeak
* Date : April, 2023
**************************************************************/
#include "Arduino.h"
#include "Audio.h"
#include "WiFi.h"

//
// Local Wi-Fi details
//
String ssid = "TP-Link_6138";
String pwd = "2484r45";

//
// Define MAX98357A amplifier connections
//
#define I2S_BCLK 4
#define I2S_LRC 21

● 131

Practical Audio DSP Projects with the ESP32 - UK.indd 131 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

#define I2S_DOUT 22

#define Event_Button 15 // Event button


int Count = 0;
String Events;

Audio audio; // Audio object

//
// Set the Serial Monitor, connect to Wi-Fi, Configure I2S
// Set the amplifier volume
//
void setup()
{
Serial.begin(115200);
pinMode(Event_Button, INPUT_PULLUP);
WiFi.disconnect();
delay(500);
WiFi.mode(WIFI_STA);
Serial.println("Connecting to internet...");
WiFi.begin(ssid.c_str(), pwd.c_str());
while(WiFi.status() != WL_CONNECTED) delay(1000);
Serial.println("Wi-Fi is connected...");

audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);


audio.setVolume(10);
audio.connecttospeech("This is an event counter project","en");
}

//
// Here, the total count is displayed on Serial Monitor
// At the same time final count is spoken on the speaker
//
void loop()
{
audio.loop();
if(digitalRead(Event_Button) == 0)
{
Count++; // Increment Count
Serial.print("Count = "); // Heading
Serial.println(Count); // Display Count
Events = Count;
const char * f = Events.c_str();
audio.connecttospeech(f, "en"); // Speak Count
delay(30);

● 132

Practical Audio DSP Projects with the ESP32 - UK.indd 132 06-07-2023 10:40
Chapter 6 • Audio DSP Projects

}
}

Figure 6.47: Program: EventSpeak.

Figure 6.48 shows a snapshot of the Serial Monitor.

Figure 6.48: Serial Monitor display.

Suggestions for further work: This project can be modified such that a temperature
sensor can be connected to the development board and the temperature (or the maximum
or minimum temperature, or when an alarm temperature value is reached) can be spoken
to the speaker.

● 133

Practical Audio DSP Projects with the ESP32 - UK.indd 133 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 7 • Discrete-Time Signals

7.1 Overview
Discrete-tme signals are usually obtained from analog signals by converting the signal from
analog into digital form using analog-to-digital converters (ADCs). This is also known as
the sampling process. The converted signal is then processed using a digital processor like
a microcontroller. The processed signal is usually converted back into analog form using a
digital-to-analog converter (DAC).

Digital signals are also known as discrete-time signals. Before going into the details of
digital signal processing theory, it is worthwhile to review the properties of discrete-time
signals, also called digital signals.

7.2 The sampling process


Figure 7.1 shows the ideal sampling process in its simplest form. Here, a switch opens
at equally-spaced intervals to create the samples. In the ideal case, you assume impulse
sampling where the contact time is assumed to be very small.

Figure 7.1: Ideal sampling process.

One of the important questions in sampling is: what should be the switching rate? In other
words, how often should the analog signal be sampled? Conceivably the simplest answer to
this question is that the sampling rate should be as fast as possible. However, unnecessarily
fast sampling rate requires many more samples to be stored, processed, or transmitted.
On the other hand, the original signal cannot be constructed if a low sampling rate is used.
Can you choose a sampling rate that is just adequate for the signal to be sampled without
loss of any information in the signal and without being too fast?

The famous sampling theorem by Shannon states that:

An analog signal containing components up to some maximum frequency f Hz may be


completely represented by regularly-spaced samples, provided the sampling rate is at least
2f samples per second.

Thus, for example, a speech waveform having a frequency of 1 kHz should be sampled at
least 2 kHz, or 2,000 times per second. In general, if the frequency of the analog signal is
f, then the maximum sampling interval should be:

● 134

Practical Audio DSP Projects with the ESP32 - UK.indd 134 06-07-2023 10:40
Chapter 7 • Discrete-Time Signals

T = ½f

In practice, you choose a somewhat higher sampling frequency than given by Shannon's
theorem. For example, a signal having f = 1kHz is usually sampled at 5 kHz or even higher.

7.3 Some digital signal types


The characteristics of some of the useful digital signals are given in this section.

7.3.1 Unit step function


The discrete-time unit step function H[n] is defined by

The unit step sequence is shown in Figure 6.2.

Figure 7.2: Unit step sequence.

7.3.2 Sinusoidal signal


The discrete-time sinusoidal function is defined by

where A is the amplitude and T is the period of the signal.

Figure 7.3 shows a typical discrete-time sinusoidal signal. This figure has been obtained
using the following MATLAB statements:

n = 0:20;
y = sin(2*pi*n/20);
stem(n, y, 'k', 'fill')

● 135

Practical Audio DSP Projects with the ESP32 - UK.indd 135 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 7.3: Discrete sinusoidal signal.

Notice that you can also use the cosine version of the sinusoid, defined by

Figure 7.4 shows a typical discrete-time sinusoidal cosine signal.

Figure 7.4: Cosine version of the sinusoidal signal.

7.3.3 Exponential signal


The basic discrete exponential signal is defined by

The first 6 sequences of an example discrete exponential signal with a = 0.2 is shown in
Figure 7.5. This figure has been obtained using the following MATLAB statements:

n = 0:6;
y = exp(0.2*n);
stem(n, y, 'k', 'fill')

● 136

Practical Audio DSP Projects with the ESP32 - UK.indd 136 06-07-2023 10:40
Chapter 7 • Discrete-Time Signals

Figure 7.5: Basic discrete exponential signal.

7.3.4 Exponential sinusoidal decay signal


The discrete exponential sinusoidal decay signal is defined by

An example is shown in Figure 7.6 with A = 1, a = 0.1, and n = 30. This figure has been
obtained using the following MATLAB statements:

n = 0:30;
y = exp(-0.1*n). *sin(2*pi*n/30);
stem(n, y, 'k', 'fill')

Figure 7.6: Example of sinusoidal decay signal.

7.4 Block diagram representation


Operations on discrete-time sequences can be represented by using block diagrams as
shown in Figure 7.7. Block diagrams can be useful when discrete-time sequences are used
in systems with discrete-time inputs and outputs.

● 137

Practical Audio DSP Projects with the ESP32 - UK.indd 137 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 7.7: Block diagram representation of discrete-time sequences.

7.4.1 Block diagram manipulation


Block diagram manipulation is useful for deriving the equations at various parts of the sys-
tem. An example is given below.

Example 7.1
The block diagram of a discrete-time system is shown in Figure 7.8. Derive the output
equation y[n].

Figure 7.8: Block diagram of a discrete-time system.

Solution 7.1
Figure 7.9 shows the signals at different parts of the block diagram. The output signal is
given by:

For the left-hand side of the diagram you can write

b0x[n] + b1x[n-1] + b2x[n-2]

Similarly, for the right-hand side you can write

a1y[n-1] + a2y[n-2]

Adding the two equations, you find the output y[n] as

y[n] = b0x[n] + b1x[n-1] + b2x[n-2] + a1y[n-1] + a2y[n-2]

● 138

Practical Audio DSP Projects with the ESP32 - UK.indd 138 06-07-2023 10:40
Chapter 7 • Discrete-Time Signals

Figure 7.9: Signals at different parts of the diagram.

7.5 The convolution process


The convolution is the process used to express the input-output relationship of a system.
The convolution is used to express the output y[n] of a discrete-time system in terms of its
input x[n] and impulse response h[n].

In general, the output sequence y[n] is found by the convolution process using the follow-
ing equation:

The convolution of x[n] and h[n] is usually represented as

y[n] = x[n] * h[n]

An example is given below.

Example 7.2
The impulse response of a linear time-invariant system is shown in Figure 7.10. Calculate
the output response when the input sequence shown in Figure 7.11 is applied to the sys-
tem.

Figure 7.10: Impulse response of the system.

● 139

Practical Audio DSP Projects with the ESP32 - UK.indd 139 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 7.11: The input sequence.

Solution 7.2
The impulse response sequence is:

h[n] = [1, -2, 3, -1, 2]

and the input sequence is:

x[n] = [-2, 2, 1, 0, 3]

Using equation (7.1), with 5 samples, the output sequence is given by:

Thus,

y[0] = x[0].h[0]
y[1] = x[0].h[1] + x[1].h[0]
y[2] = x[0].h[2] + x[1].h[1] + x[2].h[0]
y[3] = x[0].h[3] + x[1].h[2] + x[2].h[1] + x[3].h[0]
y[4] = x[0].h[4] + x[1].h[3] + x[2].h[2] + x[3].h[1] + x[4].h[0]

or,

y[0] = -2 x 1 = -2
y[1] = -2 x (-2) + 2 x 1 = 6
y[2] = -2 x 3 + 2 x (-2) + 1 x 1 = -9
y[3] = -2 x (-1) + 2 x 3 + 1 x (-2) + 0 x 1 = 6
y[4] = -2 x 2 + 2 x (-1) + 1 x 3 + 0 x (-2) + 3 x 1= 0

alternatively, the output sequence is given by (see Figure 7.12):

y[n] = [-2, 6, -9, 6, 0]

● 140

Practical Audio DSP Projects with the ESP32 - UK.indd 140 06-07-2023 10:40
Chapter 7 • Discrete-Time Signals

Figure 7.12: The output response.

MATLAB function conv can be used to perform the convolution operation. The required
statements for the above example are given below:

h = [1 -2 3 -1 2];
x = [-2 2 1 0 3];
y = conv(h, x)

y=
-2 6 -9 6 0 -3 11 -3 6

The following MATLAB program can be used to calculate and plot the output sequence using
convolution:

%
% Convolution program
%
h = input('Enter the impulse response sequence: ' );
x = input('Enter the input sequence: ');
y = conv(h, x);
L = length(y) ;
n = 0:1:L-1;
disp('Output sequence = ');
disp(y);
stem(n, y, 'k', 'fill');
xlabel('Time');
ylabel('Amplitude');

● 141

Practical Audio DSP Projects with the ESP32 - UK.indd 141 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

An example run is given below:

Enter the impulse response sequence: [1 -2 3 -1 2]


Enter the input sequence: [-2 2 1 0 3]
Output sequence =
-2 6 -9 6 0 -3 11 -3 6

The output sequence generated by the program is shown in Figure 7.13.

Figure 7.13: The output sequence.

● 142

Practical Audio DSP Projects with the ESP32 - UK.indd 142 06-07-2023 10:40
Chapter 8 • The Z-Transform

Chapter 8 • The Z-Transform

8.1 Overview
The z-transform is an extremely useful tool for the analysis and design of digital signals
and processors. This tool is widely used by DSP designers for describing digital signals and
systems. In this chapter, you get to explore the basic properties of the z-transform and see
how it can be exploited in DSP applications.

The z-transform X(z) of a digital signal x[n] is defined as:

(8.1)

The z-transform of a signal consists of an infinite series in the complex variable z-1 with
coefficients. The z-transform is used in digital systems just as the Laplace transform is used
in continuous-time systems. The response of a digital, system can be determined easily by
finding the z-transform of the output and then calculating the inverse z-transform, just like
the Laplace transform techniques used in continuous-time systems. You will now look at
how you can find the z-transforms of some commonly used discrete-time functions. Tables
of z-transforms for most of the commonly used functions are available on the Internet for
interested readers.

8.2 Unit step function


Consider a unit step function as shown in Figure 8.1, defined as

From (7.1),

or,

Figure 8.1: Unit step function.

● 143

Practical Audio DSP Projects with the ESP32 - UK.indd 143 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

8.3 Unit ramp function


Consider a unit ramp function as shown in Figure 8.2, defined by

From (7.1),

or,

Figure 8.2: Unit step function.

You can use the MATLAB function ztrans to find the z-transform as shown below for the unit
ramp function:

syms t
x = t;
ztrans(x)
ans =

z/(z - 1)^2

8.4 Sine function


Consider the sine function, defined as

● 144

Practical Audio DSP Projects with the ESP32 - UK.indd 144 06-07-2023 10:40
Chapter 8 • The Z-Transform

recall that,

So that

But you already know that the z-transform of an exponential function is

Therefore, substituting,

or,

Using MATLAB,

syms a
syms t
x=sin(a*t);
ztrans(x)

ans =

(z*sin(a))/(z^2 - 2*cos(a)*z + 1)

8.5 Discrete impulse function


Consider the sine function, defined as

From the definition of the z-transform,

● 145

Practical Audio DSP Projects with the ESP32 - UK.indd 145 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

8.6 The z-Transform of a function expressed as a Laplace Transform


The z-transform of a function expressed as a Laplace transform can be found by using one
of the following methods:

• Given G(s), calculate the time response g(t) by finding the inverse Laplace
transform of G(s). Then, find the z-transform either from the first principles, or
by looking at the z-transform tables.

• Gives G(s), find the z-transform G(z) by looking at the tables which give the
Laplace transforms and their equivalent z-transforms.

• Given the Laplace transform G(s), express it in the form G(s) = N(s) / D(s) and
then use the following formula to find the z-transform G(z):

Where and the xn , n = 1,2,….p, are the roots of the equation D(s) = 0.

An example is given below.

Example 8.1
Let

Determine G(z) by the first method described above.

Solution 8.1
You can express G(s) as a sum of its partial fractions:

The inverse Laplace transform is,

From the definition of the z-transforms, you can write

or,

● 146

Practical Audio DSP Projects with the ESP32 - UK.indd 146 06-07-2023 10:40
Chapter 8 • The Z-Transform

or,

8.7 Inverse z-transforms


The z-transforms are the ratios of polynomials in the complex variable z, with the numera-
tor polynomial being of order higher than the denominator. By finding the inverse z-trans-
form you find the sequence associated with the given z-transform polynomial. Thus, you
use an inverse transform to obtain y(t) from Y[z]. There are several methods to find the
inverse z-transform of a given function:
• Power series (long division);
• Expanding Y[z] into partial fractions and using z-transform tables to find the
inverse transforms;
• Obtaining the inverse z-transform using an inversion integral;
• Using a program such as MATLAB

Some examples are given in this section.

Example 8.2
Find the inverse z-transform of the following polynomial using the long division method

Solution 8.2
Dividing the denominator into the numerator gives

● 147

Practical Audio DSP Projects with the ESP32 - UK.indd 147 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The coefficients of the power series are:

y[0] = 1
y[1] = 4
y[2] = 8
y[3] = 8
………..
………..

The required time sequence is:

Figure 8.3 shows the first few samples of the time sequence y(t)

Figure 8.3: First few samples of y(t).

Example 8.3
Repeat Example 8.2 using MATLAB to find the time sequence

Solution 8.3
The required MATLAB statements are given below. Notice that the numerator and denom-
inator polynomials are entered. Then the required length is entered and MATLAB function
impz calculates and returns the power series coefficients (impulse response) in x and the
time sequence in n:

num = [1 1 0];
den = [1 -3 4];
L = 5;
[x,n] = impz(num, den, L)

x=

1
4
8
8

● 148

Practical Audio DSP Projects with the ESP32 - UK.indd 148 06-07-2023 10:40
Chapter 8 • The Z-Transform

-8

n=

0
1
2
3
4

The following MATLAB program can be used to find the power series coefficients of any
polynomial in z-transform and then plot the time response:

%
% Inverse z-transform program
%
num = input('Enter the numerator coefficients: ' );
den = input('Enter the denominator coefficients: ');
L = input('Enter the required length: ');
[y, n] = impz(num, den, L)
n = 0:1:L-1;
stem(n, y, 'k', 'fill');
xlabel('Time');
ylabel('y(t)');

An example run is given below:

Enter the numerator coefficients: [1 1]


Enter the denominator coefficients: [1 -3 4]
Enter the required length: 5

y=

1
4
8
8
-8

n=

0
1
2

● 149

Practical Audio DSP Projects with the ESP32 - UK.indd 149 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

3
4

Figure 8.4 shows the time response plotted by MATLAB.

Figure 8.4: The time response.

Example 8.4
Find the inverse z-transform of the following function using partial fractions:

Solution 8.4
The above expression can be written as:

The values of A and B can be found by equating like powers in the numerator, i.e.

You find, A = -1, B = 1, giving

or

From the z-transform tables, you find that

y[n] = -1 + 2n

and the coefficients of the power series are:

y(0) = 0
y(1) = 1

● 150

Practical Audio DSP Projects with the ESP32 - UK.indd 150 06-07-2023 10:40
Chapter 8 • The Z-Transform

y(2) = 3
y(3) = 7
y(4) = 15
……….
……….

so that the required time sequence is

8.7.1 Coefficients of partial fraction expansion


Case 1: Distinct real roots

The coefficients of the partial expansion can easily be found by considering the general
z-transform of the form:

The partial fraction expansion can be written as

And the coefficients Ai can easily be found as

Example 8.5
Using the partial expansion method described above, find the inverse z-transform of

Solution 8.5
Rewriting the function as

you find that

● 151

Practical Audio DSP Projects with the ESP32 - UK.indd 151 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Thus,
z z
Y [ z] = +
z −1 z − 2
And the inverse z-transform is obtained from the tables as

Case 2: Multiple order roots

When Y[z] has multiple order roots of the form

Then the partial fraction expansion can be written as

and the coefficients can easily be found from

An example is given below to illustrate the process.

Example 8.6
Find the inverse z-transform of

Solution 8.6
Rewriting the equation as

you obtain

● 152

Practical Audio DSP Projects with the ESP32 - UK.indd 152 06-07-2023 10:40
Chapter 8 • The Z-Transform

you can thus write,

The inverse transform is found from the tables as

● 153

Practical Audio DSP Projects with the ESP32 - UK.indd 153 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 9 • Digital Filters

9.1 Overview
Filtering is the process where the frequency components comprised in a signal are altered.
Filters are the basic components of signal processing and telecommunication systems. In
general, the primary functions of a filter are one or more of the following:
• to modify the frequency spectrum of a signal;
• to confine a signal into a prescribed frequency band, for example, low-pass,
high-pass, or band-pass filters as in removing noise from the signal;
• to decompose a signal into two or more frequency bands.

Filters are used in many signal-processing applications, such as audio processing, video
processing, radio receivers and transmitters, radar, and biomedical signal processing.
Traditionally, all types of filters have been analog before the low-cost and wide availability
of digital processors. An analog filter handles analog signals (or continuous signals), while
digital filters perform mathematical operations on sampled, discrete-time signals. In the
early days, analog filters have been passive and designed using passive components such
as resistors, capacitors, and inductors. One of the major problems with analog filters was
that it was difficult to design filters with accurate frequency responses. In addition, the
analog filters were bulky, especially those designed for low-frequency operation. With the
invention and wide availability of the operational amplifiers, most general-purpose analog
filters are nowadays designed using these components. The design using operational am-
plifiers is based on using passive components of only resistors and capacitors. Although the
frequency responses of these filters can be selected more accurately than the all passive
filters, the problem is that such filters are designed to work at medium to high frequencies.

Digital filters are designed using digital processors, such as microcontrollers. These filters
offer many advantages compared to the analog filters: The frequency response of digital
filters can be controlled to great accuracy. For example, the cut-off frequency can be se-
lected with very high precision. Digital filters are especially useful at low frequencies where
the analog ones are bulky. Because the digital filters are based on filter programs, it is very
easy to change the frequency response of a filter, all that is required is to modify the pro-
gram. Digital filters can outperform analog filters usually in terms of phase responses. Dig-
ital filters have some disadvantages compared to analog filters. Perhaps the biggest disad-
vantage is that they can be more expensive than analog filters in low-volume applications.

The types of digital filters that you will be designing in this book are linear filters. Like linear
systems, linear filters are characterized by their impulse responses. In general, an impulse
response can be of finite or an infinite length. Two types of digital filters are commonly
used: Finite Impulse Response (FIR) digital filters and Infinite Impulse Response
(IIR) digital filters. Both types have some advantages and disadvantages that should be
carefully considered when designing a filter. Besides, it is necessary to consider all funda-
mental characteristics of a signal to be filtered as these are very important when deciding
which filter to use. In most cases, it is only one characteristic that really matters, and it is
whether it is necessary that the filter has linear phase characteristics or not. The FIR filters
are also known as non-recursive filters, and IIR filters are as recursive filters. A Finite

● 154

Practical Audio DSP Projects with the ESP32 - UK.indd 154 06-07-2023 10:40
Chapter 9 • Digital Filters

Impulse Response filter (FIR) has its impulse coefficients extending over a finite time
interval and are zero beyond that. Thus, for example, an Nth-order FIR filter has an impulse
response with (N + 1) coefficients. The basic characteristics of FIR digital filters are:
• Linear phase characteristic
• High-filter order (more complex circuits)
• Stability

In Infinite Impulse Response (IIR) type filters the impulse response has an infinite du-
ration. In reality, you do not compute an infinite number of terms for the implementation
of IIR filters. In these filters, the input-output samples of the filter are related by linear
difference equations, and the filter is designed using these equations. The basic character-
istics of IIR digital filters are:
• Non-linear phase characteristic
• Low-filter order (easier circuits)
• Potential of becoming unstable

One of the drawbacks of FIR filters is the high-order of the designed filter. The order of the
FIR filter is remarkably higher compared to an IIR filter with the same frequency response.
This is the reason why it is so important to use FIR filters only when the linear phase char-
acteristic is very important. In this chapter, you will be learning the basic theory of both
FIR- and IIR-type digital filters.

9.2 FIR Filters and IIR Filters


Before going into the design of digital filters, it is worthwhile to compare the advantages
and disadvantages of both the FIR and IIR type filters, and this is given below:

• FIR filters are used where linear phase characteristics are required. This is a
desirable property in many signal-processing applications, such as in audio
and video processing. IIR filters, on the other hand, can be used where linear
characteristics are not of concern.

• FIR filters require many tappings for high order and, consequently, they require
more memory. The same filter can be designed with IIR filters using a small
filter order with much less memory.

• FIR filters are more stable than the IIR filters as feedback is not involved.

• IIR filters can simulate analog filter responses. FIR filters, on the other hand,
cannot be designed from the theory of analog filters.

• In general, it is easier to implement FIR filters than the IIR filters.

• IIR filters are more suitable in high-speed signal processing operations as they
require fewer arithmetic operations.

● 155

Practical Audio DSP Projects with the ESP32 - UK.indd 155 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

• IIR filters are very sensitive to filter coefficients and quantization errors. Thus,
processors with wider data path may be required for their implementation.

9.3 The Digital Filter Design Process


The digital filter design process can be broken down into the following steps:
• Specifying the filter characteristics and filter type
• Deriving the filter coefficients
• Realizing the filter
• Simulating the filter response (if suitable tools are available)
• Implementing the filter using a processor (e.g., a microcontroller)

Specifying the filter characteristics


The digital filter design process starts with the specification of the required filter. This spec-
ification usually consists of the following:
• Type of filter response, e.g., low-pass, high-pass, band-pass, or band-stop
• Required filter type (FIR or IIR)
• Required-filter order
• Required pass-band and stop-band frequencies and ripple, and the cut-off
frequency
• Sampling frequency

Filter response
Figure 9.1 shows the ideal frequency responses of the low-pass, high-pass, and band-pass
filters.

Figure 9.1: Ideal filter responses: a) low-pass, b) high-pass, c) band-pass, d) band-stop.

The band characteristics are shown in more detail in Figure 9.2 for the case of realizable
low-pass filters. Here, the pass-band and the stop-band may have ripples as shown in the
figure. The ideal cut-off frequency is at the midpoint between the pass-band and the stop-
band and is given by

● 156

Practical Audio DSP Projects with the ESP32 - UK.indd 156 06-07-2023 10:40
Chapter 9 • Digital Filters

The transition band is between the pass-band and the stop-band and is given by

The ripple in the pass-band varies between and The maximum ripple in the
pass-band is usually expressed in decibels and is given by

or,

Similarly, the stop-band ripple is given by

Figure 9.2: Realizable low-pass filter band characteristics.

Filter type
The second important issue in designing a digital filter is the selection of the filter type, i.e.
whether an IIR or an FIR filter is to be used. If the requirement is to have linear phase re-
sponse, then an FIR filter should be employed. If the linear phase response is not a require-
ment, then either an IIR or an FIR filter can be used. The IIR filters are computationally
more efficient and require fewer multiplications and additions. Also, for a given response
characteristic, the FIR design requires higher filter order and consequently more memory
elements.

In many practical applications the linearity of the phase response is not a requirement and
this makes the IIR filter preferable because of the lower processor specification require-
ments.

● 157

Practical Audio DSP Projects with the ESP32 - UK.indd 157 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Filter order
The choice of the filter length depends upon the required frequency response specifications.
The easiest method to choose the filter order is by trial and error using a computer-aided
filter design software package (as you shall see in later chapters).

For the design of IIR-type digital filters converted from analog filters, you can estimate the
filter order from the analog design formulas as will be discussed in the section on designing
IIR filters.

There are several estimates of the filter order for the design of FIR filters. A simple formula
often used is:

Where ws and w p are the normalized angular edge frequencies given by

and , and fT is the sampling frequency.

The above formula can also be written as

An example is given for the use of this formula with MATLAB.

Example 9.1
It is required to design an FIR-type digital filter with pass-band edge at 200 Hz, stop-band
edge at 400 Hz, pass-band ripple of 0.002 and stop-band ripple of 0.001. Assuming a
sampling rate of 1 kHz, estimate the length of the filter. Use the MATLAB package in this
example.

Solution 9.1
The required MATLAB program is given below

dp = input('Pass-band ripple: ');


ds = input('Stop-band ripple: ');
fs = input('Stop-band edge in Hz: ');
fp = input('Pass-band edge in Hz: ');
ft = input('Sampling frequency in Hz: ');
n = –20 * log10 (sqrt(dp * ds)) – 13;
d = 14.6*(fs – fp) / ft;
N=n/d

● 158

Practical Audio DSP Projects with the ESP32 - UK.indd 158 06-07-2023 10:40
Chapter 9 • Digital Filters

A sample run of the program for this example is given below:

Pass-band ripple: 0.002


Stop-band ripple: 0.001
Stop-band edge in Hz: 400
Pass-band edge in Hz: 200
Sampling frequency in Hz: 1000

N = 15.0650

Sampling frequency
According to the sampling theorem, the sampling frequency should be at least twice the
highest frequency in the signal to be sampled. In practice, however, in order to preserve
the fidelity, the sampling frequency is usually (not always) taken to be between 5 to 10
times the highest frequency of the signal to be sampled.

● 159

Practical Audio DSP Projects with the ESP32 - UK.indd 159 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 10 • Designing FIR Digital Filters

10.1 Overview
There are several methods leading to practical design of FIR digital filters. Most FIR filter
design methods are based on ideal filter approximation, meaning the resulting filter ap-
proximates the ideal characteristic as the filter order increases, thus making the filter and
its implementation more complex. The filter design process starts with the specifications
and requirements of the desirable FIR filter. Which method is to be used in the filter design
process depends on the filter specifications and implementation. In this chapter, you will be
learning the basic Fourier Transform-based design and the windowing functions. In addi-
tion, computer-aided design techniques using MATLAB and some of the popular FIR digital
design software packages will be discussed with examples.

FIR filters are non-recursive where the output depends only on the present and previous
inputs, and the differential equation describing the output can be written as

M
y[n] = ∑ bk x[n − k ]
k =0
(10.1)

Where bk equals the successive terms in the impulse response of the filter. In practical
applications, between 10 and 100 coefficients are taken.

The transfer function of FIR filters corresponding to equation (10.1) is given by

M
H [ z ] = ∑ bk z − k
k =0
(10.2)
and the corresponding frequency response is given by

(10.3)

10.2 Truncation and windowing


The coefficients of a realizable FIR low-pass filter can be obtained from:

for 0 ≤ n ≤ N − 1 , and zero otherwise (10.4)

When you truncate an infinite-length impulse response, the process is equivalent to mul-
tiplying it by a finite-length window function. The window function determines how many
coefficients of the impulse response should be taken. In other words, the window function
determines how much of the impulse response you can see. By extending the window func-
tion more of the impulse response can be seen and a better approximation is made to the
ideal filter response.

● 160

Practical Audio DSP Projects with the ESP32 - UK.indd 160 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

The windowing operation is performed in the time domain, and the required impulse re-
sponse coefficients are obtained from the multiplication of the ideal impulse response with
the windowing function. i.e.

(10.5)

Where h[n] are the impulse response coefficients, and w[n]are the windowing function
coefficients.

Many windowing functions have been proposed over the years for the design of FIR filters.
The properties of some of the commonly used windowing functions are given in the next
section.

10.2.1 Rectangular window


This is the simplest windowing function that truncates the ideal impulse response and keeps
it within a rectangular region. This is equivalent to multiplying the ideal impulse response
with

(10.6)

Since the rectangular window has an abrupt transition to zero, it causes oscillatory behavior
in the frequency response of the designed filter (also known as the Gibbs phenomenon).
An example is given below.

Example 10.1
Find the impulse response of a low-pass filter with rectangular windowing where the cut-off
frequency is π/4 and N = 11.

Solution 10.1
Since N = 11, M = (N – 1) / 2 = 5

From equation (10.6),

or, as 0≤n≤10 you get,

h[0] = h[10] = -0.045


h[1] = h[9] = 0
h[2] = h[8] = 0.075
h[3] = h[7] = 0.16
h[4] = h[6] = 0.225

● 161

Practical Audio DSP Projects with the ESP32 - UK.indd 161 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

h[5] = 0.25

note that h[5] is calculated from

Multiplying by the rectangular windowing functions does not change the impulse response
coefficients.

10.2.2 Hamming window


The Hamming window provides a window function that has smooth edges at both ends, and
this window reduces the ripple effect.

The Hamming window is defined mathematically as:

, n = 0,1,2,…., N-1

Figure 10.1 shows the Hamming window for N = 100, plotted using the following MATLAB
statements:

n=0:99;
w=0.54-0.46*cos(2*pi*n/99);
plot(n,w)

Figure 10.1: The Hamming window.

Because the window function is multiplied by the ideal filter impulse response, the impulse
response of the FIR low-pass filter designed using the Hamming window has the following
equation:

● 162

Practical Audio DSP Projects with the ESP32 - UK.indd 162 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

for 0 ≤ n ≤ N − 1 , and zero otherwise


An example filter design is given below for a low-pass FIR filter using the Hamming window.

Example 10.2
Find the impulse response of a low-pass filter with Hamming window, where the cut-off
frequency is π/4 and N = 11

Solution 10.2
The impulse response coefficients of the ideal filter are given by:

Since N = 11, M = (N – 1) / 2 = 5

From equation (10.4),

or, as 0≤n≤10 you get,

h[0] = h[10] = -0.045


h[1] = h[9] = 0
h[2] = h[8] = 0.075
h[3] = h[7] = 0.16
h[4] = h[6] = 0.225
h[5] = 0.25

Using the following MATLAB statements, you can find the coefficients of the Hamming win-
dow for the required filter:

>> n=0:10;
>> w=0.54 - 0.46*cos(2*pi*n/10)

w=

Columns 1 through 9

0.0800 0.1679 0.3979 0.6821 0.9121 1.0000 0.9121 0.6821 0.3979

Columns 10 through 11

0.1679 0.0800

Thus,

● 163

Practical Audio DSP Projects with the ESP32 - UK.indd 163 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

w[0] = w[10] = 0.0800


w[1] = w[9] = 0.1679
w[2] = w[8] = 0.3979
w[3] = w[7] = 0.6821
w[4] = w[6] = 0.9121
w[5] = 1

The impulse response coefficients are found from the multiplication of h[n] and w[n] and
are:

hd[0] = hd[10] = -0.0036


hd[1] = hd[9] = 0
hd[2] = hd[8] = 0.029
hd[3] = hd[7] = 0.109
hd[4] = hd[6] = 0.205
hd[5] = 0.25

10.2.3 Hanning Window


The Hanning window function is similar to the Hamming window and is defined mathemat-
ically as

, n = 0,1,2,…., N-1

10.2.4 Blackman Window


The Blackman window function gives an even lower ripple than the Hamming window func-
tion. This function is defined mathematically as

, n = 0,1,2,…., N-1

Figure 10.2 shows the Blackman window function plotted with N = 100, using the following
MATLAB statements. Notice that the Blackman window is wider than the Hamming window.

● 164

Practical Audio DSP Projects with the ESP32 - UK.indd 164 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

Figure 10.2: The Blackman window.

An example is given below to show how the impulse response of an FIR filter can be com-
puted using the Blackman window.

Example 10.3
Find the impulse response of a low-pass filter with Blackman window, where the cut-off
frequency is π/4 and N = 11. Plot the frequency response using MATLAB.

Solution 10.3
As in Example 10.2, the impulse response coefficients of the ideal filter are given by:

Since N = 11, M = (N – 1) / 2 = 5

From equation (10.6),

or, as 0≤n≤10 you get,

h[0] = h[10] = -0.045


h[1] = h[9] = 0
h[2] = h[8] = 0.075
h[3] = h[7] = 0.16
h[4] = h[6] = 0.225
h[5] = 0.25

Using the following MATLAB statements, you can find the coefficients of the Blackman win-
dow for the required filter:

n=0:10;
w=0.42-0.5*cos(2*pi*n/10)+0.08*cos(4*pi*n/10)

● 165

Practical Audio DSP Projects with the ESP32 - UK.indd 165 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

w=

Columns 1 through 9

-0.0000 0.0402 0.2008 0.5098 0.8492 1.0000 0.8492 0.5098 0.2008

Columns 10 through 11

0.0402 -0.0000

Thus,

w[0] = w[10] = 0
w[1] = w[9] = 0.0402
w[2] = w[8] = 0.2008
w[3] = w[7] = 0.5098
w[4] = w[6] = 0.8492
w[5] = 1

The impulse response coefficients are found from the multiplication of h[n] and w[n] and
are:

hd[0] = hd[10] = 0
hd[1] = hd[9] = 0
hd[2] = hd[8] = 0.0151
hd[3] = hd[7] = 0.0816
hd[4] = hd[6] = 0.1911
hd[5] = 0.25

The frequency response is plotted using MATLAB function fvtool(hd, 1) and is shown in Fig-
ure 10.3. Note that the response exhibits a lower ripple than the Hamming window.

Figure 10.3: Frequency response of the designed filter.

● 166

Practical Audio DSP Projects with the ESP32 - UK.indd 166 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

When designing digital FIR filters using window functions it is necessary to specify:
• The window function to be used
• The filter order for the required specifications (selectivity and stop-band
attenuation)

The selected windowing function affects the transition region, the minimum stop-band
attenuation of the used window function, and the minimum stop-band attenuation of the
designed filter. Table 10.1 shows a comparison of some of the windowing functions for an
FIR filter having 20 coefficients.

Table 10.1: Comparison of selected windowing functions.

It is important to see from the table that the minimum attenuation of window function and
that of the filter designed using that function are different for different windows. The differ-
ence is mainly the stop-band attenuation. The minimum stop-band attenuation is fixed for
each windowing function, except for the Kaiser window (described in next section).

Some important response concepts are shown in Figure 10.4, such as the main lobe, main
lobe width, side lobes, transition region, and minimum stop-band attenuation.

Figure 10.4: Some important FIR response concepts.

● 167

Practical Audio DSP Projects with the ESP32 - UK.indd 167 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

As can be seen from the table above, the stop-band attenuation of the given windows is
not adjustable. Only the transition region can be affected by increasing the filter order.
Therefore, a design should start by specifying the appropriate window function on the basis
of the stop-band attenuation. A window with the least stop-band that satisfies the given
requirements should be chosen. As a result, the designed filter will have the narrowest
transition region.

10.2.4 Kaiser window


Each of the window functions described earlier is a kind of compromise between require-
ments for a narrow transition region and high stop-band attenuation. The Kaiser window
(also known as the Kaiser-Bessel window) is an optimal window in the sense that it has
maximum attenuation according to the given width of the main lobe. The Kaiser window
is frequently chosen in FIR filter design as it contains an adjustable parameter with which
main lobe width and corresponding minimum stop-band attenuation can be controlled.

10.2.5 Remez Exchange-based design


The Remez Exchange algorithm offers a much more powerful design technique than the
windowing method you have seen in the last few sections. This algorithm designs an opti-
mal FIR filter by minimizing the ripples in the pass-band. In general, the pass-band ripples
all have equal amplitude, as do all the stop-band ripples. The Parks-McClellan algorithm
uses the Remez Exchange algorithm and Chebyshev approximation theory to design digital
filters with an optimal fit between the desired and actual frequency responses. You will see
how to design FIR filters based on this algorithm using the computer-aided techniques in
the next section.

10.3 Using computer-aided techniques for the design of FIR filters


There are many computer programs to help design various types of FIR digital filters. In
addition, you can use the MATLAB, or even write the necessary algorithm using a program-
ming language.

Some of the popular FIR filter design programs include:


• ScopeFIR (www.ioweigan.com)
• FIR filter design by Dr A R Collins (https://www.arc.id.au/FilterDesign.html)
• TFilter (http://t-filter.engineerjs.com/)
• FIIIR (https://fiiir.com/)
• DigitalFilter Plus (https://www.numerix-dsp.com/dfplus/)
• Online Filter Design Tool (https://leventozturk.com/engineering/filter_design/)

and many other online design tools and programs that can be found on the Internet. All of
the FIR design software given here are free of charge except the ScopeFIR. ScopeFIR is a
professional FIR filter design tool covering all types of algorithms and window functions with
plots of the impulse response, frequency response and so on. In this section, you will learn
how to design FIR filters using the ScopeFIR software package and the freely available Dr
A R Collins FIR software program.

● 168

Practical Audio DSP Projects with the ESP32 - UK.indd 168 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

10.3.1 ScopeFIR
ScopeFIR software enables you to design many different types of FIR filters, including low-
pass, high-pass, band-pass, and band-stop. In addition, different algorithms can be select-
ed for the design. The impulse response coefficients, plot of the impulse response, and plot
of the frequency response of the designed filter can easily be seen.

The features of the ScopeFIR filter are given below:


• Design of low-pass, band-pass and band-stop filters
• Design using windowed design, simple and advanced McClellan algorithm,
Raised cosine algorithm, and others
• Specifying the filter order
• Specifying the cut-off frequency and the sampling rate
• Specifying the pass-band and stop-band ripples

Some example FIR filter designs are given below to illustrate the steps involved in the de-
sign. The following examples assume that the ScopeFIR package has already been installed
on the PC. The version of the software used by the author was version 6.0.

Example 10.4
Design an FIR filter with the following specifications using the ScopeFIR software package:
• Low-pass
• Filter order 20 (number of taps = 21)
• Hamming window
• Cut-off frequency 1 kHz
• Sampling frequency 10 kHz

Obtain the impulse filter coefficients and plot the impulse response and the frequency re-
sponse of the designed filter.

Solution 10.4
Step 1: Start the ScopeFIR package.

Step 2: Select the required algorithm (e.g., Windowed Sinc) as shown in Figure 10.5.

● 169

Practical Audio DSP Projects with the ESP32 - UK.indd 169 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 10.5: Select the required algorithm.

Step 3: Enter the cut-off frequency, sampling frequency, number of taps, and select Ham-
ming window and filter type as Low-Pass as shown in Figure 10.6.

Figure 10.6: Enter the frequencies and select Hamming window.

Step 4: Click Design. You should see the impulse response parameters in the top right-
hand side of the screen as shown in Figure 10.7.

Figure 10.7: Impulse response coefficients.

● 170

Practical Audio DSP Projects with the ESP32 - UK.indd 170 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

The frequency response of the designed filter is shown in Figure 10.8. Notice that the ripple
occurs around the –60 dB line.

Figure 10.8: Frequency response of the designed filter.

The impulse response is shown in Figure 10.9.

Figure 10.9: Impulse response of the designed filter.

Example 10.5
Design an FIR filter with the following specifications using the ScopeFIR software package:
• Low-pass
• Filter order 20 (number of taps = 21)
• Simple Parks-McClellan
• Pass-band upper frequency 1 kHz
• Stop-band lower frequency 1.5kHz
• Sampling frequency 10 kHz
• Pass-band ripple 1 dB
• Stop-band attenuation 80 dB

Obtain the impulse filter coefficients and plot the impulse response and the frequency re-
sponse of the designed filter.

● 171

Practical Audio DSP Projects with the ESP32 - UK.indd 171 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Solution 10.5
Figure 10.10 shows the design parameters entered to the form.

Figure 10.10: Entering the design parameters.

Clicking the Design button designs the filter. The frequency response of the designed filter
is shown in Figure 10.11. Note that the stop-band attenuation is around -60 dB.

Figure 10.11: Frequency response of the designed filter.

You can optimize the design by clicking the Optimize button. This will make sure that the
stop-band attenuation is at least -80 dB as requested, but the number of tappings will in-
crease as shown in Figure 10.12 (it will increase to 57 in this example).

● 172

Practical Audio DSP Projects with the ESP32 - UK.indd 172 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

Figure 10.12: Frequency response of the optimized filter.

The impulse response of the optimized filter is shown in Figure 10.13.

Figure 10.13: Impulse response of the designed filter.

Example 10.6
Design an FIR filter with the following specifications using the ScopeFIR software package:
• High-pass
• Filter order 30 (number of taps = 31)
• Simple Parks-McClellan
• Pass-band upper frequency 1.5 kHz
• Stop-band lower frequency 2 kHz
• Sampling frequency 10 kHz
• Pass-band ripple 1 dB
• Stop-band attenuation 50 dB

Obtain the impulse filter coefficients and plot the impulse response and the frequency re-
sponse of the designed filter.

● 173

Practical Audio DSP Projects with the ESP32 - UK.indd 173 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Solution 10.6
Figure 10.14 shows the design parameters entered into the form.

Figure 10.14: Entering the design parameters.

Clicking the Design button designs the filter. The frequency response of the designed filter
is shown in Figure 10.15. Note that the stop-band attenuation is around -45 dB.

Figure 10.15: Frequency response of the designed filter.

10.3.2 Dr A R Collins FIR filter design


This program is based on the Kaiser window function and it can be used to design low-pass,
high-pass, band-pass, band-stop FIR digital filters. The program is very simple to use.
Some examples are given below.

Example 10.7
Design an FIR filter with the following specifications using the Dr A R Collins FIR program:
• Low-pass
• Filter order 20 (number of taps = 21)
• Kaiser window
• Cut-off frequency 1 kHz
• Sampling frequency 10 kHz
• Stop-band attenuation 60 dB

● 174

Practical Audio DSP Projects with the ESP32 - UK.indd 174 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

Solution 10.7
Start the program and enter the required filter specifications as shown in Figure 10.16.
Click CALCULATE FILTER. The designed filter frequency response, impulse response, and
the filter coefficients will be displayed as shown in the Figure. Notice that the stop-band
attenuation is 60 dB.

Figure 10.16: Designing using Dr A R Collins program.

Figure 10.17 shows the same design with the stop-band attenuation changed to 80 dB.

Figure 10.17: Stop-band attenuation changed to 80 dB.

● 175

Practical Audio DSP Projects with the ESP32 - UK.indd 175 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 10.18 shows the same design with the stop-band attenuation at 60 dB, but the filter
order increased to 50. Notice the change in the transition region by increasing the filter
order (the transition region became much shorter).

Figure 10.18: Filter with increased filter order.

Example 10.8
Design an FIR filter with the following specifications using the Dr A R Collins FIR program:
• and-pass
• Filter order 30 (number of taps = 31)
• Band edges at 1800 Hz and 3000 Hz
• Kaiser window
• Sampling frequency 10 kHz
• Stop-band attenuation 60 dB

Solution 10.8
Start the program and enter the required filter specifications as shown in Figure 10.19. The
frequency response, impulse response, and filter coefficients are all shown in the Figure.

● 176

Practical Audio DSP Projects with the ESP32 - UK.indd 176 06-07-2023 10:40
Chapter 10 • Designing FIR Digital Filters

Figure 10.19: Band-pass filter design.

10.4 FIR digital filter structures


There are several FIR structures used in practice. The most commonly used ones are the
direct form and cascade form. You shall look at both realizations briefly in this section.

10.4.1 Direct FIR structures


Recall that an FIR filter of length N has the transfer function of H[z] which is a polynomial
in z-1 with degree N-1. The transfer function H[z] is given by

The input-output time-domain relationship is given by the difference equation

N −1
y[n] = ∑ h[n] x[n − k ]
k =0

Where y[n] and x[n] are the output and input sequences, respectively.

An FIR filter of length N has N coefficients, and in general requires N multipliers and N-1
adders (two-input) for its implementation. The direct form is realized by expanding and
implementing the difference equation. For example, for N = 5 you have

y[n] = h[0]x[n] + h[1]x[n − 1] + h[2]x[n − 2] + h[3]x[n − 3] + h[4]x[n − 4]

The direct form of realization for the above example with N = 5 is shown in Figure 10.20.
Notice that in this example there are 5 coefficients, 5 multipliers, and 4 two-input adders.

● 177

Practical Audio DSP Projects with the ESP32 - UK.indd 177 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 10.20: Direct form of FIR realization for N = 5.

10.4.2 Cascade FIR structures


An FIR filter can be realized as a cascade of first-order or second-order FIR transfer func-
tions. You can write the general FIR transfer function as

Where K = (N – 1) / 2 if N is odd, and K = N / 2 if N is even. An example for a fourth-order


filter is shown in Figure 10.21 where there are 4 coefficients, 4 multiplications, 4 two-input
adders.

Figure 10.21: Cascade form of FIR realization for N = 5.

● 178

Practical Audio DSP Projects with the ESP32 - UK.indd 178 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

Chapter 11 • Design Of IIR Digital Filters

11.1 Overview
There are several methods available for the design of IIR-type digital filters, such as the im-
pulse invariance method, the bilinear transform method, the analog approximation meth-
od, and others. IIR digital filter design mainly concentrates on the magnitude response
of the filter and regards the phase response as secondary. IIR digital filters are usually
designed via classical analog filter approximations. An analog filter is designed initially and
then it is converted into an equivalent digital filter using transformation methods, such as
the backward difference, or the bilinear transformation. There are several classes of analog
filters, such as Butterworth, Chebyshev, inverse-Chebyshev, Bessel, and elliptic filters.

In this chapter, you will explore some of the analog filter design methods and then see how
digital IIR-type filters can be designed using these methods. In addition, the design of IIR
digital filters using computer software packages will be discussed with example designs. At
the end of the chapter, various IIR digital filter structures will be shown.

11.2 IIR filter transfer function


The input and output of an IIR digital filter are related by the following difference equation:
N M
y[n] = −∑ a(k ) y (n − k ) + ∑ b(k ) x(n − k )
k =1 k =0 (11.1)

By combining y[k] with the first summation,


N M

∑ a ( k ) y ( n − k ) + ∑ b( k ) x ( n − k )
k =0 k =0 (11.2)

From the z-transform theory, z-1 is a unit delay operator, i.e.,

z − k x ( n) = x ( n − k ) (11.3)

Also, with a(0) = 1, from (11.2) and (11.3) you can write the transfer function in terms of
the z-transforms as

∑ b( k ) z −k

H ( z) = k =0
N

∑ a(k ) z
k =0
−k

or,

● 179

Practical Audio DSP Projects with the ESP32 - UK.indd 179 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

b(0) + b(1) z −1 + b(2) z −2 + ..... + b( M ) z − M


H ( z) =
1 + a(1) z −1 + a(2) z − 2 + ......... + a( N ) z − N (11.4)

11.3 Analog filter design review


Three types of analog filters are standard and are commonly used: Butterworth, Cheby-
shev, and elliptic filters. Figure 11.1 shows the typical frequency responses of these analog
filters for comparison. In this figure, all the filters have order 8 and cut-off frequencies of
1 Hz.

Figure 11.1: Frequency responses of commonly used analog filters.

11.4 Butterworth filters


The gain-frequency response of a Butterworth filter is given by

(11.5)

Where, N is the filter order and wc is the cut-off frequency, and the filter response decreas-
es monotonically as the frequency is increased.

At the cut-off frequency,

w = wc and the magnitude becomes

Similarly, in the stop-band, where i.e. after one decade of the cut-off frequency,

the magnitude becomes

● 180

Practical Audio DSP Projects with the ESP32 - UK.indd 180 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

or the magnitude becomes . Thus, the gain decreases by -20 dB per


decade in the stop-band for an increase of the filter order by one.

Filter order
The filter order for a given specification can be determined from the following equations

(11.6)

where

(11.7)
and

ws f
B= = s
wp fp (11.8)

where, ws and w p are the pass-band and stop-band edge frequencies. K s and K p are the
stop-band attenuation and pass-band ripple respectively (in dB).

An example is given below.

Example 11.1
Determine the order of a Butterworth filter that meets the following specifications:

fp = 1 kHz
fs = 5 kHz
Ks = 40 dB
Kp = 1 dB

Solution 11.1
From equations (11.6) to (11.8) you have
5
B= =5
1

Therefore, rounding up, you have N = 4.

● 181

Practical Audio DSP Projects with the ESP32 - UK.indd 181 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Normalized Butterworth Polynomials


The normalized Butterworth polynomials for filters with orders up to 8 are shown in Table
11.1.

Table 11.1: Normalized Butterworth polynomials.

The normalized Butterworth polynomials can be used to determine the transfer function

for any low-pass filter cut-off frequency wc using the bilinear transformation method or
the impulse invariant method, as described below.

11.4.1 Bilinear transformation method


The bilinear transformation method is used to convert an analog transfer function H(s)
into a digital transfer function H(z). This transformation is performed by

z −1
s=
z + 1 (11.9)

After the transformation, the analog critical frequency and digital critical frequency

are related by

(11.10)

The design steps with the bilinear transformation are summarized below:

1.Determine the Butterworth polynomial for the required filter (Table 11.1).

2.Calculate the normalized cut-off frequency of the digital filter ( ).


3.Calculate the normalized cut-off frequency of the required
analog filter (equation 11.10).

● 182

Practical Audio DSP Projects with the ESP32 - UK.indd 182 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

4.De-normalize the analog filter by replacing s with .


5.Convert the analog filter into a digital filter using the bilinear transformation
(equation 11.9).
6.Convert zk into z–k in the polynomial.
7.Expand the polynomial to obtain the filter coefficients by comparing them with
the IIR filter equation (equation 11.4).

An example is given below to illustrate the design process.

Example 11.2
It is required to design a low-pass 2nd-order Butterworth filter with a pass-band edge fre-
quency of 100 Hz. Assume that the sampling rate is 1000 Hz.

Solution 11.2

Step 1:
From Table 11.1, the normalized transfer function of the required 2nd-order analog filter in
the s-plane is given by:

1
H (s) = 2
s + 1.4142 s + 1
Step 2:
The normalized cut-off frequency of the digital filter is given by:

Step 3
The equivalent analog filter cut-off frequency is given by using equation (11.10):

Step 4:
De-normalizing the analog filter transfer function, you have:

1
H (s) = 2
 s  1.4142 s 
 0.325  +  0.325  + 1
   

Step 5:
z −1
Convert the analog filter into a digital filter by using equation (11.9), i.e., s=
z +1

● 183

Practical Audio DSP Projects with the ESP32 - UK.indd 183 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

This gives

1
H ( z) = 2
1  z − 1 1.4142  z − 1
0.325 2  z + 1 + 0.325  z + 1 + 1
Simplifying,

0.067 z 2 + 0.135 z + 0.067


H ( z) =
z 2 − 1.1429 z + 0.4127
Step 6:
Converting to z-k you have

0.067 + 0.135 z −1 + 0.067 z −2


H ( z) =
1 − 1.1429 z −1 + 0.4127 z − 2

Step 7:
Comparing with equation (11.4) you have the required filter parameters:

b(0)=0. 067
b(1)=0.135
b(2)=0.067
a(0)=1
a(1)=−1.1429
a(2)=0.4127

Figure 11.2 shows the frequency response of the designed filter.

Figure 11.2: Frequency response of the designed filter.

MATLAB function butter can be used to design Butterworth-type digital filters. Function
butter is used to determine the filter order. An example is given below.

● 184

Practical Audio DSP Projects with the ESP32 - UK.indd 184 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

Example 11.3
Find the coefficients of a low-pass Butterworth digital filter with a cut-off frequency of 100
Hz and a sampling frequency of 1000 Hz.

Solution 11.3
The required MATLAB statement is given below

[num, den] = butter(2,1/5)

num =

0.0675 0.1349 0.0675

den =

1.0000 -1.1430 0.4128

Where num and den are the numerator and denominator coefficients, respectively. Notice
that this result is the same as in Example 11.2.

Example 11.4
Find the coefficients of a 6th-order band-pass Butterworth digital filter with pass-band edg-
es of 0.4 and 0.8, respectively. Plot the frequency response.

Solution 11.4
The required MATLAB statements are:

N = 6;
M = N / 2;
w1 = 0.4;
w2 = 0.8;
wn = [w1 w2];
[num den] = butter(M, wn)

num =

0.0985 0 -0.2956 0 0.2956 0 -0.0985

den =

1.0000 1.3664 1.2449 0.8777 0.6537 0.2256 0.0563

Thus, the coefficients are:

● 185

Practical Audio DSP Projects with the ESP32 - UK.indd 185 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

b(0)=0.0985
b(1)=0
b(2)=−0.2956
b(3)=0
b(4 )=0. 2956
b(5)=0
b(6)=−0.0985
a(0)=1
a(1)=1.3664
a(2)=1.2449
a(3)=0.8777
a(4 )=0. 6537
a(5)=0.2256
a(6)=0.0563

The frequency response can be plotted using the following MATLAB statements and is
shown in Figure 11.3.

w = 0:0.01/pi:pi;
h = freqz(num, den, w);
plot(w/pi, 20*log10(abs(h)));
grid;
xlabel('Normalized frequency ');
ylabel('Gain (dB)');
title('Bandpass Butterworth Filter');

Figure 11.3: Frequency response of the filter.

Example 11.5
Write a MATLAB program to design a digital Butterworth band-pass filter. Enter the filter or-
der and the band edge frequencies from the keyboard. Then plot the normalized frequency
response of the filter.

● 186

Practical Audio DSP Projects with the ESP32 - UK.indd 186 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

Solution 11.5
The required MATLAB program is:

%
% Butterworth IIR band-pass filter design
%
N = input('Enter the filter order: ');
wL = input('Enter the lower pass-band edge frequency: ');
wH = input('Enter the upper pass-band edge frequency: ');
wn = [wL wH];
[num den] = butter(N/2, wn);
disp('Numerator polynomial (b terms): '); disp(num);
disp('Denominator polynomial (a terms): '); disp(den);
wf = 0:0.1/pi:pi;
H = freqz(num, den, wf);
plot(wf/pi, 20*log10(abs(H)));
grid on;
xlabel('Normalized frequency ');
ylabel('Gain (dB) ');
title('Band-pass Butterworth Filter ');

11.5 Chebyshev filters


The Butterworth filters do not provide sharp attenuation at the stop-band. Thus, in appli-
cations where large stop-band attenuation is required, a very high-order Butterworth filter
is required.

The Chebyshev filters provide higher attenuation in the stop-band but at the same time,
they provide ripples in the pass-band. Thus, if the application can tolerate some ripples in
the pass-band then Chebyshev filters offer higher attenuation in the stop-band than the
Butterworth filters for a given filter order.

The gain-frequency response of a Chebyshev filter is given by

(11.11)

Where, N is the filter order, defines the amount of ripple, and TN2 ( w) is an Nth-order
Chebyshev polynomial, given by:

(11.12)

The design of Chebyshev filters involves the determination of both the order and the ripple
parameter.

● 187

Practical Audio DSP Projects with the ESP32 - UK.indd 187 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The maximum allowed ripple (in dB) in the pass-band is given by

(11.13)

Filter order

The filter order for a given specification can be determined from the following equations

cosh −1 A
N≥
cosh −1 B (11.14)
where

(11.15)
and

ws f
B= = s
wp fp
(11.16)

where, ws and w p are the pass-band and stop-band edge frequencies. K s and K p are the
stop-band attenuation and pass-band ripple respectively (in dB).

Example 11.6
Determine the order of a Chebyshev filter that meets the following specifications:

fp = 1 kHz
fs = 5 kHz
Ks = 40 dB
Kp = 1 dB

Solution 11.6
From equations (11.14) to (11.16) you have

5
B= =5
1

● 188

Practical Audio DSP Projects with the ESP32 - UK.indd 188 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

Therefore, rounding up, you have N = 3. Compared with the Butterworth design with the
same specifications, it is clear that a lower-order Chebyshev filter is required.

The design of Chebyshev digital filters using the bilinear transformation is similar to the
design of Butterworth filters. First, the required normalized Chebyshev polynomial in the
s-plane is obtained for the required filter order and ripple using published tables. Then the
digital filter is designed by following the steps given in section 11.3.1, Example 11.2.
The MATLAB function cheby1 can be used to design Chebyshev type filters.

Example 11.7
Design a 5th-order Chebysev-type high-pass digital filter using MATLAB with a pass-band
ripple of 2 dB and the pass-band edge at 0.8. Then plot the frequency response.

Solution 11.7
The required MATLAB statements are:

N = 5;
e = 2;
wn = 0.8;
[num, den] = cheby1(N, e, wn, 'high')

num =

0.0002 -0.0010 0.0021 -0.0021 0.0010 -0.0002

den =

1.0000 4.0974 7.1332 6.5482 3.1612 0.6420

The statements to plot the frequency response are given below and is shown in Figure 11.4:

w = 0:0.1/pi:pi;
H = freqz(num, den, w);
plot(w/pi, 20*log10(abs(H)));
grid on;

Figure 11.4: Frequency response of the designed filter.

● 189

Practical Audio DSP Projects with the ESP32 - UK.indd 189 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

11.6 Elliptic filters


The Elliptic filter is the most efficient filter as it provides the most attenuation with the low-
est order. Elliptic filters have ripples in their pass-band and stop-band.

The gain-frequency response of elliptic filters is given by

(11.17)

2
Where, N is the filter order, defines the amount of ripple, and R N ( w) is an Nth-order
polynomial. The design of elliptic filters is much more complex than the design of other
types of filters. There are many books and papers on the design of elliptic filters and inter-
ested readers should consult these sources.

The MATLAB function ellip can be used to design elliptic filters.

Example 11.8
Design a low-pass digital elliptic filter with an order of 7 and a pass-band edge at 0.5. As-
sume a pass-band ripple of 0.3 dB, and minimum stop-band attenuation of 50 dB. Plot the
frequency response of the filter.
Solution 11.8
The required MATLAB statements are given below:

N = 7;
ep = 0.3;
as = 50;
wn = 0.5;
[num den] = ellip(N, ep, as, wn)

num =

0.0470 0.1428 0.2909 0.3955 0.3955 0.2909 0.1428 0.0470

den =

1.0000 -1.0369 2.4623 -1.9400 1.9515 -1.0431 0.4862 -0.1275

The frequency response can be plotted using the following MATLAB statements, and is
shown in Figure 11.5:

w = 0:0.1/pi:pi;
H = freqz(num, den, w);
plot(w/pi, 20*log10(abs(H)));
grid on;

● 190

Practical Audio DSP Projects with the ESP32 - UK.indd 190 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

Figure 11.5: Frequency response of the designed filter.

11.7 Computer-aided design tools for the design of IIR digital filters
There are many software packages available on the Internet that help to calculate the IIR
digital filter coefficients. Some popular ones are:
• ScopeIIR (iowegian.com)
• Digital Filter Plus (https://www.numerix-dsp.com/dfplus/)
• FIIIR (https://fiiir.com/)
• IIR Filter Explorer (http://jaggedplanet.com/iir/iir-explorer.asp)
• How to implement IIR Bandpass Butterworth Filter using Scipy – Python?
(https://www.geeksforgeeks.org/how-to-implement-iir-bandpass-butterworth-
filter-using-scipy-python/)
• Digital Filter Analyzer (http://www.digitalfilter.com/products/dfalz/endfalz.html)
• and many others.

Examples are given in the following sections on using the ScopeIIR and the freely available
Digital Filter Analyzer.

11.7.1 The ScopeIIR filter design program


ScopeIIR is professional software (i.e., not free) and it enables you to design many different
types of IIR filters, including low-pass, high-pass, band-pass, and band-stop. In addition,
different algorithms can be selected for the design, and the frequency response and the
phase response can be plotted.

The features of the ScopeIIR filter are given below:


• Design of low-pass, band-pass and band-stop filters
• Design of Butterworth, Chebyshev, and elliptic filters
• Specifying the filter order
• Specifying the cut-off frequency and the sampling rate
• Specifying the pass-band and stop-band ripples

Some examples of IIR filter designs are given below to illustrate the steps involved in the
design. The following examples assume that the ScopeIIR package has already been in-
stalled on the PC.

● 191

Practical Audio DSP Projects with the ESP32 - UK.indd 191 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Example 11.9
Design an IIR filter with the following specifications:
• Low-pass
• Butterworth design
• Cut-off frequency = 100 Hz
• Sampling rate = 1000 Hz
• Filter order = 7

Solution 11.9
Figure 11.6 shows the ScopeIIR design window. Clicking the design button designs the filter
and draws the frequency response and the phase response. The frequency response of the
designed filter is shown in Figure 11.7.

Figure 11.6: The design window.

Figure 11.7: Frequency response of the filter.

The filter coefficients are shown at the bottom left-hand corner of the screen. In addition,
the pole-zero positions of the designed filter are shown on the left-hand side of the screen.

11.7.2 The Digital Filter Analyzer IIR design program


This is freely available software. An example design is given below:

Example 11.10
Design an IIR filter with the following specifications:
• Low-pass
• Chebyshev design

● 192

Practical Audio DSP Projects with the ESP32 - UK.indd 192 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

• Cut-off frequency = 100 Hz


• Sampling rate = 1000 Hz
• Filter order = 8 (4 biquad sections)
• Ripple = 3 dB

Solution 11.10
Select LPF for low-pass filter, click Design and enter the specifications as shown in Figure
11.8. Click OK and then click F-Response and then Coefficients to display the frequency
response and filter coefficients (Figure 11.9).

Figure 11.8 IIR filter design specifications

Figure 11.9 Frequency response and filter coefficients

● 193

Practical Audio DSP Projects with the ESP32 - UK.indd 193 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

11.8 IIR filter structures


The IIR filters are commonly implemented in two structures: Direct structure, or Cascade
structure. Both structures are discussed briefly in this section.

11.8.1 Direct structure


The direct form of realization is based on the direct implementation of the IIR difference
equation given in (11.1):

N M
y[n] = −∑ a(k ) y (n − k ) + ∑ b(k ) x(n − k )
k =1 k =0

Expanding the above equation, the input and output samples are related by

y[n] = −a1 y (n − 1) − a 2 y (n − 2) − a3 y (n − 3) − ........ − a N y (n − N ) + b0 x(n) + b1 x(n − 1) + ........


...... + bM x(n − M )

Figure 11.10 shows the implementation of the above difference equation in direct form.

Figure 11.10: Direct form structure.

11.8.2 Cascade structure


The cascade structure is commonly used in digital filter implementations. In cascade struc-
ture, the numerator and denominator polynomials of the transfer function is expressed as
a product of lower-degree functions. Usually, the transfer function is factored into a product
of second-order and first-order polynomials.

For example, a third-order filter is implemented from a cascade of a first-order and a sec-
ond-order filter transfer functions as shown below:

● 194

Practical Audio DSP Projects with the ESP32 - UK.indd 194 06-07-2023 10:40
Chapter 11 • Design Of IIR Digital Filters

Figure11.11 shows the implementation of this third-order filter in cascade form.

Figure 11.11: Third-order cascade structure.

An example is given below to illustrate the implementation of a third-order transfer function


with a cascade structure.
Example 11.10
Implement the following third-order transfer function using a cascade structure consisting
of a first-order and a second-order transfer function.

Solution 11.10
You can factor the transfer function into a second-order and a first-order polynomial:

Writing in terms of inverse powers of z, you have

The above transfer function can easily be implemented as shown in Figure 11.12.

Figure 11.12: Implementing the transfer function.

● 195

Practical Audio DSP Projects with the ESP32 - UK.indd 195 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Chapter 12 • D
 esigning FIR Digital Filters with the
ESP32 DevKitC

12.1 Overview
In this chapter, you will be learning the design of FIR digital filters. The filter coefficients
will be obtained using the ScopeFIR filter design program described in Chapter 10. After
obtaining the filter coefficients, you will draw the structure of the filter to be implemented.
The actual physical filter will then be realized using the ESP32 DevKitC development board.

Only audio FIR digital filters are considered in this chapter. The frequency response of the
designed filter will be plotted in real-time using the Velleman PCSGU250 digital oscillo-
scope/function generator/Bode plotter device.

Several real-time audio-based projects are given in this chapter using a Pmod I2S2 device
before designing FIR-type digital filters.

12.2 The PCSGU250


Figure 12.1 shows the PCSGU250 instrument. It is connected to a PC and is a combination
of a function generator, digital oscilloscope, transient recorder, spectrum analyzer, and a
Bode plotter, manufactured by Velleman. The function generator, oscilloscope, and Bode
plotter parts of this instrument are used in the projects. The specifications of the function
generator, Bode plotter, and the oscilloscope are as follows:

Function Generator
• Sweep frequency: 0.005 Hz to 500 kHz
• Amplitude range: 00 mV to 10 V
• Offset voltage: –5 V to +5 V
• Vertical resolution: 8 bits
• Sample rate: 12.5 MHz

Bode Plotter
• Logarithmic plotting
• Automatic sync between input and output
• Volt (V) and decibel (dB) plotting
• Voltage range: 10 mV to 3 V
• Frequency range: 10 Hz to 10 kHz

Oscilloscope
• Bandwidth: DC to 12 MHz (2 channels)
• Input impedance: 1 Mohm
• Maximum input voltage: 39 V
• Timebase: 0.1 μs to 500 ms
• Input range: 10 mV to 3 V per division
• Input sensitivity: 0.3 mV display resolution

● 196

Practical Audio DSP Projects with the ESP32 - UK.indd 196 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Figure 12.1: The Velleman PCSGU250 device.

12.3 Arduino Audio Tools library


In DSP-based projects you will be using the Arduino Audio Tools library developed by
Phil Schatzmann. This library includes many useful DSP tools for generating sound, de-
signing digital filters, FFT, and many more.

Before using the library, you have to install it in your Arduino IDE. The steps are given
below (you can also see many example files at this link on how to use various tools of the
library):

• Go to the following website:

https://github.com/pschatzmann/arduino-audio-tools

• Click on Code (green tab) and then click Download ZIP (Figure 12.2).

Figure 12.2: Click on Download ZIP.

• You should have the following file downloaded to your Downloads folder (this
was the file at the time of authoring this book): arduino-audio-tools-main.
zip.

● 197

Practical Audio DSP Projects with the ESP32 - UK.indd 197 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

• Start your Arduino IDE. Click Sketch  Include Library and select Add .ZIP
Library...

• Browse and select the file you just downloaded and click OPEN.

• Restart your IDE.

• To verify your installation, click File  Examples and scroll down to audio-
tools. You should see many example files listed.

There are many header files with default settings included with the installation. You may
like to look at these files at the above link, or at the following folder (you are advised to
have a look at the sample example files under folder: Examples):

C:/users/<Your user name>/Documents/Arduino/libraries/arduino-audio-tools-


main/

12.4 Project 1: Sinewave generator


Description: In this project, you will be generating a sinewave with a frequency of 2 kHz
using the audio tools library with I2S interface.

The aim: The aim of this project is to show how the audio tools library can be used to gen-
erate a sinewave with the required frequency. This project should be a good starting point
before you look at the FIR digital filter projects.

The block diagram and circuit diagram of the project are in Figure 6.34 and Figure 6.35, re-
spectively. The generated sinewave is sent to the speaker through the I2S class D amplifier.

Program listing: Figure 12.3 shows the program listing (Program: Sinewave). At the
beginning of the program, the header file AudioTools.h is included in the program. Then
the sample rate is set to 44100 Hz with 1 channel, sine wave generator set to amplitude
32000, which is about the maximum amplitude, and the sound stream is set to sineWave.

Information on the SineWaveGenerator and GeneratedSoundStream are available at


the following links:

https://pschatzmann.github.io/arduino-audio-tools/namespaceaudio__tools.html

https://pschatzmann.github.io/arduino-audio-tools/classaudio__tools_1_1_sine_
wave_generator.html

https://pschatzmann.github.io/arduino-audio-tools/classaudio__tools_1_1_
generated_sound_stream.html

● 198

Practical Audio DSP Projects with the ESP32 - UK.indd 198 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

The sound is generated with 2 bytes (i.e. int16_t). Inside the setup() routine the Serial
Monitor is configured and AudioLogger is started (useful for debugging) so that informa-
tion is displayed on the Serial Monitor. The I2S bus is then configured by specifying the
sample rate, number of channels, amplifier pins, etc. The sine wave is then generated with
the frequency of 2000 Hz using function sineWave().

You should hear the 2 kHz audio sine wave on the speaker.

/****************************************************************
* GENERATE SINEWAVE
* =================
*
* This program uses the audio tools library to generate sinewave
* signal with the frequency of 2 KHz. The generated signal is sent
* to a speaker via an amplifier. Also, a digital oscilloscope is
* used to display the waveform
*
* Author : Dogan Ibrahim
* Program: Sinewave
* Date : April, 2023
**************************************************************/
#include "AudioTools.h"

uint16_t sample_rate=44100;
uint8_t channels = 1;
SineWaveGenerator<int16_t> sineWave(32000); // Amplitude of 32000
GeneratedSoundStream<int16_t> sound(sineWave); // Sine wave
I2SStream out;
StreamCopy copier(out, sound); // Copy sound into i2s

//
// Start Serial Monitor, start AudioLogger, configure I2S, Start sine wave
//
void setup(void)
{
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);

Serial.println("starting I2S...");
auto config = out.defaultConfig(TX_MODE);
config.sample_rate = sample_rate;
config.channels = channels;
config.bits_per_sample = 16;
config.i2s_format = I2S_STD_FORMAT;
config.is_master = true;
config.port_no = 0;

● 199

Practical Audio DSP Projects with the ESP32 - UK.indd 199 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

config.pin_ws = 21; // ws (LRC) pin


config.pin_bck = 4; // BCLK pin
config.pin_data = 22; // DIN pin
config.use_apll = true;
out.begin(config);

//
// Start sine wave
//
sineWave.begin(channels, sample_rate, 2000); // 2 kHz sinewave
Serial.println("Sinewave started...");
}

//
// Copy sound to out
//
void loop()
{
copier.copy();
}

Figure 12.3: Program: Sinewave.

In this project, the output waveform is displayed on an Arduino smartphone using the apps
called Audio Frequency Counter, by keuwlsoft (Figure 12.4). Starting the apps and
placing the Android smartphone near the speaker displays the sound frequency as shown
in Figure 12.5. Clearly, the sound frequency is 2000 Hz.

Figure 12.4: Android apps: Audio Frequency Counter.

● 200

Practical Audio DSP Projects with the ESP32 - UK.indd 200 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Figure 12.5: Displaying the sound frequency.

Figure 12.6 shows the data displayed on the Serial Monitor while the sine wave is gener-
ated.

Figure 12.6: Data on the Serial Monitor.

● 201

Practical Audio DSP Projects with the ESP32 - UK.indd 201 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

12.5 Project 2: Signal input-output with two independent I2S ports


Description: In this project, an external fast ADC and DAC pair (a Pmod I2S2 module)
is used to process signals received from an input. Here, the output signal is a copy of the
input signal as no processing is done by the program. The PCSGU250 function genera-
tor is used to generate the input signal. The output signal is displayed on the PCSGU250
oscilloscope. In this project, two independent I2S ports are used.

The aim: The aim of this project is to show how the Pmod I2S2 can be connected as
two independent I2S ports in ESP32-based signal processing applications.

A Pmod I2S2 device (Figure 12.7) is used as the external interface to the project. This
device includes on-board 24-bit high speed ADC and DAC modules which are used in
this project. An input signal is supplied to the ADC port of this device through a 3.5 mm
blue audio jack. Similarly, the output is taken from the DAC port again through a 3.5
mm green audio jack.

Figure 12.7: The Pmod I2S2.

The Pmod I2S2 takes the analog audio signal as input and outputs analog signal through
a standard 3.5 mm stereo headphone jack (labeled Line Out). An ADC converter is
used to input analog audio signals through a 3.5 mm audio jack (labeled Line In). It is
designed to work at a wide variety of standard audio sampling rates.

The specifications of the Pmod I2S2 are


• Stereo 24-bit ADC and DAC for I2S audio input and output
• Audio input sample rates (double speed mode) up to 108 kHz
• Audio output sample rate up to 200 kHz
• Cirrus CS5343 ADC and CS4344 DAC
• Optional automatic serial clock generation for audio input
• 3.5 mm stereo audio jack connectors
• 12-pin connector with two I2S interfaces
• Manufactured by Digilent
• 25 × 20 × 25 mm
• +3.0 V to +5.25 V operation

● 202

Practical Audio DSP Projects with the ESP32 - UK.indd 202 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Further details are available on the website:

https://digilent.com/reference/pmod/pmodi2s2/reference-manual

The line-in converter can be placed in either Master Mode or Slave Mode by setting mode
jumper JP1 to the corresponding position. The position of this jumper should not be changed
while the Pmod I2S2 is powered on. In Slave Mode, LRCK and SCLK must be generated
by the host board. Supported sample rate ranges and their corresponding MCLK/LRCK and
SCLK/LRCK ratios are provided in Table 12.1 below from the CS5343 datasheet. The line-in
converter automatically selects as needed from single- and double-speed modes:

Jumper JP1state Description


MST Line-in converter Master Mode selected
SLV Line-in converter Slave Mode selected

Table 12.1: Sample rate ranges.

In Master Mode, both LRCK and SCLK are automatically generated by the line-in con-
verter. For Master Mode, the provided MCLK rate must be within the range of 4-54 KHz.
Once the line-in converter has powered up, it automatically selects an MCLK/LRCK ratio of
256×/512× depending on the MCLK rates.

I2S2 has 12 pins. The pin configurations are as in Table 12.2. Pin 1 is marked on the PCB
(see Figure 12.7. Pins run from 1 to 6 on top of the PCB and from 7 to 12 at the bottom,
with pin 7 located under pin 1):

Table 12.2: Pmod I2S2 pin configuration.

● 203

Practical Audio DSP Projects with the ESP32 - UK.indd 203 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Block diagram: Figure 12.8 shows the block diagram of the project, where the input and
output of the Pmod I2S2 are connected to the PCSGU250 combined function generator/
oscilloscope/Bode plotter.

Figure 12.8: Block diagram of the project.

Circuit diagram: The circuit diagram of the project is shown in Figure 12.9.

Figure 12.9: Circuit diagram.

The connections between the Pmod I2S2 and the ESP32 DevKitC are given below. Note that
the master clock (MCLK) must be connected to either GPIO0, GPIO1 or GPIO3:

Pmod I2S2 pin ESP32 DevKitC pin Description


1 GPIO1 (35) D/A MCLK (line out Master Clock)
2 GPIO19 (31) D/A LRCK (line out Word Select)
3 GPIO18 (30) D/A SCLK (line out Serial Clock)

● 204

Practical Audio DSP Projects with the ESP32 - UK.indd 204 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

4 GPIO23 (37) D/A SDIN (line out Data input)


5 GND Power supply ground
6 VCC Power supply +3.3 V
7 GPIO0 (25) A/D MCLK (line in Master Clock)
8 GPIO15 (23) A/D LRCK (line in Word Select)
9 GPIO14 (12) A/D SCLK (line in Serial Clock)
10 GPIO22 (36) A/D SDOUT (line in Serial Data out)
11 GND Power supply ground
12 Power supply +3.3 V

Note: Pin 4 SDIN is data output from ESP32, pin 10 SDOUT is data input to ESP32. A/D
is the input channel side, and D/A is the output channel side.

Program listing: Figure 12.10 shows the program listing (Program: InOut). At the be-
ginning of the program, AudioTools header file is included, sample_rate is set to 10 kHz
(can be changed as you like), bits_per_sample is set to 16, and two streams named in
and out are defined. You then define using StreamCopy that in will be copied to out.
Inside the setup() function, Serial Monitor and the AudioLogger are initialized, and the
input stream (configin) and output stream (configout) of the I2S ports are configured by
specifying the used GPIO ports. Notice that separate GPIO pins are used for the output and
input I2S ports. Pin pin_ws is the LRCK channel and pin_bck is the SCLK channel. Master
clock (pin_mck) is set to 0 (i.e. GPIO0) for the input and to 1 (i.e. GPIO1) for the output
streams. The remainder of the program runs in the loop() function where the in stream is
copied to the out stream.

/******************************************************************
* USING Pmod I2S2 TO INPUT-OUTPUT A SIGNAL
* ========================================
*
* In this program the Pmod I2S2 module is used. Input signal is
* received from the PCSGU250 function generator.The output signal
* is displayed on the PCSGU250 oscilloscope
*
* Author : Dogan Ibrahim
* Program: InOut
* Date : May, 2023
*
* Note: This program is taken from Phil Schatzmann's stream file
* called i2s-i2s-2.ino and has been modified slightly
*****************************************************************/
#include "AudioTools.h"

uint16_t sample_rate=10000;
uint16_t channels = 2;
uint16_t bits_per_sample = 16;
I2SStream in, out;

● 205

Practical Audio DSP Projects with the ESP32 - UK.indd 205 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

StreamCopy copier(out, in);

void setup(void)
{
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);

//
// in stream configuration
//
auto configin = in.defaultConfig(RX_MODE); // RX mode
configin.sample_rate = sample_rate;
configin.channels = channels;
configin.bits_per_sample = bits_per_sample;
configin.i2s_format = I2S_STD_FORMAT;
configin.is_master = true;
configin.port_no = 0;
configin.pin_ws = 15; // LRCK pin
configin.pin_bck = 14; // SCLK pin
configin.pin_data = 22; // Data pin
configin.pin_mck=0; // Master clock
in.begin(configin);

//
// out stream configuration
//
auto configout = out.defaultConfig(TX_MODE); // TX mode
configout.sample_rate = sample_rate;
configout.channels = channels;
configout.bits_per_sample = bits_per_sample;
configout.i2s_format = I2S_STD_FORMAT;
configout.is_master = true;
configout.port_no = 1;
configout.pin_ws = 19; // LRCK pin
configout.pin_bck = 18; // SCLK pin
configout.pin_data = 23; // Data pin
configout.pin_mck=1; // Master clock
out.begin(configout);
}

//
// Copy sound to out
//
void loop()
{

● 206

Practical Audio DSP Projects with the ESP32 - UK.indd 206 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

copier.copy();
}

Figure 12.10: Program: InOut.

Note that the program in Figure 12.10 is taken from Phil Schatzmann's stream file
called i2s-i2s-2.ino and it has been modified slightly. The original program can be found
at the following website:

https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/
examples-stream/streams-i2s-i2s-2/streams-i2s-i2s-2.ino

Figure 12.11 shows the input and output waveforms on the oscilloscope (input is the top
waveform). Note that the output signal is similar to the input signal since the input is sent
directly to the output without any processing. In this example, the input was a sinewave
with the frequency of 200 Hz.

Figure 12.11: Input and output waveforms.

12.6 Project 3: Signal input-output using a shared I2S port


Description: This project is very similar to the previous one, where the output signal is the
same as the input signal. The only difference here is that a shared I2S port is used instead
of two independent I2S ports.

The aim: The aim of this project is to show how the Pmod I2S2 can be connected as a
shared I2S port in ESP32-based signal processing applications.

Circuit diagram: The block diagram of the project is as in Figure 12.8. Figure 12.12 shows
the circuit diagram. Notice that a shared I2S port is used in this project where Pmod I2S2
A/D and D/A pins MCLK, LRCK, and SCLK are shared.

● 207

Practical Audio DSP Projects with the ESP32 - UK.indd 207 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The connections between the Pmod I2S2 and the ESP32 DevKitC are given below:

Pmod I2S2 pin ESP32 DevKitC pin Description


1,7 GPIO0 (25) MCLK (Master Clock)
2,8 GPIO19 (31) LRCK (Word Select)
3,9 GPIO18 (30) SCLK (Serial Clock)
4 GPIO23 (37) D/A SDIN (line out Data input)
5 GND Power supply ground
6 VCC Power supply +3.3 V
10 GPIO22 (36) A/D SDOUT (line in Serial Data out)
11 GND Power supply ground
12 Power supply +3.3 V

Figure 12.12: Circuit diagram of the project.

Program listing: Figure 12.13 shows the program listing (Program: Shared). This pro-
gram is similar to Figure 12.10, but here the I2S port pins are shared. Notice that the I2S
configuration mode is set to RXTX_MODE. The input pin is specified as pin_data_rx and
the output pin simply as pin_data. Here, again, the output waveform is similar to the input
waveform since the input is sent to the output without any processing. In this example,
the sample rate was set to 10 kHz (can be changed if required) and the input was a 200
Hz sinewave.

/****************************************************************
* INPUT-OUTPUT WITH Pmod SHARED PORTS
* ===================================
*
* In this program a Pmod I2S2 module is used. The input signal is
* copied to the output. MCLK, LRCK, SCLK pins of the A/D and D/A
* share the same ESP32 GPIO ports. The data input and output pins

● 208

Practical Audio DSP Projects with the ESP32 - UK.indd 208 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

* are connected to difefrent GPIO ports


*
* Author : Dogan Ibrahim
* Program: Shared
* Date : May, 2023
**************************************************************/
#include "AudioTools.h"

uint16_t sample_rate=10000;
uint8_t channels = 2;
I2SStream in;
StreamCopy copier(in, in);

//
// Configure the input and output streams
//
void setup(void)
{
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);

auto config = in.defaultConfig(RXTX_MODE); // RXTX mode


config.sample_rate = sample_rate; // Sample rate
config.channels = channels;
config.bits_per_sample = 16; // 16 bits
config.i2s_format = I2S_STD_FORMAT; // STD format
config.is_master = true;
config.port_no = 0;
config.pin_ws = 19; // WS (LRCK)
config.pin_bck = 18; // BCK (SCLK)
config.pin_data = 23; // SDIN
config.pin_data_rx = 22; // SDOUT
config.pin_mck = 0; // Master clock
in.begin(config);
}

//
// Copy in stream to output
//
void loop()
{
copier.copy();
}

Figure 12.13: Program: Shared.

● 209

Practical Audio DSP Projects with the ESP32 - UK.indd 209 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

12.7 Project 4: Designing a FIR low-pass digital filter


Description: In this project, a low-pass FIR filter will be designed with the following spec-
ifications:

Window Type: Kaiser


Sampling Frequency: 44100 Hz
Passband Upper Frequency: 1000 Hz
Filter Order: 10 (11 taps)
Pass-band attenuation: 22 dB

The aim: The aim of this project is to show how FIR low-pass filters can be designed using
the ESP32 and the audio tools library. In this project, you will be using the Dr A R Collin's
FIR design program.
The block diagram and circuit diagram of the project are in Figure 12.8 and Figure 12.9
respectively, except that CH2 of the PCSGU250 is not used and CH1 is connected to the
output of the Pmod I2S2 (green plug).

PCSGU250 generates sine wave signals with varying frequencies at the ADC input of the
Pmod I2S2 ADC/DAC module. At the same time, the signals at the DAC output of Pmod are
plotted in real-time by the Bode plotter of the PCSGU250 device.

Calculating the filter coefficients with Scope FIR


The specifications of the filter are entered into the program and CALCULATE FILTER
button is clicked (Figure 12.14). The filter frequency and impulse responses and the list of
coefficients are shown in the Figure. Note that the filter frequency response is plotted on a
linear frequency scale from 0 to about 22 kHz (half the sampling time).

Figure 12.14: Enter the specifications of the filter.

The coefficients are calculated to be as in Figure 12.15.

● 210

Practical Audio DSP Projects with the ESP32 - UK.indd 210 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Figure 12.15: Coefficients of the filter.

The coefficients can be written as follows. You can see the symmetry in the coefficients:

h[0] = h[10] = 0.037388


h[1] = h[9] = 0.040120
h[2] = h[8] = 0.042348
h[3] = h[7] = 0.043997
h[4] = h[6] = 0.045010
h[5] = 0.045351

Implementing the FIR filter


The filter is implemented using the Direct form of realization (see Chapter 10). The struc-
ture of the filter to be designed is shown in Figure 12.16 with N = 10, having 11 taps.

● 211

Practical Audio DSP Projects with the ESP32 - UK.indd 211 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 12.16: Structure of the FIR filter.

Program Listing: The Arduino Audio Tools library is used in this project. The program is
called FIR1.C and its listing is shown in Figure 12.17. At the beginning of the program, the
sample time is set to 44100 Hz and the 11 filter coefficients are defined in a floating point
array called Coefficients:

float Coefficients[] =
{
0.037388,
0.040120,
0.042348,
0.043997,
0.045010,
0.045351,
0.045010,
0.043997,
0.042348,
0.040120,
0.037388
};

Inside the setup() function the filter is defined as FIR, and the input and output streams
are configured with the GPIO port numbers of the ESP32 DevKitC.

● 212

Practical Audio DSP Projects with the ESP32 - UK.indd 212 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

/****************************************************************
* FIR LOW-PASS FILTER
* ===================
*
* This is the FIR low-pass filter program using the Pmod I2S2
* module as the ADC/DAC. The specifications of the filter are:
*
* Window Type: Kaiser
* Sampling Frequency: 44100 Hz
* Passband Upper Frequency: 1000 Hz
* Filter Order: 10 (11 taps)
* Pass-band attenuation: 22 dB
*
* Author : Dogan Ibrahim
* Program: FIR1
* Date : May, 2023
**************************************************************/
#include "AudioTools.h"

uint16_t sample_rate=44100;
uint8_t channels = 1;
I2SStream in,out;
FilteredStream <int16_t, float> FIR_Filter(in, channels);
StreamCopy copier(out, FIR_Filter);

//
// FIR low-pass filter coefficients
//
float Coefficients[] =
{
0.037388,
0.040120,
0.042348,
0.043997,
0.045010,
0.045351,
0.045010,
0.043997,
0.042348,
0.040120,
0.037388
};

void setup(void)
{
Serial.begin(115200);

● 213

Practical Audio DSP Projects with the ESP32 - UK.indd 213 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

AudioLogger::instance().begin(Serial, AudioLogger::Info);

FIR_Filter.setFilter(0, new FIR<float>(Coefficients));

//
// Configure out stream
//
auto configout = out.defaultConfig(TX_MODE);
configout.sample_rate = sample_rate;
configout.channels = channels;
configout.bits_per_sample = 16;
configout.i2s_format = I2S_STD_FORMAT;
configout.is_master = true;
configout.port_no = 1;
configout.pin_ws = 19; // LRCK
configout.pin_bck = 18; // SCLK
configout.pin_data = 23; // SDOUT
configout.pin_mck = 1;
out.begin(configout);

//
// Configure in stream
//
auto configin = in.defaultConfig(RX_MODE);
configin.sample_rate = sample_rate;
configin.channels = channels;
configin.bits_per_sample = 16;
configin.i2s_format = I2S_STD_FORMAT;
configin.is_master = true;
configin.port_no = 0;
configin.pin_ws = 15; // LRCK
configin.pin_bck = 14; // SCLK
configin.pin_data = 22; // SDOUT
configin.pin_mck = 0;
in.begin(configin);
}

//
// Copy filtered signal to out
//
void loop()
{
copier.copy();
}

Figure 12.17: Program: FIR1.

● 214

Practical Audio DSP Projects with the ESP32 - UK.indd 214 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Figure 12.18 shows the frequency response obtained from the designed filter. Notice in this
figure that the frequency axis is linear.

Figure 12.18: Frequency response of the designed filter.

The instructions to plot the frequency response using the PCSGU250 device are as follows:

• Connect the PCSGU250 function generator output to the input of the Pmod
I2S2 module (blue jack connector).

• Connect the output of the filter (green jack connector of I2S2) to CH1 of the
PCSGU250.

• Connect the PCSGU250 device to the USB port of your PC and power it up

• Start the PCSGU250 software (PcLab 200LT).

• Click the Circuit Analyzer button.

• Click the Start button to draw the frequency response (you may have to adjust
the horizontal and vertical axes scale factors). In this project, the vertical axis
was set to 5 dB/div, the frequency range set to 100 Hz to 100 kHz, and the
signal amplitude was set to 1.6 V on the oscilloscope function generator.

The PCSGU250 device may not give an accurate graph in the stop-band if the input signal
is very small as may be the case in the stop-band of low-pass filters.

12.8 Project 5: Design of a FIR band-pass filter


Description: An example of designing a band-pass filter is given in this section. The filter
specifications are as follows:

Filter type: Simple Parks-McClellan


Sampling frequency: 44100 Hz

● 215

Practical Audio DSP Projects with the ESP32 - UK.indd 215 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Passband bandwidth at top: 8000 Hz


Passband bandwidth at bottom: 9000 Hz
Filter Order: 10 (11 taps)
Stopband attenuation: 30 dB

The aim: The aim of this project is to show how FIR band-pass filters can be designed
using the ESP32 and the audio tools library. In this project, you will be using the ScopeFIR
filter design package to get the filter coefficients.

The block diagram and circuit diagram of the project are in Figure 12.8 and Figure 12.9,
respectively.

Figure 12.19 shows the filter specifications entered into the program. The theoretical fre-
quency response and the filter coefficients are displayed in the figure.

Figure 12.19: Entering the filter specifications.

The filter coefficients are shown in Figure 12.20.

● 216

Practical Audio DSP Projects with the ESP32 - UK.indd 216 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Figure 12.20: The filter coefficients.

The same program as in Figure 12.17 is used to design the band-pass filter but the filter
coefficients were changed for the band-pass filter. Figure 12.21 shows the frequency re-
sponse of the designed filter, plotted using the PCSU250 function generator/Bode plotter.

Figure 12.21: Frequency response of the designed filter.

12.9 Project 6: Design of a FIR high-pass filter


Description: The high-pass filter to be designed has the following specifications:

Window Type: Keiser


Sampling Frequency: 44100 Hz
Pass-band lower frequency: 1000 Hz
Stop-band attenuation: 22 dB
Filter Order: 10 (11 taps)

The aim: The aim of this project is to show how FIR high-pass filters can be designed using
the ESP32 and the audio tools library. In this project, you will be using the Dr AR Collin's
FIR design program.

The block diagram and circuit diagram of the project are as in Figure 12.8 and Figure 12.9,
respectively.

● 217

Practical Audio DSP Projects with the ESP32 - UK.indd 217 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 12.22 shows the filter specifications entered into the program. Clicking the CALCU-
LATE FILTER button displays the frequency response, impulse response and lists the filter
coefficients.

Figure 12.22: Entering the filter specifications.

The filter coefficients are shown in Figure 12.23.

Figure 12.23: The filter coefficients.

The same program as in Figure 12.17 is used to design the high-pass filter but the filter
coefficients were changed for the high-pass filter. This is left as an exercise to the readers.

12.10 Design of FIR digital filters from the first principles (without
using a library)
In the previous FIR filter design examples, you have used the Arduino Audio Tools library.
In this section, you will be designing FIR filters without using a library. Here, you will be
using the ESP32 on-chip ADC and DAC converters. It is important to realize that the ESP32
on-chip ADC and DAC converters have very low specifications, and they can only be used in
very low audio DSP applications. The on-chip ADC is 12-bit wide, while the on-chip DAC is

● 218

Practical Audio DSP Projects with the ESP32 - UK.indd 218 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

only 8-bit wide. As a result, the output waveform will not be very accurate representation
if standard 16-bit converters were to be used. But the main aim is here to show FIR filter-
ing can be done using the first principles, without a library. More accurate results can be
obtained by using fast 16-bit external ADC and DAC converters. Additionally, both the ADC
and the DAC are unipolar and they do not accept negative going data. But the sinewave
input has both positive and negative half cycles. The input waveform can be shifted up so
that it is always positive. Modifying the design given in this section to use fast external ADC
and DAC converters should be very easy as it involves modifying the input and output parts
of the hardware and the program.

Designing FIR filters from the first principles requires the use of a timer interrupt of the
ESP32 processor. The operation of the program is such that a timer interrupt is configured
to generate interrupts at the required sample times of the filter. Inside the interrupt service
routine (ISR) data is read from the ADC, processed, and then output to the DAC. Figure
12.24 shows the operation of the program as a PDL (Program Description Language).

BEGIN/MAIN
Configure timer interrupt at the filter sampling time
Store filter coefficients in an array
Configure ADC and DAC
Wait for timer interrupts (ISR)
END/MAIN

BEGIN/ISR
Read a new sample from ADC
Calculate the output sample
Send the output sample to the DAC
Delay the input signals by one sample time
END/TMR

Figure 12.24: Operation of the filter program.

Before writing the filter program, it is worthwhile to review the ESP32 timers and timer
interrupts.

12.10.1 ESP32 timers and timer interrupts


The ESP32 processor has two hardware timer groups, each group having two general-pur-
pose hardware timers. One of the groups has timers Timer_0 and Timer_2 while the other
group has timers Timer_1 and Timer_3. All the timers are 64-bit, based on using 16-bit
prescalers and 64-bit up/down counters with auto-reload features. Prescalers are used for
dividing the base clock frequency (usually 80 MHz) and the divided frequency increments
or decrements a timer counter. The prescalers are 16-bit, and therefore they can divide the
80 MHz clock frequency from 2 to 65535.

● 219

Practical Audio DSP Projects with the ESP32 - UK.indd 219 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

A timer can trigger an alarm when the timer value matches a preset value. When this
happens, the timer will auto-reload to zero and it will trigger a timer interrupt (if enabled).

The timer speed can be determined using the following formula:

Timer speed in MHz = Timer clock speed (MHz) / prescaler value

As an example, with a prescaler value of 80 and a clock frequency of 80 MHz, the timer
speed will be 1 MHz.

The steps to configure a timer to generate timer interrupts are as follows:

Step 1: Initialize the timer:

Timer = timerBegin(0, prescaler, true);

For example,

Timer = timerBegin(0, 80, true);

This function has 3 arguments: The first argument is the timer number (0 to 3), the second
argument is the prescaler value which can have values 2 to 65535. In the above exam-
ple, it is set to 80 so that the timer will count from 0 to 1,000,000 in one second. i.e. each
count will take 1 microsecond. The last argument is a flag where true counts UP and false
counts DOWN.

Step 2: Attach the timer interrupt to a function:

timerAttachInterrupt(Timer, &ISR, true);

This function has 3 arguments: the first argument is the pointer as defined in Step 1.
The second argument is the function to be called when the timer interrupt occurs. Note
that the interrupt service routine function cannot have any arguments and it should have
the IRAM_ATTR keyword. When you use the IRAM_ATTR attribute, the compiled code is
placed in the ESP32's Internal RAM (IRAM). Otherwise, the code is kept in Flash memory.
The Flash memory on ESP32 is much slower than internal RAM. If the code you want to run
is an Interrupt Service Routine (ISR), you generally want to execute it as soon as possible.
If you had to wait for the ISR to load from the Flash memory, then the ISR routine could be
very slow. The third argument is a flag set to true to enable the auto-reload.

Step 3: Timer match value


You have to load a value into the timer for which an interrupt will be generated. This is done
using the following function:

timerAlarmWrite(Timer, cnt, true);

● 220

Practical Audio DSP Projects with the ESP32 - UK.indd 220 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

for example,

timerAlarmWrite(Timer, 1000000, true);


This function has 3 arguments: The first argument is the timer pointer as described in
Step 1. The second argument, cnt, is the value that the counter will count up to before
it generates an interrupt. Cnt is a 64-bit integer variable. For example, as above, if you
are specifying a value of 1,000,000 then the timer will count from 0 to 999,999 and then
to 1,000,000 and an interrupt will be generated at this point because the timer value will
match the specified value. If the prescaler was set to 80 so that the clock is 1 microsecond,
it will take 1 microsecond × 1,000,000 or 1 second for a timer interrupt to be generated.

Step 4: Enable the timer interrupt


The following function is used to enable timer interrupts:

timerAlarmEnable(Timer);

where Timer is the pointer as in Step 1.

What you are interested to practice is calculating the value to be loaded into the prescaler
in Step 1 and into variable cnt in Step 3 for a required timer interrupt time. This can be
calculated using the following formula:

f (Hz) = Timer clock speed (Hz) / (prescaler * cnt)


T (seconds) = prescaler * cnt / Timer clock speed (Hz)

or,
prescaler * cnt = Timer clock speed (Hz) * T (seconds)

assuming a clock speed of 80 MHz.

prescaler * cnt = 80,000,000 * T (seconds)

Here, you can choose a value for the prescaler and then calculate the required value of cnt.
Assuming a prescaler value of 80, you have:

cnt = 80,000,000 * T / 80

or
cnt = 1,000,000 * T (seconds)

For example, for a 1-second timer interrupt, you can set cnt as: cnt = 1,000,000. Similarly,
for 1-millisecond timer interrupt you can set cnt as: cnt = 1,000,000 * 0.001 = 1000

The variable manipulated in the interrupt ISR function should be declared with the volatile
keyword.

● 221

Practical Audio DSP Projects with the ESP32 - UK.indd 221 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Some other timer interrupt related functions that may be useful are (see website for the
full list: https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/
api/timer.html):

timerGetConfig: get initialized timer configuration


timerSetConfig: configure timer
timerDetachInterrupt: detach interrupt from timer
timerStart: start the counter of the timer
timerStop: stop the counter of the timer
timerWrite: set the timer counter value
timerSetDivider: set the divider value
timerSetCountUp: configure the counting direction
timerAlarmDisable: disable timer alarm events

A simple example project is given in the next section to show how timer interrupts can be
generated every second and how an LED connected to a GPIO port can be flashed every
second inside the ISR.

12.10.2 Project 7: Flashing an LED using timer interrupts


Description: In this project, an LED is connected to port GPIO23 and this LED is flashed
every second inside a timer interrupt service routine.

The aim: The aim of this project is to show how the timer interrupt can be used in a simple
project.

The block diagram and circuit diagram of the project are as in Figure 4.11 and Figure 4.12,
respectively. The LED is connected to port GPIO23 through a current-limiting resistor.

Program listing: Figure 12.25 shows the program listing (Program: TimerInt). At the be-
ginning of the program, LED is assigned to port GPIO23, and a pointer is created to variable
the named My_timer of type hw_timer_t. Inside the setup routine, the LED port is con-
figured as an output and timer 0 is configured to generated interrupts at every second with
the callback function ISR. The timer is configured with a prescaler value of 80 and a count
value of 1,000,000. Inside the interrupt service routine, the state of the LED is changed.

/****************************************************************
* FLASHING LED IN ISR
* ===================
*
* In this program an LED is connectec to port GPIO23 through a
* current limiting resistor. The LED flashed every second inside
* a timer interrupt service routine called ISR
*
* Program: TimerInt
* Date : May, 2023
**************************************************************/

● 222

Practical Audio DSP Projects with the ESP32 - UK.indd 222 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

#define LED 23
hw_timer_t *My_timer = NULL;

void IRAM_ATTR ISR()


{
digitalWrite(LED, !digitalRead(LED));
}

//
// Configure timer 0, prscaler=80, UP count, timer interrupts at
// every second, attach interrupt, callback function ISR
//
void setup()
{
pinMode(LED, OUTPUT);
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &ISR, true);
timerAlarmWrite(My_timer, 1000000, true);
timerAlarmEnable(My_timer);
}

void loop()
{
}

Figure 12.25: Program: TimerInt.

12.10.3 Project 8: Timer interrupt-driven FIR low-pass filter program


Description: Now that you have learned how to generate timer interrupts, it is time to
write the filter program. The filter will be designed with the following specifications:

Window Type: Simple Parks-McClellan


Sampling Frequency: 1000 Hz
Passband Upper Frequency: 100 Hz
Passband Lower frequency: 150 Hz
Filter Order: 10 (11 taps)
Pass-band attenuation: 30 dB

Using ScopeFIR filter design program (you can use any other design program if you wish),
the specifications of the filter to be designed is shown in Figure 12.26.

● 223

Practical Audio DSP Projects with the ESP32 - UK.indd 223 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 12.26: Specifications of the filter.

The filter coefficients are found to be:

float h[N+1]= {-0.0613461, 0.0476723, 0.105628, 0.1775189, 0.236046, 0.258520,


0.236046, 0.177518, 0.105628, 0.047672, -0.0613461};

The filter will be implemented using the Direct form of realization (see Chapter 10). The
structure of the filter to be designed has N = 10, having 11 taps.

Circuit diagram: Figure 12.27 shows the circuit diagram. An analog input signal is ap-
plied to analog input GPIO34 (ADC1_CH6). The analog output is taken from port GPIO25
(DAC_CH_1).

Figure 12.27: Circuit diagram of the project.

● 224

Practical Audio DSP Projects with the ESP32 - UK.indd 224 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Program listing: Figure 12.28 shows the program listing (Program: FIRInt). At the be-
ginning of the program, the 11 filter coefficients are stored in a floating-point array called
h. Inside the setup() function timer 0 is initialized to generate interrupts at every millisec-
ond (1000 Hz sampling time). Timer 0 prescaler is set to 80 and the counter value is set
to 1000 as described earlier in Section 12.10.1. The timer callback function is named ISR.
This function is called every millisecond. Here, a new input sample is read by the ADC, the
FIR algorithm is applied, and the output is sent to DAC.

The ADC on the ESP32 processor is 12-bits wide, having a range of 0 to 4095. The DAC on
the other hand is only 8-bits wide, having a range of 0 to 255. The map statement is used
to map the received 0 to 4095 into 0 to 255 before the received samples are processed.
Also, the ADC and DAC are unipolar and they do not accept negative data. Because of this,
the input data was shifted up so that it is always positive.

/****************************************************************
* FIR FILTER DESIGN FROM FIRST PRINCIPLES
* =======================================
*
* This is an FIR filter design program. The program is developed
* from first principles and does not use any filter design library
* Timer interrupt is used to read and process the input samples.
* Analog input ADC1_CH6 (GPIO34) is used.
* DAC channel used is DAC_CH_1 (GPIO25).
*
* Program: FIRInt
* Date : May, 2023
* Author : Dogan Ibrahim
**************************************************************/
#define N 10 //Filter order=10,11 taps
#define ADC 34 // ADC channel
#define DAC 25 // DAC channel
hw_timer_t *My_timer = NULL; // Timer pointer

//
// Filter coefficients
//
float h[N+1]={-0.0613461,0.0476723,0.105628,0.1775189,
0.236046,0.258520,0.236046,0.177518,0.105628,0.047672,-0.0613461};

float yN, x[N];


int i, AnalogIn = 0;

//
// Timer interrupt service routine. Program jumps here
// every 1 ms (sampling time = 1 kHz)
//

● 225

Practical Audio DSP Projects with the ESP32 - UK.indd 225 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

void IRAM_ATTR ISR()


{
AnalogIn = analogRead(ADC);
AnalogIn = map(AnalogIn,0,4095,0,255);
x[0] = AnalogIn;
yN = 0.0;
//
// Calculate a new output yn
//
for(i = 0; i <= N; i++)
{
yN = yN + h[i] * x[i];
}
//
// Output the new sample via the DAC
//
dacWrite(DAC, (byte)yN);
//
// Shift the input samples for teh delay action
//
for(i = 0; i < N; i++)
{
x[N-i] = x[N-i-1];
}
}

//
// Configure timer 0 to interrupt at every 1 ms
// Prescaler is set to 80, counter is set to 1000
//
void setup()
{
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &ISR, true); // Attach interrupt
timerAlarmWrite(My_timer, 1000, true); // 1 msec.
timerAlarmEnable(My_timer); // Enable Timer
}

//
// Do nothing, wait for timer interrupts
//
void loop()
{
}

Figure 12.28: Program: FIRInt.

● 226

Practical Audio DSP Projects with the ESP32 - UK.indd 226 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

Figure 12.29 shows the frequency response of the designed filter.

Figure 12.29: Frequency response of the designed filter.

12.10.4 More efficient FIR digital filter program


In this section, you will be designing an FIR digital filter using a more efficient algorithm.
Shifting of the input samples in the program given in Figure 12.28 can result in a large
number of bytes being moved in memory and as a result excessive time can be wasted by
this operation. In this algorithm, you will be using a circular buffer to store the input sample
values and then simply change a pointer to access the data elements instead of actually
moving the data in memory.

This method is explained in most DSP books, and the basic operation is explained below by
considering a 3rd-order filter. Figure 12.30 shows a 3rd-order FIR filter where A, B, C and D
are the tapping points. The operations performed are summarized below:

Figure 12.30: 3rd-order FIR filter.

Stage 1:

Where x[0] is where the last input sample is stored.

● 227

Practical Audio DSP Projects with the ESP32 - UK.indd 227 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

After the output, shift the input values so that:

where new1 is the new sample stored in tapping point A.

Stage 2:

After the output, shift the input values so that:

where new2 is the new sample stored in tapping point A.

Stage 3:

After the output, shift the input values so that:

where new3 is the new sample stored in tapping point A.

Stage 4:

After the output, shift the input values so that:

where new4 is the new sample stored in tapping point A.

Stage 5:

and the above process repeats forever.

The important point to notice here is that the input sample is always multiplied by h0 and
the input values are shifted right by one sample time.

Figure 12.31 shows the filter operation where the variables multiplied by each other are
shown with arrows. On close examination of this figure, it is clear that the filtering operation
can be conducted by making the input array x to be a circular array. The last input samples
are always loaded into the array location which is not needed for the next calculation and
the input array pointer moves up as new samples are received. At the same time, the array
pointer moves down to conduct the multiplication with the filter coefficients.

● 228

Practical Audio DSP Projects with the ESP32 - UK.indd 228 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

The required operations inside the ISR are described by the following PDL. Notice here that
a round bracket means the contents of the array pointed to by the corresponding pointer.
The input pointer (i_pointer) and the x-array pointer (x_pointer) are initialized outside the
ISR:

y = 0
Input to x[i_pointer]
DO for all taps
y = y + h[i] * (x_pointer)
Increment x_pointer and wrap around if > N
ENDDO
Output y to DAC converter
Decrement i_pointer and wrap around if < 0

Figure 12.31 Schematic representation of the operations.

You will be designing a high-pass filter now as described in the next section using the new
algorithm.

12.10.5 Project 9: An efficient FIR low-pass filter


Description: The band-pass filter to be designed has the following specifications:

Filter type: Simple Parks-McClellan


Sampling frequency: 1000 Hz
Passband upper frequency: 200 Hz
Passband lower frequency: 250 Hz
Filter Order: 20 (11 taps)
Stopband attenuation: 20 dB

● 229

Practical Audio DSP Projects with the ESP32 - UK.indd 229 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The ScopeFIR program was used to obtain the filter coefficients and the frequency re-
sponse. The frequency response of the filter is shown in Figure 12.32. The filter coefficients
are shown in Figure 12.33.

Figure 12.32: Frequency response of the filter.

Figure 12.33: Filter coefficients.

● 230

Practical Audio DSP Projects with the ESP32 - UK.indd 230 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

The filter coefficients are:

h[0] = h[20] = 0.0249468


h[1] = h[19] = 0.0239936
h[2] = h[18] = -0.0429125
h[3] = h[17] = -0.0104958
h[4] = h[16] = 0.0312610
h[5] = h[15] = 0.0448283
h[6] = h[14] = -0.0430474
h[7] = h[13] = -0.0915298
h[8] = h[12] = 0.0451578
h[9] = h[11]= 0.3139042
h[10] = 0.452620

Program Listing: The program listing is shown in Figure 12.34 (Program: FIRCircular).
Most of the code is similar to the one in Figure 12.28, but here a circular buffer is used for
the input samples. The filtering operation is implemented by the following code:

for(i = 0; i <= N; i++)


{
yN = yN + h[i]*x[x_pointer];
if(++x_pointer > N)x_pointer = 0;
}
i_pointer--;
if(i_pointer < 0)i_pointer = N;

Here, as mentioned earlier, the x_pointer moves down to access the next input sample,
while new input samples are loaded into the array location pointed to by i_pointer.

/****************************************************************
* FIR FILTER DESIGN FROM FIRST PRINCIPLES
* =======================================
*
* This is an FIR filter design program. The program is developed
* from first principles and does not use any filter design library
* Timer interrupt is used to read and process the input samples.
* Analog input ADC1_CH6 (GPIO34) is used.
* DAC channel used is DAC_CH_1 (GPIO25).
*
* This is more efficient algorithm
*
* Program: FIRCircular
* Date : May, 2023
* Author : Dogan Ibrahim
**************************************************************/

● 231

Practical Audio DSP Projects with the ESP32 - UK.indd 231 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

#define N 20 //Filter order=20,21 taps


#define ADC 34 // ADC channel
#define DAC 25 // DAC channel
hw_timer_t *My_timer = NULL; // Timer pointer

//
// Filter coefficients
//
float h[N+1]={0.02494684, 0.02399362, -0.04291250, -0.01049585,
0.03126108, 0.04482837, -0.04304749, -0.09152983,
0.04515781, 0.31390420, 0.45262051, 0.31390420,
0.04515781,-0.09152983, -0.04304749, 0.04482837,
0.03126108,-0.01049585, -0.04291250, 0.02399362,
0.02494684};

float yN, x[N];


int i, AnalogIn = 0;
signed char i_pointer = 0;
signed char x_pointer = 0;

//
// Timer interrupt service routine. Program jumps here
// every 1 ms (sampling time = 1 kHz)
//
void IRAM_ATTR ISR()
{
AnalogIn = analogRead(ADC);
AnalogIn = map(AnalogIn,0,4095,0,255);
x[i_pointer] = AnalogIn;
yN = 0.0;

//
// Calculate a new output yn. This process will also shift the
// input samples as required so that there is no need to move
// the samples around in memory. Index x_pointer is used as the
// pointer and the pointer is initialized outside the loop
//
x_pointer = i_pointer;
//
// Calculate a new output yn
//
for(i = 0; i <= N; i++)
{
yN = yN + h[i] * x[x_pointer];
if(++x_pointer > N)x_pointer = 0;
}

● 232

Practical Audio DSP Projects with the ESP32 - UK.indd 232 06-07-2023 10:40
Chapter 12 • Designing FIR Digital Filters with the ESP32 DevKitC

i_pointer--;
if(i_pointer < 0)i_pointer = N;

//
// Output the new sample via the DAC
//
dacWrite(DAC, (byte)yN);
}

//
// Configure timer 0 to interrupt at every 1 ms
// Prescaler is set to 80, counter is set to 1000
//
void setup()
{
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &ISR, true); // Attach interrupt
timerAlarmWrite(My_timer, 1000, true); // 1 msec. interrupts
timerAlarmEnable(My_timer); // Enable Timer
}

//
// Do nothing, wait for timer interrupts
//
void loop()
{
}

Figure 12.34: Program: FIRCircular.

The frequency response of the designed filter as plotted by the PCSGU250 and is shown in
Figure 12.35.

● 233

Practical Audio DSP Projects with the ESP32 - UK.indd 233 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 12.35: Frequency response of the designed filter.

Notice that the overall filter performance could be improved by using faster ADC and DAC
converters having at least 16-bits word sizes. Figure 12.36 shows the output waveform
from the filter, which is very noisy because of the 8-bit DAC converter.

Figure 12.36: Filter output waveform.

● 234

Practical Audio DSP Projects with the ESP32 - UK.indd 234 06-07-2023 10:40
Chapter 13 • Designing IIR Digital Filters with the ESP32 DevKitC

Chapter 13 • D
 esigning IIR Digital Filters with the
ESP32 DevKitC

13.1 Overview
In this chapter, you will be looking at the design of IIR digital filters using the ESP32
DevKitC. The filter coefficients will be obtained using one of the methods described in earli-
er chapters. The actual physical filter will be realized using the Arduino Audio Tools library.
The frequency response of the designed filter will be plotted in real-time using the Velleman
PCSGU250 plotter device, as has been described in Chapter 12.

Several IIR-type digital filter design examples are given in this chapter, including low-pass
and band-pass filters.

13.2 Project 1: Design of an IIR low-pass filter


Description: The specifications of the low-pass filter to be designed are as follows:

Filter type: Butterworth


Sampling frequency: 1000 Hz
Cut-off frequency: 100 Hz
Filter order: 2

The aim: The aim of this project is to show how an IIR-type Butterworth low-pass filter can
be designed using the ESP32 DevKitC development board.

Design: In this design, the filter coefficients were obtained as described in Chapter 11,
Example 11.2. Here, the filter transfer function was found to be:

0.067 + 0.135 z −1 + 0.067 z −2


H ( z) =
1 − 1.1429 z −1 + 0.4127 z − 2

With these filter coefficients:

(0)=0. 067
b(1)=0.135
b(2)=0.067
a(0)=1
a(1)=−1.1429
a(2)=0.4127

In a cascade implementation, the general z-transform of a second-order section (biquad)


is as follows (Figure 13.1):

● 235

Practical Audio DSP Projects with the ESP32 - UK.indd 235 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

b0 + b1 z −1 + b2 z −2
H ( z) =
1 + a1 z −1 + a2 z −2

Figure 13.1: Cascade implementation.

The block diagram and circuit diagram of the filter are in Figure 12.8 and Figure 12.9, re-
spectively.

Program listing: Arduino Audio Tools library is used in this program. Figure 13.2 shows
the filter program (Program: IIR1). At the beginning of the program, the input and out-
put streams are defined, and the filter coefficients are stored in two floating-point arrays
b_coefficients and a_coefficients. Filter coefficients are stored in these two arrays in the
forms b0, b1, b2, b3, b4, etc, and as a0, a1, a2, a3, a4, etc. Inside the setup() function,
the IIR filter is defined, input and output I2S interface is defined for the ESP32 GPIO ports.

/****************************************************************
* IIR LOW-PASS FILTER
* ===================
*
* This is the IIR low-pass filter program using the Pmod I2S2
* module as the ADC/DAC. The specifications of the filter are:
*
* Window Type: Butterworth
* Sampling Frequency: 1000 Hz
* Passband Upper Frequency: 100 Hz
* Filter Order: 2
*
* Author : Dogan Ibrahim
* Program: IIR1
* Date : May, 2023
**************************************************************/
#include "AudioTools.h"

uint16_t sample_rate=1000;
uint8_t channels = 1;
I2SStream in,out;
FilteredStream <int16_t, float> IIR_Filter(in, channels);
StreamCopy copier(out, IIR_Filter);

● 236

Practical Audio DSP Projects with the ESP32 - UK.indd 236 06-07-2023 10:40
Chapter 13 • Designing IIR Digital Filters with the ESP32 DevKitC

//
// IIR low-pass filter coefficients
//
const float b_coefficients[]={0.067,0.135, 0.067};
const float a_coefficients[]={1.0,-1.1429,0.4127};

void setup(void)
{
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);

IIR_Filter.setFilter(0, new IIR<float>(b_coefficients, a_coefficients));

//
// Configure out stream
//
auto configout = out.defaultConfig(TX_MODE);
configout.sample_rate = sample_rate;
configout.channels = channels;
configout.bits_per_sample = 16;
configout.i2s_format = I2S_STD_FORMAT;
configout.is_master = true;
configout.port_no = 1;
configout.pin_ws = 19; // LRCK
configout.pin_bck = 18; // SCLK
configout.pin_data = 23; // SDOUT
configout.pin_mck = 1;
out.begin(configout);

//
// Configure in stream
//
auto configin = in.defaultConfig(RX_MODE);
configin.sample_rate = sample_rate;
configin.channels = channels;
configin.bits_per_sample = 16;
configin.i2s_format = I2S_STD_FORMAT;
configin.is_master = true;
configin.port_no = 0;
configin.pin_ws = 15; // LRCK
configin.pin_bck = 14; // SCLK
configin.pin_data = 22; // SDOUT
configin.pin_mck = 0;
in.begin(configin);
}

● 237

Practical Audio DSP Projects with the ESP32 - UK.indd 237 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

//
// Copy filtered signal to out
//
void loop()
{
copier.copy();
}

Figure 13.2: Program: IIR1.

Figure 13.3 shows the frequency response of the designed filter, plotted in real-time using
the PCSGU250 device, as described in Chapter 12.

Figure 13.3: Frequency response of the filter.

13.3 IIR filters of any order


In general, any even order filter can be made by combining the second-order sections, and
any odd order filter can be made by combining the second-order sections and a first-order
section.

The z-transform of a first-order section is:

b0 + b1 z −1
H ( z) =
1 + a1 z −1
The above transfer function can be implemented in cascade form as shown in Figure 13.4.

● 238

Practical Audio DSP Projects with the ESP32 - UK.indd 238 06-07-2023 10:40
Chapter 13 • Designing IIR Digital Filters with the ESP32 DevKitC

Figure 13.4: First-order IIR filter.

13.4 Design of IIR filters without using a filter library


In this section, you will learn to design IIR filters from the first principles, without using a
filter library. The on-chip ADC and DAC converters of the ESP32 are used in this section.
The ADC converter is 12-bits wide and the DAC is only 8-bits wide. Also, the sampling rate
of these converters is very low. These converters, however, can be replaced with external
fast ones with some small changes in the program given in this section.

13.4.1 The IIR filter algorithm


The algorithm for a second-order section can easily be derived with reference to Figure
13.1. Let x1 and x2 be the two states of the filter and G be the gain as shown in the figure.
You can then write the following equations:

x1 = r.z-1
x2 = x1.z-1
r = xn – a1.x1 – a2.x2
yn = r.b0 + b1.x1 + b2.x2

The filter operations are then performed inside the interrupt service routine as shown in
the following steps:

• Get a new sample xn via ADC converter


• Calculate r, where r = xn – a1.x1 – a2.x2
• Calculate yn, where yn = r.b0 + b1.x1 + b2.x2
• Output yn to DAC converter
• Delay the current sample, x2 = x1 and x1 = r

An example design is given below.

13.4.2 Project 2: Design of IIR low-pass filter from the first principles
Description: A low-pass IIR filter with the same specifications as in the previous project
is used here. i.e.:

Filter type: Butterworth


Sampling frequency: 1000 Hz
Cut-off frequency: 100 Hz
Filter order: 2

● 239

Practical Audio DSP Projects with the ESP32 - UK.indd 239 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

The aim: The aim of this project is to show how an IIR-type Butterworth low-pass filter can
be designed from the first principles without using a filter library.

The circuit diagram of the filter is the same as in Figure12.27.

Program listing: Figure 13.5 shows the program listing (Program: IIRInt). At the begin-
ning of the program, the filter coefficients are defined. The timer is configured to generate
interrupts every milliseconds, so that the sampling time is 1000 Hz. Inside the interrupt
service routine, the IIR filter algorithm is implemented. Notice that since the ADC range is
0 to 4095 and the DAC range is 0 to 255, a map statement is used to map the ADC to the
DAC range.

/****************************************************************
* IIR FILTER DESIGN FROM FIRST PRINCIPLES
* =======================================
*
* This is an IIR filter design program. The program is developed
* from first principles and does not use any filter design library
* Timer interrupt is used to read and process the input samples.
* Analog input ADC1_CH6 (GPIO34) is used.
* DAC channel used is DAC_CH_1 (GPIO25).
*
* Program: IIRInt
* Date : May, 2023
* Author : Dogan Ibrahim
**************************************************************/
#define ADC 34 // ADC channel
#define DAC 25 // DAC channel
hw_timer_t *My_timer = NULL; // Timer pointer

//
// Filter coefficients
//
float IIR_b0 = 0.067;
float IIR_b1 = 0.135;
float IIR_b2 = 0.067;
float IIR_a1 = -1.1429;
float IIR_a2 = 0.4127;

float IIR_x1, IIR_x2, IIR_r, IIR_yn;


int i, AnalogIn = 0;

//
// Timer interrupt service routine. Program jumps here
// every 1 ms (sampling time = 1 kHz)
//

● 240

Practical Audio DSP Projects with the ESP32 - UK.indd 240 06-07-2023 10:40
Chapter 13 • Designing IIR Digital Filters with the ESP32 DevKitC

void IRAM_ATTR ISR()


{
AnalogIn = analogRead(ADC);
AnalogIn = map(AnalogIn,0,4095,0,255);
IIR_r = AnalogIn -IIR_a1 * IIR_x1 - IIR_a2 * IIR_x2;
IIR_yn = IIR_r * IIR_b0 + IIR_b1 * IIR_x1 + IIR_b2 * IIR_x2;

//
// Output the new sample via the DAC
//
dacWrite(DAC, (byte)IIR_yn);
IIR_x2 = IIR_x1;
IIR_x1 = IIR_r;
}

//
// Configure timer 0 to interrupt at every 1 ms
// Prescaler is set to 80, counter is set to 1000
//
void setup()
{
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &ISR, true);
timerAlarmWrite(My_timer, 1000, true);
timerAlarmEnable(My_timer);
}

//
// Do nothing, wait for timer interrupts
//
void loop()
{
}

Figure 13.5: Program: IIRInt.

Figure 13.6 shows the filter frequency response, plotted using the PSCGU250 device.

● 241

Practical Audio DSP Projects with the ESP32 - UK.indd 241 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure 13.6: Filter frequency response.

● 242

Practical Audio DSP Projects with the ESP32 - UK.indd 242 06-07-2023 10:40
Chapter 14 • Fast Fourier Transform (FFT)

Chapter 14 • Fast Fourier Transform (FFT)

14.1 Overview
The Fourier transform is one of the important topics in signal processing as a means of
mapping a signal from the time domain into the frequency domain. Any signal of any shape
can be represented by an infinite sum of sine and cosine waveforms. Fourier transform is
used to find the components of these series when analog signals are used. The result is the
frequency spectrum of the input analog signal, where each of its frequency and amplitude
values can be extracted.

The Discrete Fourier Transform (DFT) is a transformation just like the Fourier Transform,
but it is used with digital signals. i.e. DFT is the discrete version of the original Fourier
Transform. The Fast Fourier Transform (FFT) is an algorithm used to compute the DFT fast
and efficiently. i.e. FFT is an implementation of the DFT which produces almost identical
results as the DFT, but it is much more efficient and faster than the DFT.

Both DFT and FFT are complex processes, requiring good mathematics to understand. Al-
though there are several FFT algorithms, one of the most commonly used FFT algorithms
was developed by Cooley-Tukey, which is a divide and conquer type algorithm. This algo-
rithm breaks down the DFT into smaller parts.

Both DFT and FFT are used in many digital DSP applications, including extracting the fre-
quency spectrum, detecting targets from radar echoes, solving complex differential appli-
cations, spectral analysis, acoustic measurements, filtering algorithms, convolutions, image
processing, polynomial multiplication, and many more.

14.2 Why FFT?


The FFT algorithm is so efficient and fast that it can be implemented with most microcon-
troller systems. It enables one to see which frequencies are present in any digital signal
and also which of these frequencies are the dominating ones. In an FFT display, what you
see is the frequency at the horizontal axis and the amplitude at the vertical axis. A graph
of one or more spikes is shown. A tall spike indicates that that frequency is dominant in the
input signal. The most dominant spike represents the fundamental frequency of the input
signal. The other spikes are in the form of harmonics which occur at multiple frequencies
of the fundamental frequency.

If the input signal is a sine wave, then there is only one spike with the same frequency as
the input signal. If the input signal is a square wave, then a number of spikes with decreas-
ing amplitudes are shown at different frequency points. The FFT algorithm works with a fi-
nite number of input samples (called the length), which need to be multiples of 2 (e.g. 32,
64, 128, 256, etc). In general, the larger the samples, the slower will be the algorithm and
also more memory will be needed as more processing is required. However, larger samples
will give more accurate results.

In this chapter, we will be developing an FFT program using the Arduino Audio Tools library
of Phil Pschatzmann's, which is based on the class AudioRealFFT. The results will be

● 243

Practical Audio DSP Projects with the ESP32 - UK.indd 243 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

displayed on the Serial Monitor with the frequency, magnitude (of the frequency) and the
musical note corresponding to the frequency are all displayed together with the difference
between the frequency and the musical tone frequency. More details are available on the
following website:

https://github.com/pschatzmann/arduino-audio-tools/wiki/FFT

14.3 Project 1: FFT of an input signal


Description: In this project, the Pmod I2S2 module is used and a signal (sine wave,
square wave, or any other waveform) is injected into its input port (blue connector). The
fundamental frequency, magnitude, and musical tine frequency nearest to this frequency
are all displayed on the Serial Monitor.

The aim: The aim of this project is to show how the Arduino Audio Tools library can be
used for an FFT application.

Circuit diagram: Figure 14.1 shows the circuit diagram of the project. A Pmod I2S2 mod-
ule receives audio signals from the PCSGU250 device (notice that even though the ADC
part of the Pmod I2S2 is used only, the connections for both the ADC and DAC are shown
in Figure 14.1). The program processes the input samples and displays the results on the
Serial Monitor.

Figure 14.1: Circuit diagram of the project.

Program listing: Figure 14.2 shows the program listing (Program: FFT). At the beginning
of the program, header files AudioTools.h and AudioLibs/AudioRealFFT.h are included
in the program. Streams fft and in are defined. Inside the setup() function, the I2S stream
in (in RX_MODE) is configured b specifying the ESP32 GPIO ports it is connected to. Also,
the FFT is configured by setting the length to 8192 samples. The callback function is

● 244

Practical Audio DSP Projects with the ESP32 - UK.indd 244 06-07-2023 10:40
Chapter 14 • Fast Fourier Transform (FFT)

given the name fftResult so that the FFT results are available at this function. Function
fftResult() displays the frequency, magnitude, and the musical tone nearest to this
frequency together with the difference between the two frequencies (see website: https://
github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-audiokit/
streams-audiokit-fft/streams-audiokit-fft.ino).

/****************************************************************
* FAST FOURIER TRANSFORM
* ======================
*
* This program uses teh Arduino Audio Tools library to display the
* FFT components of an input signal.
*
* Author : Dogan Ibrahim
* Program: FFT
* Date : May, 2023
*
* (This program is a modifed version of the program developed
* by Phil Pschatzmann)
**************************************************************/
#include "AudioTools.h"
#include "AudioLibs/AudioRealFFT.h"

uint16_t sample_rate=44100;
uint8_t channels = 2;
I2SStream in;
AudioRealFFT fft;
StreamCopy copier(fft, in);

//
// Display fft result on Serial Monitor
//
void fftResult(AudioFFTBase &fft)
{
float diff;
auto result = fft.result();
if (result.magnitude>100)
{
Serial.print(result.frequency);
Serial.print(" ");
Serial.print(result.magnitude);
Serial.print(" => ");
Serial.print(result.frequencyAsNote(diff));
Serial.print( " diff: ");
Serial.println(diff);
}

● 245

Practical Audio DSP Projects with the ESP32 - UK.indd 245 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

void setup(void)
{
Serial.begin(115200);

//
// Configure in stream
//
auto configin = in.defaultConfig(RX_MODE);
configin.sample_rate = sample_rate;
configin.channels = channels;
configin.bits_per_sample = 16;
configin.i2s_format = I2S_STD_FORMAT;
configin.is_master = true;
configin.port_no = 0;
configin.pin_ws = 15; // LRCK
configin.pin_bck = 14; // SCLK
configin.pin_data = 22; // SDOUT
configin.pin_mck = 0;
in.begin(configin);

//
// Configure FFT
//
auto tcfg = fft.defaultConfig();
tcfg.length = 8192;
tcfg.channels = channels;
tcfg.sample_rate = sample_rate;
tcfg.bits_per_sample = 16;
tcfg.callback = &fftResult;
fft.begin(tcfg);
}

//
// Copy input signal to fft
//
void loop()
{
copier.copy();
}

Figure 14.2: Program: FFT.

● 246

Practical Audio DSP Projects with the ESP32 - UK.indd 246 06-07-2023 10:40
Chapter 14 • Fast Fourier Transform (FFT)

A sample output is shown in Figure 14.3 where the input was a sine wave having a fre-
quency of 440 Hz.

Figure 14.3: Sample output on the Serial Monitor.

● 247

Practical Audio DSP Projects with the ESP32 - UK.indd 247 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Appendix A

Bill of Materials

Components and modules used for the projects and experiments described in the book.

Qty. Item
8 LED
8 330-ohm resistor
1 100 k-ohm resistor
1 100 k-ohm potentiometer
1 Pushbutton
1 TMP36 temperature sensor
1 I2C LCD
1 microSD card reader module (SPI)
1 4-way, 3.3-V relay module
1 INMP441 digital microphone
1 MAX98357 class-D amplifier module
1 Small loudspeaker, 4-ohm, 3-watt (e.g., CQRobot speaker) (Note 1)
2 Small breadboard (Note 2)
10 Male and female breadboard jumper wires
1 ESP32 DevKitC with microUSB cable
1 Pmod I2S2 module and 2 pcs. 3.5-mm jack audio cables (optional)

Note 1: One project employs two MAX98357 ICs and two loudspeakers.

Note 2: The ESP32 development board is wide and not breadboard friendly. You may need
to use two small breadboards with the power rails removed in order to plug in the ESP32.

● 248

Practical Audio DSP Projects with the ESP32 - UK.indd 248 06-07-2023 10:40
Appendix B

Appendix B

Using the AUDACITY Audio Sound Processing Software


Audacity is a free open-source digital audio sound processing software package available
for Windows, macOS, and Linux-like operating systems. The software can be used to record
sound from multiple sources to post-process audio sounds including sound effects such as
trimming, fading, normalization, pitch and tempo, noise removal, and so on. The software
allows for frequency spectrum analysis, measuring RMS values, and so on. Various sounds
can be generated, such as chirp, DTMF tones, noise, rhythm track and so on. Existing sound
files can be imported into the program and these files can be edited in various ways.

The Audacity program has so many features that arguably the easiest way of
learning to use it is to install the package on your PC and then experiment with it.

The Windows version of the Audacity program can be downloaded from the following web-
site:

https://www.audacityteam.org/download/windows/

At the time of writing this book, the latest version was 3.3.2. Double-click on the program
icon to start it. Figure A.1 shows the startup screen of Audacity.

Figure A.1 Audacity startup screen.

As an example, let's generate a tone with a frequency of 1000 Hz. Click Generate 
Tone… Then select the required frequency as shown in Figure A.2. Figure A.3 shows the
screen after the tone is generated. Click the play button (green arrow) to hear the gener-
ated tone.

● 249

Practical Audio DSP Projects with the ESP32 - UK.indd 249 06-07-2023 10:40
Practical Audio DSP Projects with the ESP32

Figure A.2: Select the required tone frequency.

Figure A.3: Screen after the tone is generated.

Now, click Effect  Fading  Fade In. The screen will change as in Figure A.4 where the
sound amplitude will increase gradually. Click Effect  Distortion and Modulation 
Tremolo and select the given defaults and click Apply. The screen will change as shown in
Figure A.5. Play the tone and notice the tremolo effect.

Figure A.4: Fade-In effect.

● 250

Practical Audio DSP Projects with the ESP32 - UK.indd 250 06-07-2023 10:40
Appendix B

Figure A.5: Tremolo effect.

Click Analyze  Plot Spectrum… to plot the frequency spectrum of the generated sound
waveform. This is shown in Figure A.6, where the peak of the spectrum is around 1000 Hz.

Figure A.6: Frequency spectrum.

To export the sound as an MP3 file, click File  Export  Export as MP3 and assign a
name to your file.

● 251

Practical Audio DSP Projects with the ESP32 - UK.indd 251 06-07-2023 10:41
Practical Audio DSP Projects with the ESP32

Index digital microphone 86


Digital signals 134
A digital signal types 135
AAC 80 Direct FIR structures 177
a_coefficients 236 Direct structure 194
ADC 16 discrete exponential signal 136
AIFF 79 Discrete impulse function 145
ALAC 80 discrete-time signals. 134
amplitude 76
Analog audio processing 78 E
Analog filter 180 Elliptic filters 190
analogRead 44 EN 21
Arduino Audio Tools library 197 ESP32 timers 219
Arduino IDE 23 Espressif 13
audio DSP system 83 event counter 45

B F
b_coefficients 236 FadeLED 38
Bilinear transformation 182 Fast Fourier Transform 243
Bit Clock 83 FAT32 58
Blackman Window 164 FFT) 243
Block diagram 137 FIIIR 168
Block diagram manipulation 138 filter characteristics 156
Bluetooth 18 filter coefficients 210
Bode Plotter 196 Filter order 158
BOOT 21 Filter response 156
Butterworth filters 180 filter structures 177
Button 35 Filter type 157
Finite Impulse Response 154
C FIR 155
CAN bus 13 FIR filter design 174
Cascade FIR structures 178 firmware 22
Cascade structure 194 FLAC 80
Chebyshev filters 187 flash memory 123
Class-D amplifier 94 Format 58
clock generator 14 frequency 76
convolution process 139 Function Generator 196
current capacity 22
G
D GPIOs 16
DAC 17, 51
DAC decoder 94 H
DevKitC 20 Hamming window 162
DFT 243 Hanning Window 164
Digital audio DSP system 83
Digital Filters 154

● 252

Practical Audio DSP Projects with the ESP32 - UK.indd 252 06-07-2023 10:41
Index

I R
I2C 13 Rectangular window 161
I2S 13 ripple effect 162
IIR 155 RTC 13, 16
IIR filter algorithm 239
impulse response 139 S
Infinite Impulse Response 154 Sampling frequency 159
INMP441 87 sampling process 134
Internet radio 110 Sawtooth) 52
Inverse z-transforms 147 ScopeFIR 168
SD card 18
K SD cards 54
Kaiser window 168 SDHC 55
SD pin 95
L SDSC 55
Laplace Transform 146 SDXC 55
LCD 46 Shannon 134
ledcAttachPin 40 shared I2S port 207
ledcSetup 40 Signal input-output 202
ledcWrite 40 Signal to noise ratio 78
longitudinal waves 76 signal volume 119
lossy compression 79 Sine function 144
loudspeaker 93 Sinewave generator 198
L/R output 95 SNR 78
Sound waves 76
M SPI 13
MAX98357A 94 stereo 120
MEMS 87
MP3 80 T
music files 116 temperature sensor 17
Text to speech 114
O TFilter 168
Omnidirectional 87 timer interrupts 219
TMP36 41
P Touch sensor 17
Parks-McClellan 171 transverse waves 76
partial fraction expansion 151 Truncation 160
PCM 79 TTS 114
PCSGU250 196
Phil Schatzmann 197 U
PLAYALL 116 UART 13
Playing an MP3 file 123 Uncompressed audio file 79
Pulse counter 18 Unit ramp function 144
pushbutton 33 Unit step function 143
PWM 13 unit step sequence 135
USB connector 21

● 253

Practical Audio DSP Projects with the ESP32 - UK.indd 253 06-07-2023 10:41
Practical Audio DSP Projects with the ESP32

V
volume control 119

W
watchdog timers 16
WAV 79
wave speed 77
Wi-Fi 18
windowing 160
WMA 80
Word Select 83

Z
z-transform 143

● 254

Practical Audio DSP Projects with the ESP32 - UK.indd 254 06-07-2023 10:41
books
books

Practical Dogan Ibrahim

Audio DSP Projects holds a BSc


(Hons) degree

with the ESP32


in Electronic
Engineering,
an MSc degree
Easy and Affordable Digital Signal Processing in Automatic Control Engineering,
and a PhD degree in Digital Signal
Processing and microprocessors.
The aim of this book is to teach the basic principles of Digital Signal Dogan has worked in many
Processing (DSP) and to introduce it from a practical point of view using organizations and is a Fellow of
the Institution of Engineering and
the bare minimum of mathematics. Only the basic level of discrete-time Technology (IET) in UK and is
systems theory is given, sufficient to implement DSP applications in real a Chartered electrical engineer.
time. The practical implementations are described in real time using the Dogan has authored over 100
highly popular ESP32 DevKitC microcontroller development board. With technical books and over 200
the low cost and extremely popular ESP32 microcontroller, you should be technical articles on electronics,
microprocessors, microcontrollers,
able to design elementary DSP projects with sampling frequencies within and related fields. Dogan is a
the audio range. All programming is done using the popular Arduino IDE certified Arduino professional and
in conjunction with the C language compiler. has many years of experience with
almost all types of microprocessors
After laying a solid foundation of DSP theory and pertinent discussions on and microcontrollers.
the main DSP software tools on the market, the book present the following
audio-based sound and DSP projects:

> Using an I2S-based digital microphone to capture audio sound Ahmet Ibrahim
> Using an I2S-based class-D audio amplifier and speaker holds BSc
> Playing MP3 music stored on an SD card through an I2S-based (Hons) and
amplifier and speaker MSc degrees
in the fields
> Playing MP3 music files stored in ESP32 flash memory through an
of computing,
I2S-based amplifier and speaker software, and networking. Ahmet
> Mono and stereo Internet radio with I2S-based amplifiers and speakers has held positions in many industries
> Text-to-speech output with an I2S-based amplifier and speaker involved in enterprise computing.
> Using the volume control in I2S-based amplifier and speaker systems He enjoys advising, designing, and
implementing complex cloud and
> A speaking event counter with an I2S-based amplifier and speaker
on-premises computer systems.
> An adjustable sinewave generator with I2S-based amplifier and
speaker
> Using the Pmod I2S2 24-bit fast ADC/DAC module
> Digital low-pass and band-pass real-time FIR filter design with
external and internal A/D and D/A conversion Elektor International Media BV
> Digital low-pass and band-pass real-time IIR filter design with www.elektor.com
external and internal A/D and D/A conversion
> Fast Fourier Transforms (FFT)

You might also like