《DNK210使用指南 -CanMV版 V1.0》第二十八章 音訊播放實驗

正点原子發表於2024-10-08

第二十八章 音訊播放實驗

1)實驗平臺:正點原子DNK210開發板

2)章節摘自【正點原子】DNK210使用指南 - CanMV版 V1.0

3)購買連結:https://detail.tmall.com/item.htm?&id=782801398750

4)全套實驗原始碼+手冊+影片下載地址:http://www.openedv.com/docs/boards/k210/ATK-DNK210.html

5)正點原子官方B站:https://space.bilibili.com/394620890

6)正點原子K210技術交流企鵝群:605557868

本章將介紹CanMV下的音訊播放,透過CanMV提供的模組便能快速實現音訊播放。透過本章的學習,讀者將學習到CanMV下控制I2S輸出音訊資料和audio模組的使用。
本章分為如下幾個小節:
28.1 maix.I2S模組及audio模組介紹
28.2 硬體設計
28.3 程式設計
28.4 執行驗證

28.1 maix.I2S模組及audio模組介紹
Kendryte K210擁有三個I2S標準介面,且都是Master模式,Kendryte K210上的I2S特點如下所示:

  1. 匯流排寬度可配置為8、16、32位
  2. 每個介面最多支援4個立體聲通道
  3. 由於傳送器和接收器的獨立性,所以支援全雙工通訊
  4. APB匯流排和I2S sclk的非同步時鐘
  5. 音訊資料解析度為12、16、20、14、32位
  6. 可配置的FIFO深度為2、4、8、16字
  7. 可配置可程式設計的DMA暫存器
  8. 可程式設計FIFO閾值

在CanMV中可以使用CanMV提供的maix.I2S模組操作Kendryte K210上的I2S。maix.I2S模組可以配置I2S的通道傳輸模式、通道解析度、取樣率等引數。
maix.I2S模組提供了I2S建構函式,用於建立一個I2S物件,I2S建構函式如下所示:

class I2S(device_num, sample_points=1024, pll2=0, mclk=0)

透過I2S建構函式可以透過指定引數建立並初始化一個I2S物件。
device_num指的是I2S裝置的編號,可以指I2S.DEVICE_0、I2S.DEVICE_1或I2S.DEVICE_2,它們分別對用了Kendryte K210硬體上的三個I2S介面裝置。
sample_points指的是I2S裝置的取樣率,預設為1024,最大值為65536。
pll2指的是Kendryte K210 PLL2的頻率,當為0時表示不對PLL2進行額外配置。
mclk指的是Kendryte K210 I2S裝置輸入時鐘的分頻係數,輸入時鐘來自PLL2,當為0時表示不對該分頻係數進行額外配置。
I2S建構函式的使用示例如下所示:

from maix import I2S
i2s_dev = I2S(I2S.DEVICE_0)

maix.I2S為I2S物件提供了channel_config()方法,用於對I2S裝置的通道進行配置,channel_config()方法如下所示:

I2S.channel_config(channel=I2S.CHANNEL_0, mode=I2S.RECEIVER, resolution=I2S.RESOLUTION_16_BIT,
 cycles=I2S.SCLK_CYCLES_32, align_mode=I2S.STANDARD_MODE)

channel_config()方法用於配置I2S裝置指定通道的各項引數,包括傳輸模式、解析度、單個資料時鐘數、對齊模式等。
channel指的是通道編號,可以是I2S.CHANNEL_0~I2S.CHANNEL_3,分別對應了Kendryte K210 I2S裝置的通道0~通道3。
mode指的是I2S通道的傳輸模式,可以是I2S.TRANSMITTER或I2S.RECEIVER,分別對應了傳送模式和接收模式,其中傳送模式用於播放音訊,而接收模式用於錄製音訊。
resolution指的是I2S通道的解析度,即接收資料位數,可以是I2S.RESOLUTION_12_BIT、I2S.RESOLUTION_16_BIT、I2S.RESOLUTION_20_BIT、I2S.RESOLUTION_24_BIT或I2S.RESOLUTION_32_BIT。
cycles指的是I2S通道的單個資料佔用的時鐘數量,可以是I2S.SCLK_CYCLES_16、I2S.SCLK_CYCLES_24或I2S.SCLK_CYCLES_32。
align_mode指的是I2S通道的資料對齊模式,可以是I2S.STANDARD_MODE、I2S.RIGHT_JUSTIFYING_MODE或I2S.LEFT_JUSTIFYING_MODE。
channel_config()方法的使用示例如下所示:

from maix import I2S
i2s_dev = I2S(I2S.DEVICE_0)
i2s_dev.channel_config(I2S.CHANNEL_0, I2S.TRANSMITTER, resolution=I2S.RESOLUTION_16_BIT, 
cycles=I2S.SCLK_CYCLES_32, align_mode=I2S.STANDARD_MODE)

maix.I2S為I2S物件提供了set_sample_rate()方法,用於配置I2S物件的取樣率,set_sample_rate()方法如下所示:

I2S.set_sample_rate(sample_rate)

set_sample_rate()方法用於配置I2S物件的取樣率,只有正確地配置了取樣率,才能正確地播放音訊。
sample_rate指的是取樣率,最大值為4194304。
set_sample_rate()方法的使用示例如下所示:

from maix import I2S
i2s_dev = I2S(I2S.DEVICE_0)
i2s_dev.channel_config(I2S.CHANNEL_0, I2S.TRANSMITTER, resolution=I2S.RESOLUTION_16_BIT, 
cycles=I2S.SCLK_CYCLES_32, align_mode=I2S.STANDARD_MODE)
i2s_dev.set_sample_rate(44100)

maix.I2S為I2S物件提供了record()方法,用於從I2S物件獲取音訊資料,record()方法如下所示:

I2S.record(points=0, time=0)

record()方法用於從I2S物件獲取音訊資料,獲取資料的長度可以透過取樣點或時間進行指定。
points指的是獲取音訊資料的取樣點數量,預設為0。
time指的是獲取音訊資料的時間長度,單位為秒(S),預設為0。
record()的使用示例如下所示:

from maix import I2S
i2s_dev = I2S(I2S.DEVICE_0)
i2s_dev.channel_config(I2S.CHANNEL_0, I2S.TRANSMITTER, resolution=I2S.RESOLUTION_16_BIT, 
cycles=I2S.SCLK_CYCLES_32, align_mode=I2S.STANDARD_MODE)
i2s_dev.set_sample_rate(44100)
i2s_dev.record(time=10)

maix.I2S模組僅僅是用於配置Kendryte K210硬體上的I2S介面裝置,但對於音訊檔案的編解碼以及資料流的處理,需要使用到CanMV提供的audio模組。
audio模組是CanMV內建的模組,audio模組用於音訊的播放和錄製,audio模組可以抽象出音訊物件,該物件可以被當作引數傳入,也可以直接只用該物件的方法來播放和錄製音訊。
audio模組提供了Audio建構函式,用於建立一個Audio物件,Audio建構函式如下所示:

class Audio(array=None, path=None, points=1024, is_creat=False, samplerate=44100)

透過Audio建構函式可以透過指定引數建立初始化一個Audio物件。
array指的是bytearray型別的音訊資料,可以將該資料轉換為音訊物件,預設為None。
path指的是檔案系統中的音訊檔案的路徑,目前CanMV僅支援WAV格式的音訊檔案。
points指的是構造Audio物件時建立多少個取樣點的音訊緩衝區,一個取樣點的大小為32bit,預設為1024。
is_creat指的是CanMV以什麼樣的方式開啟path指定的音訊檔案,當為True時,CanMV將以只寫方式開啟音訊檔案,一般用於音訊錄製,當為False時,CanMV將以只讀方式開啟音訊檔案,一般用於音訊播放,預設為False。
samplerate指的是取樣率,預設為44100。
Audio建構函式的使用示例如下所示:

import audio
audio_player = audio.Audio(path="/sd/MUSIC/play.wav")

audio模組為Audio物件提供了play_process()方法,用於預處理音訊物件,play_process()方法如下所示:

audio.play_process(i2s_dev)

play_process()方法用於預處理音訊物件,在播放音訊之前需要對音訊檔案進行解析,並且傳入一個用於播放音訊的I2S物件。
i2s_dev指的是使用maix.I2S模組提供的I2S建構函式構造的I2S物件。
play_process()方法會解析音訊檔案,並但會以list型別返回WAV檔案的頭部資訊,包含numchannels(聲道數)、samplerate(取樣率)、byterate(每秒資料位元組數 = samplerate * numchannels* bitspersample / 8)、blockalign(每個取樣所需的位元組數 = numchannels * bitspersample / 8)、bitspersample(每個取樣儲存的bit數,8:8bit,16:16bit,32:32bit),datasize(音訊資料長度)。
play_process()方法的使用示例如下所示:

from maix import I2S
import audio
i2s_dev = I2S(I2S.DEVICE_0)
audio_player = audio.Audio(path="/sd/MUSIC/play.wav")
wav_info = audio_player.play_process(i2s_dev)

audio模組為Audio物件提供了play()方法,用於讀取音訊檔案並解析播放,play()方法如下所示:

audio.play()

play()方法用於讀取音訊檔案並解析播放,每次執行play()函式會讀取並解析播放一小段音訊檔案,因此play()函式需要配合迴圈使用。
play()方法的使用示例如下所示:

from maix import I2S
import audio
i2s_dev = I2S(I2S.DEVICE_0)
audio_player = audio.Audio(path="/sd/MUSIC/play.wav")
wav_info = audio_player.play_process(i2s_dev)
i2s_dev.set_sample_rate(wav_info[1])
while audio_player.play():
    pass

audio模組為Audio物件提供了volume()方法,用於配置播放音訊時的音量,volume()方法如下所示:

audio.volume(volume)

volume()方法用於配置播放音訊時的音量。
volume指的是配置的音量,範圍為[0, 100]。
volume()方法的使用示例如下所示:

from maix import I2S
import audio
i2s_dev = I2S(I2S.DEVICE_0)
audio_player = audio.Audio(path="/sd/MUSIC/play.wav")
audio_player.volume(30)

audio模組為Audio物件提供了record()方法,用於將從I2S物件獲取到的音訊資料使用WAV編碼儲存到檔案系統中,record()方法如下所示:

audio.record(record)

record()方法用於將從I2S物件獲取到的音訊資料儲存到構建Audio物件時指定的檔案中。
record指的是從I2S物件獲取到的音訊資料。
record()方法的使用示例如下所示:

from maix import I2S
import audio
i2s_dev = I2S(I2S.DEVICE_0)
i2s_dev.channel_config(I2S.CHANNEL_0, I2S.RECEIVER, align_mode=I2S.STANDARD_MODE)
i2s_dev.set_sample_rate(11400)
audio_recorder = audio.Audio(path="/sd/record.wav", is_create=True, samplerate=11400)
data = i2s_dev.record(time=10)
audio_recorder.record(datas[0])

28.2 硬體設計
28.2.1 例程功能

  1. 使用maix.I2S模組和audio模組播放CanMV檔案系統中指定的音訊檔案。

28.2.2 硬體資源

  1. 數字功放NS4168
    SPK_CTRL- IO21
    IIS_SDOUT- IO31
    IIS_BCK- IO32
    IIS_LRCK- IO33

28.2.3 原理圖
本章實驗內容,需要解析檔案系統中的WAV檔案,然後將音訊資料透過I2S介面傳送到數字功放NS4168,隨後NS4168便可根據配置,控制板載的揚聲器發聲。
DNK210開發板上的數字功放NS4168的連線原理圖,如下圖所示:

圖28.2.3.1 數字功放NS4168連線原理圖

關於數字功放NS4168的使用方法,可參考NS4168的資料手冊,NS4168的資料手冊可透過網站獲取,網址為:http://www.nsiway.com.cn/product/18.html。
這裡簡單對NS4168的CTRL引腳進行說明,當CTRL引腳上的電壓為0V0.4V時,NS4168處於低功耗關斷狀態,當CTRL引腳上的電壓為0.9V1.15V時,NS4168控制揚聲器播放I2S介面接收到音訊資料中的左聲道資料,當CTRL引腳上的電壓為1.5V~VDD時,NS4168控制揚聲器播放I2S介面接收到的音訊資料中的右聲道資料。

28.3 程式設計
28.3.1 maix.I2S模組及audio模組介紹
有關maix.I2S模組及audio模組的介紹,請見第28.1小節《maix.I2S模組及audio模組介紹》。
28.3.2 程式流程圖

圖28.3.2.1 音訊播放實驗流程圖

28.3.3 main.py程式碼
main.py中的指令碼程式碼如下所示:

from board import board_info
from fpioa_manager import fm
from maix import GPIO
from maix import I2S
import audio
fm.register(board_info.SPK_CTRL, fm.fpioa.GPIO0)
fm.register(board_info.SPK_WS, fm.fpioa.I2S0_WS)
fm.register(board_info.SPK_SCLK, fm.fpioa.I2S0_SCLK)
fm.register(board_info.SPK_SDOUT, fm.fpioa.I2S0_OUT_D0)
# 控制數字功放播放右聲道音訊資料
spk_ctl = GPIO(GPIO.GPIO0, GPIO.OUT)
spk_ctl.value(1)
# 構造I2S物件並配置I2S通道
i2s_dev = I2S(I2S.DEVICE_0)
i2s_dev.channel_config(I2S.CHANNEL_0, I2S.TRANSMITTER, resolution=I2S.RESOLUTION_16_BIT, 
cycles=I2S.SCLK_CYCLES_32, align_mode=I2S.STANDARD_MODE)
# 構造Audio物件並解析音訊檔案
audio_player = audio.Audio(path="/sd/MUSIC/play.wav")
wav_info = audio_player.play_process(i2s_dev)
# 根據解析資料配置I2S物件的取樣率並配置播放音量
i2s_dev.set_sample_rate(wav_info[1])
audio_player.volume(30)
# 迴圈播放音訊檔案
while audio_player.play():
    pass
# 結束音訊播放
audio_player.finish()

可以看到首先是為GPIO以及I2S分配IO,然後控制數字功放NS4168的CTRL引腳為高電平,此時NS4168被配置為控制揚聲器播放音訊資料中的右聲道音訊。
接著是構造了一個I2S物件,並配置了I2S對應的通道為傳送模式,因為本實驗需要播放音訊資料。
再接著構造了一個Audio物件,Audio物件與檔案系統中的音訊檔案進行繫結,然後解析音訊檔案,獲取音訊檔案WAV的頭部資訊。
接下來根據WAV頭部資訊中的取樣率配置I2S物件,同時配置好Audio物件輸出音訊的音量。
然後就是迴圈播放音訊資料了,如果都沒有問題的話,此時應該能聽見DNK210開發闆闆載的揚聲器發聲了。
最後在音訊檔案播放完畢後,結束音訊播放,釋放音訊播放佔用的資源。
28.4 執行驗證
將DNK210開發板連線CanMV IDE,同時將實驗例程目錄下的play.wav音訊檔案放入SD卡根目錄下的media資料夾下後,點選CanMV IDE上的“開始(執行指令碼)”按鈕後,可以聽到DNK210開發闆闆載的揚聲器播放了play.wav音訊。

相關文章