micropython / micropython/micropython

Simple I2S streaming code only works for sample rates <22050

Open
#12,955 14 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug port-esp32
Dominant language
C
Stars
22.1k
Forks
9k
Avg merge
6d 4h
Merged PRs (30d)
16

Description

notes:

from machine import I2S
from machine import Pin
import web
import asyncio 
from queue import Queue    
  
bck_pin = Pin(33)  # Bit clock output
ws_pin = Pin(32)   # Word clock output
sdin_pin = Pin(25) # Serial data input

au_chunk_len = 8192
au_chunks = 8 # must be power of 2

audio_in = I2S(1,                                 # create I2S peripheral to read audio
               sck=bck_pin, ws=ws_pin, sd=sdin_pin,    # sample data from an INMP441
               mode=I2S.RX,
               bits=32,
               format=I2S.MONO,
               rate=8000,
               ibuf=au_chunk_len)

sreader = asyncio.StreamReader(audio_in)

queue = Queue(au_chunks)

async def produce():
    print("Running produce()")
    
    #ring buffer
    dma_buffer = memoryview(bytearray(au_chunk_len*au_chunks))

    f=0
    while True:
        b = dma_buffer[f*au_chunk_len:(f+1)*au_chunk_len]
        t = au_chunk_len
        while t>0:
            t -= await sreader.readinto(b[au_chunk_len-t:])            
        await queue.put(b)
        f= (f+1)&(au_chunks-1)
        
            
app = web.App(host='0.0.0.0', port=80)

@app.route('/')
async def scan_network_handler(r, w):
    w.write(b'HTTP/1.0 200 OK\r\n')
    w.write(b'Content-Type: application/octet-stream\r\n')
    w.write(b'\r\n')

    # empty queue
    for i in range(au_chunks):
        _ = await queue.get()

    for i in range(30):
        print(f"c {i}, {queue.qsize()}")
        samples = await queue.get()
        w.write(samples)
    await w.drain()   


# Start event loop and create server task
loop = asyncio.get_event_loop()
loop.create_task(app.serve())
loop.create_task(produce())
loop.run_forever()

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided ESP32 I2S reproducer and compare its streaming behavior across the reported sample rates. Read the I2S and asyncio stream interfaces used by the example, then determine what evidence is needed to reproduce the failure. Done means the same streaming example works reliably at rates below and above 22050.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
audio-video-rtc, embedded-iot
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.