首頁 > 評測 > PSoC 6評測第四篇-錄音與放音

PSoC 6評測第四篇-錄音與放音

PSoC 6   耳機(jī)   PDM   PCM   ADC采樣   
  • 作者:zhanzr
  • 來源:21ic
  • [導(dǎo)讀]
  • 寫上一篇關(guān)于EInk的文章的時候,就想著要寫這一篇了.因為作者本人除了喜歡閱讀之外,還比較喜歡音樂.也喜歡聽也喜歡唱K,故此對音頻相關(guān)的技術(shù)也較為感興趣,至于水平只能說稍知一二.看到這個CY8CKIT開發(fā)套件上帶有數(shù)字麥克風(fēng),就動了心思.本文使用開發(fā)板子上的資源做一個簡單的錄音與放音實驗,研究一下相關(guān)知識.
image11.png

圖 8 KHz定時器用作播放更新

注意產(chǎn)生的頻率有一定的誤差,只要在一定范圍內(nèi)是可以接受的.某些要求苛刻的音頻設(shè)備使用比較不常見的晶體頻率即是為了最大程度提高播放精度.

根據(jù)現(xiàn)有條件,直接將耳機(jī)的兩個通道分別接在VDAC與PWM輸出上:

image12.jpg

圖 硬件連接細(xì)節(jié)

根據(jù)實驗,阻抗大的耳機(jī)效果好一點點,因為引腳驅(qū)動有限的緣故.

image13.jpg

圖 入耳式的耳機(jī)阻抗稍大一點

軟件

因為主要模塊都是硬件生成的,所以軟件上也只是控制一個流程而已.流程就是錄制-播放兩個過程進(jìn)行循環(huán).此例子與上一篇的例子不同,僅僅使用了Cortex M4的內(nèi)核,M0+內(nèi)核除了使能Cortex M4之外沒有做任何事情.

初始化各模塊:

/* Enable global interrupts. */

__enable_irq();

/* Initialize the PCM interrupt and enable it */

Cy_SysInt_Init(&PCM_ISR_cfg, PCM_ISR_Handler);

NVIC_EnableIRQ(PCM_ISR_cfg.intrSrc);

//The Audio Play ISR

Cy_SysInt_Init(&AudioPlayISR_cfg, AudioPlay_ISR_Handler);

NVIC_EnableIRQ(AudioPlayISR_cfg.intrSrc);

/* Start the UART component for reporting the volume */

UART_Start();

AudioTimer_Start();

VDAC_Start();

AudioPWM_Start();

/* Star the PCM component */

Cy_PDM_PCM_Init(PDM_PCM_HW, &PDM_PCM_config);

Cy_PDM_PCM_Enable(PDM_PCM_HW);

此時各模塊已經(jīng)開始工作,剛剛開始是錄音模式.

PDM_PCM的ISR:

void PCM_ISR_Handler(void)

{

/* Set the PCM flag */

flag = 1;

/* Disable PCM ISR to avoid multiple calls to this ISR */

NVIC_DisableIRQ(PCM_ISR_cfg.intrSrc);

}

此處做標(biāo)記表示有一個FIFO的數(shù)據(jù)轉(zhuǎn)換為PCM完成需要拿走.主循環(huán)中將其放入播放buffer:

for (uint32_t i = 0; i < PDM_PCM_RX_FIFO_TRG_LVL; i++)

{

g_AudioBuff[g_RecIdx++]=(int16_t)PDM_PCM_ReadFifo();

}

一旦buffer滿了即轉(zhuǎn)為播放模式,當(dāng)中需要用戶按下SW2按鈕:

printf("To Enter Play Mode.\n");

printf("Press SW2\n");

/* Clear SW2 interrupt */

Cy_GPIO_ClearInterrupt(SW2_PORT, SW2_NUM);

while(0 == (Cy_GPIO_GetInterruptStatus(SW2_PORT, SW2_NUM)))

{

__WFI();

}

printf("Play...\n");

g_playRecFlag = true;

g_PlayIdx = 0;

在Audio Timer的ISR中更新播放Sample:

void AudioPlay_ISR_Handler(void)

{

if((true == g_playRecFlag) && (g_PlayIdx < SAMPLE_SIZE))

{

int16_t tmpV16 = g_AudioBuff[g_PlayIdx++];

VDAC_SetValueBuffered(tmpV16>>4);

int8_t tmpV8 = tmpV16/256;

if(tmpV8 < 0)

{

AudioPWM_SetCompare0(256 - tmpV8);

}

else

{

AudioPWM_SetCompare0(127 + tmpV8);

}

}

AudioTimer_ClearInterrupt(CY_TCPWM_INT_ON_CC_OR_TC);

}

注意采集進(jìn)來的數(shù)據(jù)為16bit有符號數(shù)據(jù),而DAC為12bit,PWM為8bit,需要加以轉(zhuǎn)換.一旦播放完畢需要用戶按下SW2重新開始錄音.過程與上面的過程類似,反復(fù)循環(huán).

根據(jù)實際體驗,目前這個PDM_PCM轉(zhuǎn)換結(jié)果不是很完美,噪音較多,也有可能是本人使用不當(dāng).如有進(jìn)一步的研究結(jié)果再來匯報.

總結(jié),資源與參考

Cypress的這個開發(fā)板子CY8CKIT能玩的點較多,拿到板子忍不住做了不少實驗.其實編輯說搞一兩篇就算交差了,這次也算超額完成任務(wù).官方也有一篇音頻例程,講的是檢測當(dāng)前環(huán)境的噪音水平,本人認(rèn)為過于簡單于是在此基礎(chǔ)上完成了本文的實驗.

關(guān)于音頻,本人一向很感興趣,以前也寫過不少此方面的文章.包括本文做的一些實驗其實是之前文章的延伸,故此一些過于細(xì)節(jié)的部分不想贅述,感興趣的讀者可以在本站找一下之前的文章配合閱讀.目前人工智能,語音識別比較熱門,作者也有心再做一點此方面的實驗,但是這個話題就太大,不知道能否寫出文章來.

代碼下載連接:

鏈接: https://pan.baidu.com/s/1nw4o2Pr 密碼: cjtc

  • 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!

網(wǎng)友評論

  • 聯(lián)系人:巧克力娃娃
  • 郵箱:board@21ic.com
  • 我要投稿
  • 歡迎入駐,開放投稿

熱門標(biāo)簽
項目外包 more+