Playing with Maixduino: recording and playing audio using Micropython

1. Prepare

  • Maixduino
  • 1W speaker
  • Micro SD card

2. Format SD card and connect speaker

Micro SD card should be formatted as FAT32 type. SD card should be placed into Maixduino after saving script to the board. If we save script to the board while card is being inside, MaixPy IDE will save script to SD instead of flash memory.

Connect a 1W speaker to the board as in the picture below.

Connect speaker and Micro SD card to Maixduino

3. Record audio to wav file

from fpioa_manager import fm
from Maix import I2S
import audio

# Register i2s(i2s0) pin
fm.register(20,fm.fpioa.I2S0_IN_D0, force=True)
fm.register(19,fm.fpioa.I2S0_WS, force=True)
fm.register(18,fm.fpioa.I2S0_SCLK, force=True)

# Function to record wav file
def recorder(filepath,duration=5):
    # user setting
    record_rate   = 16000
    # in seconds, maximum 10s
    if duration > 10:
        duration = 10
    # default seting
    record_points = 2048
    record_ch     = 2
    # Init i2s(i2s0)
    rec_dev = I2S(I2S.DEVICE_0)
    rec_dev.channel_config(rec_dev.CHANNEL_0, rec_dev.RECEIVER, align_mode=I2S.STANDARD_MODE)
    rec_dev.set_sample_rate(record_rate)
    print(rec_dev)
    try:
        # init audio
        wav_recorder = audio.Audio(path=filepath, is_create=True, samplerate=record_rate)
        queue = []
        record_frame_cnt = record_time*record_rate//record_points
        # Record and save
        print("[REC WAV] Recording in %d seconds..." %(record_time))
        for i in range(record_frame_cnt):
            tmp = rec_dev.record(record_points*record_ch)
            if len(queue) > 0:
                ret = wav_recorder.record(queue[0])
                queue.pop(0)
            rec_dev.wait_record()
            queue.append(tmp)
            #print("[REC] " + str(i) + ":" + str(time.ticks()))
        # Done
        print("[REC WAV] Done!")
        wav_recorder.finish()
    except Exception as e:
        print("[Exception] %s" % (e))

# Record in 5s
recorder("/sd/record.wav",5)

4. Play wav file

from fpioa_manager import fm
from Maix import I2S
import audio

# Register i2s(i2s1) pin
fm.register(34,fm.fpioa.I2S1_OUT_D1, force=True)
fm.register(35,fm.fpioa.I2S1_SCLK, force=True)
fm.register(33,fm.fpioa.I2S1_WS, force=True)

# Function to play wav file
def player(filepath,vol=80):
    # Init i2s(i2s1)
    wav_dev = I2S(I2S.DEVICE_1)
    ret = None
    try:
        # Init audio
        audio_player = audio.Audio(path = filepath)
        audio_player.volume(vol)
        # read audio info
        wav_info = audio_player.play_process(wav_dev)
        # config i2s according to audio info
        wav_dev.channel_config(wav_dev.CHANNEL_1, I2S.TRANSMITTER,resolution = I2S.RESOLUTION_16_BIT ,cycles = I2S.SCLK_CYCLES_32, align_mode = I2S.RIGHT_JUSTIFYING_MODE)
        wav_dev.set_sample_rate(wav_info[1])
        print("[PLAY WAV] Playing %s..." %(filepath))
        # loop to play audio
        while True:
            ret = audio_player.play()
            if ret == None:
                print("[ERROR] Audio format error!")
                break
            elif ret==0:
                break
        print("[PLAY WAV] Done!")
        audio_player.finish()
    except Exception as e:
        print("[Exception] %s" % (e))
    return ret
 
# Play wav file with volume = 100
player("/sd/record.wav",100)

5. Record and playback

import time
from fpioa_manager import fm
from Maix import I2S
import audio

# Register i2s(i2s0) pin
fm.register(20,fm.fpioa.I2S0_IN_D0, force=True)
fm.register(19,fm.fpioa.I2S0_WS, force=True)
fm.register(18,fm.fpioa.I2S0_SCLK, force=True)

# Register i2s(i2s1) pin
fm.register(34,fm.fpioa.I2S1_OUT_D1, force=True)
fm.register(35,fm.fpioa.I2S1_SCLK, force=True)
fm.register(33,fm.fpioa.I2S1_WS, force=True)

# Function to record and playback
def recorder(filepath,duration=5,playback=False):
    # user setting
    record_rate   = 16000
    # in seconds, maximum 10s
    if duration > 10:
        duration = 10
    record_time   = duration
    # default seting
    record_points = 2048
    record_ch     = 2
    # Init i2s(i2s0)
    rec_dev = I2S(I2S.DEVICE_0)
    rec_dev.channel_config(rec_dev.CHANNEL_0, rec_dev.RECEIVER, align_mode=I2S.STANDARD_MODE)
    rec_dev.set_sample_rate(record_rate)
    print(rec_dev)
    # Init i2s(i2s1)
    wav_dev = I2S(I2S.DEVICE_1)
    if playback:
        # config i2s according to audio info
        wav_dev.channel_config(wav_dev.CHANNEL_1, I2S.TRANSMITTER,resolution = I2S.RESOLUTION_16_BIT ,cycles = I2S.SCLK_CYCLES_32, align_mode = I2S.RIGHT_JUSTIFYING_MODE)
        wav_dev.set_sample_rate(record_rate)
    try:
        # init audio
        wav_recorder = audio.Audio(path=filepath, is_create=True, samplerate=record_rate)
        queue = []
        record_frame_cnt = record_time*record_rate//record_points
        print("[PLAYBACK] Recording in %d seconds..." %(record_time))
        # Record and play
        for i in range(record_frame_cnt):
            tmp = rec_dev.record(record_points*record_ch)
            if playback:
                wav_dev.play(tmp)
            if len(queue) > 0:
                ret = wav_recorder.record(queue[0])
                queue.pop(0)
            rec_dev.wait_record()
            queue.append(tmp)
            #print("[REC] " + str(i) + ":" + str(time.ticks()))
        # Done
        print("[PLAYBACK] Done!")
        wav_recorder.finish()
    except Exception as e:
        print("[Exception] %s" % (e))
 
# Record and playback in 5s
recorder("/sd/record.wav",5,True)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *