#M5StickV のマイクで録音・スピーカで再生をしてみた


## 概要
最近、販売されている新しいタイプのM5StickVでは、マイクが実装されていることが判明しました。シリアルナンバーのK027から続く数字が2003以降であるモデルにマイクが搭載されています。
手持ちのM5StickV がマイク対応していたことから、マイクで録音・スピーカで再生をしてみた。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/M5stickV?src=hash&amp;ref_src=twsrc%5Etfw">#M5stickV</a> のマイクで録音・スピーカで再生をしてみた🦻 <a href="https://t.co/UrPM6kcQEi">pic.twitter.com/UrPM6kcQEi</a></p>&mdash; nnn (@nnn112358) <a href="https://twitter.com/nnn112358/status/1296869654032334848?ref_src=twsrc%5Etfw">August 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

また、maixpy でマイクで録音するには、以前のバージョンのaudioモジュールには不具合あり、最新verが必要です。置き場所はこちら。

https://github.com/nnn112358/M5StickV_microphone


M5StickV（マイク搭載版）
https://www.switch-science.com/catalog/6651/

## M5StickVの回路図

Kendryte K210のIO_12とIO_13がマイクアンプのGoertek4737と接続されています。

![クリップボード03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73020/0cd73d35-b90a-d410-c08f-a771ba301f0a.jpeg)


|	K210のIO	|	IO名	|機能|
|	--------------	|	--------------	|--------------	|
|	IO_12	|	MIC DAT 	|	マイクAmpのDAT端子と接続|
|	IO_13	|	MIC CLK 	|	マイクAmpのCLK端子と接続|	
|	IO_11	|	SPK SD 	|		スピーカAmpのSD端子と接続|
|	IO_14	|	SPK LRCCLK 	|	スピーカAmpのLRCCLK端子と接続|
|	IO_15	|	SPK BCLK 	|	スピーカAmpのBCLK端子と接続|

## MaixPyのAudio モジュール
MaixPyでは音声データを扱うためのAudio モジュールが用意されています。
Audio オブジェクトへパラメーターとして渡すことで、直接Audio を録音や再生することができます。

```
import audio
audio.Audio(array=None, path=None, points=1024)
パラメーター
　　　array: オーディオオブジェクトに変換可能なbytearray型のデータ。
　　　Path:パスを指定します。現在wav形式のみをサポートしています。
　　　points: オーディオバッファのサンプリングデータ数を指定します。0の場合、バッファは開かれません。デフォルトは1024です。

audio_data = test_audio.to_bytes ()
　　　オーディオオブジェクトのオーディオデータをbytearray型のオブジェクトに変換します。

```

## MaixPyのI2Sモジュール
I2Sモジュールは主にI2Sデバイスを駆動するために使用されます。k210には合計3つのI2Sデバイスが搭載されており、各デバイスは合計4つのチャンネルを持っています。使用前にピンのマッピングと管理が必要です。

```
from Maix import I2S
i2s_dev = I2S(device_num)
	device_num：K210 の I2S デバイス番号を指定します。最大 3 です。

i2s_dev.channel_config(channel, mode, resolution, cycles, align_mode)
	channel：I2S チャンネル番号
	mode：チャネル送信モード、受信モードを選びます
	resolution：チャネルの解像度、つまり受信データビット数を指定します
	cycles：通信データのクロック周期を指定します。
	align_mode：チャネルのアライメントモードを指定します

i2s_dev.set_sample_rate(sample_rate)
	サンプルレートを指定します

```


## M5StickVのマイクで録音する
maixPyのAudioモジュールを使って、M5StickVのマイクで録音するソースコードです。

```
from Maix import GPIO, I2S, FFT
import image,lcd,math,time,gc,lcd
from board import board_info
from fpioa_manager import fm
import audio

lcd.init()
lcd.clear()
lcd.rotation(2)

sample_rate = 22050
sample_points = 4096

# I2S MIC GPIO
fm.register(board_info.MIC_LRCLK, fm.fpioa.I2S0_WS, force=True)
fm.register(board_info.MIC_DAT, fm.fpioa.I2S0_IN_D0, force=True)
fm.register(board_info.MIC_CLK, fm.fpioa.I2S0_SCLK, force=True)

mic_dev = I2S(I2S.DEVICE_0)
mic_dev.channel_config(mic_dev.CHANNEL_0, mic_dev.RECEIVER, align_mode=I2S.STANDARD_MODE)
mic_dev.set_sample_rate(sample_rate)
print(mic_dev)

player = audio.Audio(path="/sd/record_1.wav", is_create=True, samplerate=sample_rate)
queue = []

lcd.draw_string(20,50,"REC")

for i in range(100):
    tmp = mic_dev.record(sample_points)
    if len(queue) > 0:
        ret = player.record(queue[0])
        queue.pop(0)
    mic_dev.wait_record()
    queue.append(tmp)

player.finish()

lcd.draw_string(20,50,"finish")

```


## M5StickVのスピーカで再生する
maixPyのAudioモジュールを使って、M5StickVのスピーカで再生するソースコードです。

```
from fpioa_manager import *
from Maix import I2S, GPIO
import audio

#Speaker I2s Initialize
fm.register(board_info.SPK_SD, fm.fpioa.GPIO0)
spk_sd=GPIO(GPIO.GPIO0, GPIO.OUT)
spk_sd.value(1)
fm.register(board_info.SPK_DIN,fm.fpioa.I2S1_OUT_D1)
fm.register(board_info.SPK_BCLK,fm.fpioa.I2S1_SCLK)
fm.register(board_info.SPK_LRCLK,fm.fpioa.I2S1_WS)
wav_dev = I2S(I2S.DEVICE_1)
sample_rate = 22050

#Play Wav File
def play_wav(fname):
    player = audio.Audio(path = fname)
    player.volume(100)
    wav_info = player.play_process(wav_dev)
    wav_dev.channel_config(wav_dev.CHANNEL_1,
        I2S.TRANSMITTER,resolution = I2S.RESOLUTION_16_BIT,
        align_mode = I2S.STANDARD_MODE)
    wav_dev.set_sample_rate(sample_rate )
    while True:
        ret = player.play()
        if ret == None:
            break
        elif ret==0:
            break
    player.finish()
    print("finish")

play_wav("record_1.wav")

```



# 参考資料
- 動け！M5StickVのマイク 
https://togetter.com/li/1394287

- M5Stack Docs 
https://docs.m5stack.com/#/en/core/m5stickv
https://docs.m5stack.com/#/en/related_documents/M5StickV-Maixpy

- M5Stack Maixpy example 
https://docs.m5stack.com/#/en/related_documents/M5StickV-Maixpy

- Sipeed Maixpy Document
https://maixpy.sipeed.com/en/

- プリンをもっと見守る技術 
https://github.com/anoken/purin_wo_motto_mimamoru_gijutsu

- m5stickv_microphone_example
https://github.com/nnn112358/M5StickV_microphone