miketeachman / micropython-i2s-examples

Examples for I2S support on microcontrollers that run MicroPython
MIT License
219 stars 35 forks source link

play the Audio file from a URL #22

Open CRCbary opened 1 year ago

CRCbary commented 1 year ago

Hi Mike,

first i would like to thank you for the code and explainations. I have request if you don't mind. can i play the WAV file from a URL insted of an SD card?

miketeachman commented 1 year ago

Yes. It is possible to play a WAV file from a URL. Here is some example code for an ESP32 with SPIRAM. Tested with MicroPython v1.20

#
# Purpose:  plays a WAV file stored on GitHub using an I2S DAC
#
# Notes: 
# 1. the example below works on an ESP32 with SPIRAM (WROVER module).  
# 2. the example does not work on a generic ESP32 (WROOM module).  urequests will 
#    fail with "OSError: [Errno 12] ENOMEM", which is a failure to allocate memory.

import time
import network
import urequests as requests
from machine import I2S
from machine import Pin

#
#   WIFI connection information
#   
#   replace WIFI-SSID and WIFI-PASSWORD with access information for the WIFI network you will connect to
#
wifiSSID = "WIFI-SSID"         # EDIT 1 - enter name of WiFi connection point
wifiPassword = "WIFI-PASSWORD"      # EDIT 2 - enter WiFi password

#
#   create an interface that can connnect to a WIFI network
#
wifi = network.WLAN(network.STA_IF)

#
#   activate the WIFI interface
#
wifi.active(True)

#
#   connect the ESP32 device to the WIFI network
#
wifi.connect(wifiSSID, wifiPassword)
time.sleep(1)

#
#   wait until the ESP8266 has successfully connected to the WIFI network
# 
while not wifi.isconnected():
  pass

print('connected')

# ======= I2S CONFIGURATION =======
SCK_PIN = 33
WS_PIN = 25
SD_PIN = 32
I2S_ID = 0
BUFFER_LENGTH_IN_BYTES = 50000
# ======= I2S CONFIGURATION =======

# ======= AUDIO CONFIGURATION =======
WAV_FILE = "music-16k-16bits-mono.wav"
WAV_SAMPLE_SIZE_IN_BITS = 16
FORMAT = I2S.MONO
SAMPLE_RATE_IN_HZ = 16000
# ======= AUDIO CONFIGURATION =======

audio_out = I2S(
    I2S_ID,
    sck=Pin(SCK_PIN),
    ws=Pin(WS_PIN),
    sd=Pin(SD_PIN),
    mode=I2S.TX,
    bits=WAV_SAMPLE_SIZE_IN_BITS,
    format=FORMAT,
    rate=SAMPLE_RATE_IN_HZ,
    ibuf=BUFFER_LENGTH_IN_BYTES,
)

wav_samples = bytearray(10000)
wav_samples_mv = memoryview(wav_samples)

# GitHub repository information
repo_owner = 'miketeachman'
repo_name = 'micropython-i2s-examples'
file_path = 'wav/'+WAV_FILE

# URL of the binary file on GitHub
url = f'https://raw.githubusercontent.com/{repo_owner}/{repo_name}/master/{file_path}'

# Retrieve the binary file from the URL using requests
response = requests.get(url, stream=True)
_ = response.raw.read(44)  # advance to first byte of Data section in WAV file

# Check if the request was successful
if response.status_code == 200:
    # play WAV file, continuously
    while True:
        num_read = response.raw.readinto(wav_samples_mv)
        if num_read == 0:
            # end of WAV file, loop back to start of WAV file
            response.close()
            response = requests.get(url, stream=True)
            _ = response.raw.read(44)  # advance to first byte of Data section in WAV file
        else:
            _ = audio_out.write(wav_samples_mv[:num_read])
else:
    # Handle the error
    print(f'Error retrieving binary file. Status code: {response.status_code}')
bomxacalaka commented 1 year ago

I keep getting errors on esp32 when executing audio_out()

connected
E (5662) I2S: Error malloc dma buffer
/home/micropython/esp-idf-v4.2/components/freertos/queue.c:1816 (vQueueDelete)- assert failed!

abort() was called at PC 0x400978e4 on core 1

Backtrace:0x40093f46:0x3ffccf40 0x400946ad:0x3ffccf60 0x400982be:0x3ffccf80 0x400978e4:0x3ffccff0 0x40169e39:0x3ffcd010 0x40169f91:0x3ffcd030 0x4016aa1a:0x3ffcd070 0x4016b3b5:0x3ffcd0e0 0x400d6c80:0x3ffcd120 0x400d6dd9:0x3ffcd1a0 0x400e20dd:0x3ffcd1d0 0x400e3eda:0x3ffcd1f0 0x400846c6:0x3ffcd210 0x400dd10a:0x3ffcd2b0 0x400e3eda:0x3ffcd2e0 0x400e3f02:0x3ffcd300 0x400f1ae7:0x3ffcd320 0x400f1eb7:0x3ffcd3b0 0x400d5e32:0x3ffcd3d0

ELF file SHA256: d0595d695c66ca30

And when this error doesnt happen then another one happens on requests.get()

Traceback (most recent call last):
  File "main.py", line 108, in <module>
  File "urequests.py", line 180, in get
  File "urequests.py", line 76, in request
OSError: -202

Any ideas?

miketeachman commented 1 year ago

Which board are you using, and also what MicroPython release. thanks!

bomxacalaka commented 1 year ago

ESP32 v1.20.0 (2023-04-26) .bin

It seems like every time it tries to create audio_out it runs out of memory?

audio_out = I2S(
    I2S_ID,
    sck=Pin(SCK_PIN),
    ws=Pin(WS_PIN),
    sd=Pin(SD_PIN),
    mode=I2S.TX,
    bits=WAV_SAMPLE_SIZE_IN_BITS,
    format=FORMAT,
    rate=SAMPLE_RATE_IN_HZ,
    ibuf=BUFFER_LENGTH_IN_BYTES,
)
E (6603) I2S: Error malloc dma buffer
/home/micropython/esp-idf-v4.2/components/freertos/queue.c:1816 (vQueueDelete)- assert failed!

abort() was called at PC 0x400978e4 on core 1

Backtrace:0x40093f46:0x3ffccf40 0x400946ad:0x3ffccf60 0x400982be:0x3ffccf80 0x400978e4:0x3ffccff0 0x40169e39:0x3ffcd010 0x40169f91:0x3ffcd030 0x4016aa1a:0x3ffcd070 0x4016b3b5:0x3ffcd0e0 0x400d6c80:0x3ffcd120 0x400d6dd9:0x3ffcd1a0 0x400e20dd:0x3ffcd1d0 0x400e3eda:0x3ffcd1f0 0x400846c6:0x3ffcd210 0x400dd10a:0x3ffcd2b0 0x400e3eda:0x3ffcd2e0 0x400e3f02:0x3ffcd300 0x400f1ae7:0x3ffcd320 0x400f1eb7:0x3ffcd3b0 0x400d5e32:0x3ffcd3d0

ELF file SHA256: d0595d695c66ca30

And the request has issues sometimes, its not always though.

response = requests.get(url, stream=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "urequests.py", line 180, in get
  File "urequests.py", line 76, in request
OSError: -202

So I removed the stream=True and it worked, but now it stopped working again.

Thanks!