日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

?

概括

前一陣子想著語音識(shí)別作為物聯(lián)網(wǎng)不可或缺的一部分,前提是獲取到語音的聲音數(shù)據(jù)。對(duì)于聲音收錄數(shù)字化,stm32有很多現(xiàn)成的樣例,而OpenHarmony方面較少該方面的資料。便想著在OpenHarmony實(shí)現(xiàn)接收INMP441麥克風(fēng)模塊。本次實(shí)現(xiàn)通過I2S接收INMP441模塊的PCM數(shù)據(jù)。

#創(chuàng)作者激勵(lì)#【FFH】OpenHarmony輕量化系統(tǒng)聲音收錄-開源基礎(chǔ)軟件社區(qū)

環(huán)境

  • OpenHarmony-3.1
  • 潤和hispark_pegasus Hi3861開發(fā)板
  • DevEco Device Tool
  • SerialPlot
  • INMP441麥克風(fēng)模塊

聲音數(shù)字化

生活中的聲音是通過一定介質(zhì)傳播的波、主要由振幅和頻率兩個(gè)指標(biāo)來描述。

聲音數(shù)字化:麥克風(fēng)將聲音以量化位數(shù)將聲音數(shù)字化,常見的量化位深有16bit、24bit、32bit,其意義就是將每個(gè)采樣點(diǎn)用多少位表示聲音振幅的范圍,其位深越大音質(zhì)越好。麥克風(fēng)再根據(jù)采樣率進(jìn)行采集聲音,采樣率的意思就是1秒中采集聲音的次數(shù),采樣率越高音質(zhì)越好。還決定音質(zhì)的便是聲道數(shù),使用雙聲道可以大大豐富聲音的表現(xiàn)力,但隨之而來的便是數(shù)據(jù)量的翻倍。

現(xiàn)實(shí)生活中的聲音信號(hào)是如下圖般的波形圖,但是我們的計(jì)算機(jī)中只能保存數(shù)值。于是我們將波形圖量化,使用一個(gè)個(gè)整數(shù)數(shù)據(jù)記錄聲音。

#創(chuàng)作者激勵(lì)#【FFH】OpenHarmony輕量化系統(tǒng)聲音收錄-開源基礎(chǔ)軟件社區(qū)

 

本次使用的INMP441是一個(gè)數(shù)字麥克風(fēng),即本身包含了ADC,傳遞進(jìn)來的數(shù)據(jù)是數(shù)字量。得到的數(shù)據(jù)便是直接的PCM編碼格式的數(shù)據(jù),若想生成WAV文件,只需要生成一個(gè)wav head來標(biāo)識(shí)即可。

// 生成wav header,32bit 位深
void wavHeader(byte* header, int wavSize){ // 數(shù)字小端格式,字符大端格式
  header[0] = 'R';
  header[1] = 'I';
  header[2] = 'F';
  header[3] = 'F';
  unsigned int fileSize = wavSize + headerSize - 8;
  header[4] = (byte)(fileSize & 0xFF); // file size, 4byte integer
  header[5] = (byte)((fileSize >> 8) & 0xFF);
  header[6] = (byte)((fileSize >> 16) & 0xFF);
  header[7] = (byte)((fileSize >> 24) & 0xFF);
  header[8] = 'W';
  header[9] = 'A';
  header[10] = 'V';
  header[11] = 'E';
  header[12] = 'f';
  header[13] = 'm';
  header[14] = 't';
  header[15] = ' ';
  header[16] = 0x10; // length of format data = 16, 4byte integer
  header[17] = 0x00;
  header[18] = 0x00;
  header[19] = 0x00;
  header[20] = 0x01;  // format type:1(PCM), 2byte integer 
  header[21] = 0x00;
  header[22] = 0x01; // channel number:1, 2byte integer
  header[23] = 0x00;
  header[24] = 0x80; // sample rate:16000=0x00003E80, 4byte integer
  header[25] = 0x3E;
  header[26] = 0x00;
  header[27] = 0x00;
  header[28] = 0x00; // SampleRate*BitPerSample*ChannelNum/8=16000*32*1/8=64000=0x0000FA00, 4byte integer
  header[29] = 0xFA;
  header[30] = 0x00;
  header[31] = 0x00;
  header[32] = 0x04; // BitPerSample*ChannelNum/8 = 4, 2byte integer 
  header[33] = 0x00;
  header[34] = 0x20; // BitPerSample:32 = 0x0020, 2byte integer 
  header[35] = 0x00;
  header[36] = 'd';
  header[37] = 'a';
  header[38] = 't';
  header[39] = 'a';
  header[40] = (byte)(wavSize & 0xFF);
  header[41] = (byte)((wavSize >> 8) & 0xFF);
  header[42] = (byte)((wavSize >> 16) & 0xFF);
  header[43] = (byte)((wavSize >> 24) & 0xFF); 
}

針腳定義

本次實(shí)驗(yàn)只用到了以下四個(gè)I2S的針腳

  • SCK(CK):串行時(shí)鐘,由主機(jī)產(chǎn)生的時(shí)鐘線,用于控制每位數(shù)據(jù)的傳輸時(shí)序,SCK頻率= 聲道數(shù) 采樣頻率 * 采樣位數(shù)*,在OpenHarmony上被定義為BCLK口
  • SD:I2S數(shù)據(jù)線,從機(jī)通過此發(fā)送數(shù)據(jù)給主機(jī),在OpenHarmony上被定義為RX口
  • WS:聲道選擇線,由主機(jī)發(fā)送給從機(jī),從機(jī)根據(jù)此判斷發(fā)送左聲道還是右聲道。低電平為左聲道,高電平為右聲道。
  • L/R:左右聲道選擇線,指定此從機(jī)為左聲道還是右聲道。低電平為左聲道,高電平為右聲道。

INMP441

Hi3861

SCK

7

SD

11

W

8

L/R

根據(jù)需求接GND或3V3

GND

GND

VDD

3V3

查看音頻波形

Hi3861接收到了麥克風(fēng)模塊上傳的音頻數(shù)據(jù),我們可以利用串口將音頻數(shù)據(jù)發(fā)送到電腦,電腦使用串口繪畫工具SerialPlot查看音頻波形,該工具的使用方法和使用其他串口工具相似,網(wǎng)上也有許多使用教程,這里就不再詳細(xì)闡述。

#創(chuàng)作者激勵(lì)#【FFH】OpenHarmony輕量化系統(tǒng)聲音收錄-開源基礎(chǔ)軟件社區(qū)

代碼

流程:

  1. 初始化IO口
  2. 配置I2S(采樣率為8KHz,量化位數(shù)為24bit)
  3. 初始化I2S
  4. 讀取I2S數(shù)據(jù),OpenHarmony的讀取函數(shù)得到的數(shù)據(jù)就是24bit數(shù)字量;無需像stm32需要讀取的數(shù)據(jù)是byte類型,然后再拼接。

數(shù)據(jù)將以LRLR分布,即是一個(gè)左聲道數(shù)據(jù),一個(gè)右聲道數(shù)據(jù)分布

若是只使用到單聲道,也是LRLR分布,另外一個(gè)聲道數(shù)據(jù)為0

#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_pwm.h"
#include "iot_i2c.h"
#include "iot_errno.h"

#include "hi_dma.h"
#include "hi_types_base.h"
#include "hi_i2s.h"

#include "hi_io.h"

void i2s_init_demo(void)
{
    hi_u32 ret;
    //初始化IO口
    IoTGpioInit(HI_IO_NAME_GPIO_7);
    IoTGpioInit(HI_IO_NAME_GPIO_8);
    IoTGpioInit(HI_IO_NAME_GPIO_11);
    IoTGpioInit(HI_IO_NAME_GPIO_10);
    hi_io_set_func(HI_IO_NAME_GPIO_7, HI_IO_FUNC_GPIO_7_I2S0_BCLK);
    hi_io_set_func(HI_IO_NAME_GPIO_8, HI_IO_FUNC_GPIO_8_I2S0_WS);
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_I2S0_RX);
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_I2S0_TX);

    ret = hi_i2s_deinit();
    //配置I2S,采樣率為8KHz,量化位數(shù)為24bit
    hi_i2s_attribute i2s_cfg = {
        .sample_rate = HI_I2S_SAMPLE_RATE_8K,
        .resolution = HI_I2S_RESOLUTION_24BIT,
    };
    if (ret != HI_ERR_SUCCESS)
        printf("Failed to deinit i2s!n");
    //初始化
    ret = hi_i2s_init(&i2s_cfg);
    if (ret != HI_ERR_SUCCESS)
        printf("Failed to init i2s!n");
    printf("ret = %d n", ret);
    printf("I2s init succrss!n");
}

void i2s_main_demo(void)
{
    hi_u32 ret;
    i2s_init_demo();
    sleep(2);

    hi_u32 get_buff[100] = {0};
    while(1)
    {
        //讀取I2S信息
        hi_i2s_read(get_buff, 100, HI_SYS_WAIT_FOREVER);
        for (int i = 0; i < 100;i++)
        {
            printf("%dn", get_buff[i]);
        }
    }
}
//demo線程創(chuàng)建
void INMP441TestDemo(void)
{
    osThreadAttr_t attr;

    attr.name = "INMP441Task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew(i2s_main_demo, NULL, &attr) == NULL)
    {
        printf("[INMP441Task] Falied to create INMP441Task!n");
    }
}
App_FEATURE_INIT(INMP441TestDemo);
 
static_library("mic_test") {
    sources = [
        "inmp441_demo.c",
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/hals/communication/wifi_lite/wifiservice",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal",
        "//ohos_bundles/@ohos/device_soc_hisilicon/hi3861v100/sdk_liteos/include",
        "//device/soc/hisilicon/hi3861v100/sdk_liteos/include"
    ]
}

分享到:
標(biāo)簽:OpenHarmony
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績?cè)u(píng)定