from machine import Pin, I2S import math import struct from time import sleep sck_pin = Pin(14) # Serial clock (BCLK on breakout) ws_pin = Pin(13) # Word select (LRCLK on breakout) sd_pin = Pin(12) # Serial data (DIN on breakout) # Open the audio channel using I2S (Inter-IC-Sound) audio = I2S(0, # This must be either 0 or 1 for ESP32 sck=sck_pin, ws=ws_pin, sd=sd_pin, mode=I2S.TX, bits=16, format=I2S.MONO, rate=8000, # This must match the sample rate of your file! ibuf=10000) # Let's play a clip in a .wav file WAVFILE = "fuzzy.wav" BUFFER_SIZE = 10000 wav = open(WAVFILE, "rb") # Open the file to read its bytes pos = wav.seek(44) # Skip over the WAV header information and get to the data # Create a memory buffer to store the samples buf = bytearray(BUFFER_SIZE) # And create a "memoryview" (which is basically another window into the same data), # which will allow us to read the file directly into the buffer. wav_samples_mv = memoryview(buf) # Wrap the sound-playing in a try-except block # If something goes wrong in the middle (like the user pressing 'Stop'), we'll # run the "except" part and then clean up. Otherwise, we can end up with the I2S # device stuck playing, which is *really* annoying. try: while True: # Try to read some bytes from the wave file into the buffer # The `readinto` function returns the number of bytes that it read bytes_read = wav.readinto(wav_samples_mv) # If the function didn't read anything, we must have reached the end of the file if bytes_read == 0: break # Quit the loop and stop playing else: # If we did read some bytes, send them to the speaker num_written = audio.write(wav_samples_mv[:bytes_read]) except (KeyboardInterrupt) as e: pass audio.deinit()