吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何用低成本MCU實(shí)現(xiàn)音樂(lè)頻譜顯示

jf_pJlTbmA9 ? 來(lái)源:恩智浦MCU加油站 ? 作者:恩智浦MCU加油站 ? 2023-10-18 17:10 ? 次閱讀

最近在做一個(gè)有趣的小項(xiàng)目,其中有一小部分的內(nèi)容的是使用FFT做音樂(lè)頻譜顯示。于是就有了下面這個(gè)音樂(lè)頻譜顯示的低成本方案,話(huà)不多說(shuō),看看低成本MCU如何實(shí)現(xiàn)FFT音樂(lè)頻譜顯示吧。

?音頻采集硬件電路

音頻采集的硬件電路比較簡(jiǎn)單,主要的器件就是麥克風(fēng)和LM358運(yùn)放。

wKgZomUD3h-AExqDAAHj6-dGOxg753.png

圖中電路R5可調(diào)電阻的作用是來(lái)調(diào)節(jié)運(yùn)放的增益。R4的作用的是給運(yùn)放一個(gè)VDD*R4/(R3+R4) 的直流偏置,這里加直流偏置是由于ADC只能采集正電壓值,為了不丟失負(fù)電壓的音頻信號(hào),給信號(hào)整體加了一個(gè)直流偏置。

但是這個(gè)圖還有一個(gè)小問(wèn)題,運(yùn)放的輸出端加了一個(gè)電容C2,C2會(huì)把直流偏置給隔掉。在設(shè)計(jì)時(shí),這個(gè)電容可以去掉。

下圖是按照上圖搭建的音頻采集電路的輸出信號(hào),圖中波動(dòng)信號(hào)是施加的外部音頻,是我們需要做音樂(lè)頻譜顯示需要的信號(hào)。該信號(hào)有一個(gè)2.3v的直流偏置,在后續(xù)處理時(shí)需要減去這個(gè)偏置。

wKgZomUD3iCAWlWfAAG8KbueJKc623.png

?CTimer+ADC+DMA 音頻信號(hào)采集

為了呼應(yīng)標(biāo)題,我們選擇的MCU是LPC845,這是NXP的一款低成本的MCU。考慮到我們平常聽(tīng)的音樂(lè)頻率大都低于5kHz,在軟件設(shè)計(jì)時(shí)設(shè)置ADC采樣頻率為10kHz。不要問(wèn)為什么,問(wèn)就是采樣定理。

LPC845的ADC有8個(gè)觸發(fā)源,我們使用CTiimer match3來(lái)觸發(fā)ADC,將寄存器SEQA_CTRL的bit 14:12設(shè)置為0x5。CTimer match 3的輸出頻率為10kHz。

為了確保我們采集數(shù)據(jù)的實(shí)時(shí)性,DMA建議配置成雙buffer模式,以防止采樣的數(shù)據(jù)被覆蓋掉。

?FFT音頻信號(hào)處理

在DMA搬運(yùn)ADC采樣值時(shí),使用了雙buffer來(lái)搬,ADC采樣值需要減去一個(gè)2.3V的直流偏置。

Samples[]數(shù)組用于FFT計(jì)算。

    //Calculate the FFT input buffer
   if(g_DmaTransferDoneFlag_A == true)
   {
 	  for (i=0; i<128; i++)
 	  {
 		 Samples[i] =(int16_t)(((g_AdcConvResult_A[i]   0xfff0) >> 4) - 2979);//substract the 2.3v offset in the Amplifier output
 	   }
 	 g_DmaTransferDoneFlag_A = false;

    }
   else if(g_DmaTransferDoneFlag_B == true)
   {
 	  for (i=0; i<128; i++)
 	  {
 		 Samples[i] =(int16_t)(((g_AdcConvResult_B[i]   0xfff0) >> 4) - 2979);//substract the 2.3v offset in the Amplifier output
 	  }
 	  g_DmaTransferDoneFlag_B = false;
   }

根據(jù)FFT算法的原理,在進(jìn)行FFT計(jì)算之前,還需要將ADC的采樣值Samples[]乘上一個(gè)窗函數(shù),這里我們使用的漢寧窗函數(shù),由于篇幅限制,具體原理可以去查看FFT算法相關(guān)的資料

    //If 'Window' isn't rectangular, apply window
    if(Window == Triangular){
        //Apply a triangular window to the data.
        for(Cnt = 0; Cnt>L2Len;
            else Samples[Cnt] = ((int32_t)Samples[Cnt]*((Len/2)-Cnt))>>L2Len;
        }
    }
    else if(Window == Hann){
        //Use the cosine window wavetable to apply a Hann windowing function to the samples
        for(Cnt = 0; Cnt>L2Len;
            Samples[Cnt] = ((int32_t)Samples[Cnt]*(int32_t)CosWindow[Index])>>(CWBD);
        }
    }

前面說(shuō)了這么多,F(xiàn)FT算法才是實(shí)現(xiàn)音樂(lè)頻譜顯示的關(guān)鍵部分(其實(shí)上邊每一步都缺一不可)。

我在網(wǎng)上找了好多FFT算法的資料,大家在做頻譜顯示時(shí),用到最多的就是CMSIS DSP的算法庫(kù)。于是乎,采用CMSIS DSP的庫(kù)貌似是首選。

但是不用不知道,一用才發(fā)現(xiàn),由于CMSIS DSP的庫(kù)使用的是查表的方式,我的64K Flash的LPC845輕輕松松就被撐爆了。沒(méi)辦法,只能改用其他方案。經(jīng)過(guò)不懈的查閱資料,在GitHub找到一份FFT算法的代碼,這個(gè)代碼寫(xiě)的非常簡(jiǎn)潔,而且用起來(lái)很好用,感謝發(fā)布者pyrohaz,下面是FFT代碼的一部分。

/*
  FIX_MPY() - fixed-point multiplication   scaling.
  Substitute inline assembly for hardware-specific
  optimization suited to a particluar DSP processor.
  Scaling ensures that result remains 16-bit.
*/
inline short FIX_MPY(short a, short b)
{
    /* shift right one less bit (i.e. 15-1) */
    int c = ((int)a * (int)b) >> 14;
    /* last bit shifted out = rounding-bit */
    b = c   0x01;
    /* last shift + rounding bit */
    a = (c >> 1) + b;
    return a;
}
fix_fft(short fr[], short fi[], short m, short inverse)函數(shù),F(xiàn)FT計(jì)算函數(shù)

int fix_fft(short fr[], short fi[], short m, short inverse)
{
    int mr, nn, i, j, l, k, istep, n, scale, shift;
    short qr, qi, tr, ti, wr, wi;

    n = 1 << m;

    /* max FFT size = N_WAVE */
    if (n > N_WAVE)
        return -1;

    mr = 0;
    nn = n - 1;
    scale = 0;

    /* decimation in time - re-order data */
    for (m=1; m<=nn; ++m) {
        l = n;
        do {
            l >>= 1;
        } while (mr+l > nn);
        mr = (mr   (l-1)) + l;

        if (mr <= m)
            continue;
        tr = fr[m];
        fr[m] = fr[mr];
        fr[mr] = tr;
        ti = fi[m];
        fi[m] = fi[mr];
        fi[mr] = ti;
    }       

接 fix_fft(short fr[], short fi[], short m, short inverse)函數(shù)

   l = 1;
    k = LOG2_N_WAVE-1;
    while (l < n) {
        if (inverse) {
            /* variable scaling, depending upon data */
            shift = 0;
            for (i=0; i 16383 || m > 16383) {
                    shift = 1;
                    break;
                }
            }
            if (shift)
                ++scale;
        } else {
            /*
                fixed scaling, for proper normalization --
                there will be log2(n) passes, so this results
                in an overall factor of 1/n, distributed to
                maximize arithmetic accuracy.
            */
            shift = 1;
        }

接fix_fftr(short f[], int m, int inverse)函數(shù)

 /*
            it may not be obvious, but the shift will be
            performed on each data point exactly once,
            during this pass.
        */
        istep = l << 1;
        for (m=0; m>= 1;
                wi >>= 1;
            }
            for (i=m; i>= 1;
                    qi >>= 1;
                }
                fr[j] = qr - tr;
                fi[j] = qi - ti;
                fr[i] = qr + tr;
                fi[i] = qi + ti;
            }
        }
        --k;
        l = istep;
    }
    return scale;
}


/*
  fix_fftr() - forward/inverse FFT on array of real numbers.
  Real FFT/iFFT using half-size complex FFT by distributing
  even/odd samples into real/imaginary arrays respectively.
  In order to save data space (i.e. to avoid two arrays, one
  for real, one for imaginary samples), we proceed in the
  following two steps: a) samples are rearranged in the real
  array so that all even samples are in places 0-(N/2-1) and
  all imaginary samples in places (N/2)-(N-1), and b) fix_fft
  is called with fr and fi pointing to index 0 and index N/2
  respectively in the original array. The above guarantees
  that fix_fft "sees" consecutive real samples as alternating
  real and imaginary samples in the complex array.
*/
int fix_fftr(short f[], int m, int inverse)
{
    int i, N = 1<<(m-1), scale = 0;
    short tt, *fr=f, *fi= f[N];

    if (inverse)
        scale = fix_fft(fi, fr, m-1, inverse);
    for (i=1; i

int fix_fft(short fr[], short fi[], short m, short inverse) 是FFT算法的計(jì)算函數(shù),fr[]是ADC采集到信號(hào)值的實(shí)部,fi[]是ADC采集到信號(hào)值的虛部。經(jīng)過(guò)fix_fft函數(shù)處理之后,fr[]是FFT計(jì)算所得實(shí)部,fi[]是計(jì)算所得的虛部。

我們最終要顯示的音樂(lè)頻譜其實(shí)是FFT頻域中音頻的幅值,幅值的計(jì)算是實(shí)部的平方+虛部的平方開(kāi)根號(hào)。下面是具體的幅值計(jì)算部分的代碼,每一個(gè)幅值點(diǎn)對(duì)應(yīng)OLED的一列像素點(diǎn)。

//Calculate the magnitude
    for(Cnt = 0; Cnt>ColumnFilter; //calculate the DB
            }
            else{
                Col[Index] += (BufSum-Col[Index])>>ColumnFilter;  //calculate the amplitude
            }

            //Limit maximum column value
            if(Col[Index] >= YPix-9) Col[Index] = YPix-10;

            IndO = Index;
            BufSum = 0;
        }
    }

來(lái)源:恩智浦MCU加油站

免責(zé)聲明:本文為轉(zhuǎn)載文章,轉(zhuǎn)載此文目的在于傳遞更多信息,版權(quán)歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權(quán)問(wèn)題,請(qǐng)聯(lián)系小編進(jìn)行處理

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    17319

    瀏覽量

    352650
  • adc
    adc
    +關(guān)注

    關(guān)注

    99

    文章

    6533

    瀏覽量

    545757
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于MCU的FFT音樂(lè)頻譜顯示方案

    最近在做一個(gè)有趣的小項(xiàng)目,其中有一小部分的內(nèi)容的是使用FFT做音樂(lè)頻譜顯示。于是就有了下面這個(gè)音樂(lè)頻譜
    發(fā)表于 09-08 09:05 ?1792次閱讀

    怎樣實(shí)現(xiàn)根據(jù)音樂(lè)跳動(dòng)的頻譜顯示

    最近在網(wǎng)上看見(jiàn)好多人做的可以跟著音樂(lè)的節(jié)奏跳動(dòng)的頻譜顯示,主要就是FFT用51單片機(jī)怎么實(shí)現(xiàn)?求大神幫助,謝謝{:soso_e149:}
    發(fā)表于 09-16 11:42

    求基于單片機(jī)的音樂(lè)頻譜顯示設(shè)計(jì)

    各位大神,跪求基于單片機(jī)的音樂(lè)頻譜顯示設(shè)計(jì),主要要求是:音樂(lè)不是外接的音樂(lè),需要自己寫(xiě)音樂(lè)程序。
    發(fā)表于 04-11 22:52

    音樂(lè)頻譜顯示 制作

    DIY音樂(lè)頻譜顯示
    發(fā)表于 04-22 21:55

    很炫的音樂(lè)頻譜——五彩音樂(lè)頻譜顯示

    ` 本帖最后由 chinayuyi 于 2013-5-27 17:00 編輯 很炫的音樂(lè)頻譜——五彩音樂(lè)頻譜顯示器附出處:百度下“羽翼電
    發(fā)表于 05-27 16:57

    何用低成本FPGA解決高速存儲(chǔ)器接口挑戰(zhàn)?

    何用低成本FPGA解決高速存儲(chǔ)器接口挑戰(zhàn)?
    發(fā)表于 04-29 06:59

    基于RT-Thread+RA6M4的FFT音樂(lè)頻譜顯示器制作方案

    1、基于RT-Thread+RA6M4的FFT音樂(lè)頻譜顯示器制作本項(xiàng)目制作了一個(gè)FFT音樂(lè)頻譜顯示
    發(fā)表于 07-25 12:46

    音樂(lè)頻譜-PCB及代碼

    基于stc12c5a單片機(jī)的音樂(lè)頻譜顯示屏幕的制作,可以根據(jù)音樂(lè)顯示出不同的頻譜,且燈的顏色可改
    發(fā)表于 02-29 15:08 ?66次下載

    基于增強(qiáng)型8051單片機(jī)的音樂(lè)頻譜顯示器的設(shè)計(jì)

    基于增強(qiáng)型8051單片機(jī)的音樂(lè)頻譜顯示器的設(shè)計(jì)基于增強(qiáng)型8051單片機(jī)的音樂(lè)頻譜顯示器的設(shè)計(jì)
    發(fā)表于 05-20 16:50 ?26次下載

    DIY音樂(lè)頻譜顯示源代碼(源碼)

    51單片機(jī)DIY音樂(lè)頻譜顯示教程+源代碼,感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 11-22 11:15 ?100次下載

    stm32音樂(lè)頻譜OLED屏顯示

    基于STM32F103和FFT變換的音樂(lè)頻譜顯示
    發(fā)表于 06-17 14:52 ?54次下載

    MCU如何實(shí)現(xiàn)FFT音樂(lè)頻譜顯示

    最近在做一個(gè)有趣的小項(xiàng)目,其中有一小部分的內(nèi)容的是使用FFT做音樂(lè)頻譜顯示。于是就有了下面這個(gè)音樂(lè)頻譜
    的頭像 發(fā)表于 09-08 09:07 ?3959次閱讀

    低成本 MCU 助力電池組系統(tǒng)實(shí)現(xiàn)強(qiáng)大功能

    低成本 MCU 助力電池組系統(tǒng)實(shí)現(xiàn)強(qiáng)大功能
    發(fā)表于 10-28 12:00 ?0次下載
    <b class='flag-5'>低成本</b> <b class='flag-5'>MCU</b> 助力電池組系統(tǒng)<b class='flag-5'>實(shí)現(xiàn)</b>強(qiáng)大功能

    學(xué)校教學(xué)建議選擇低成本的USB頻譜

    USB頻譜儀是符合教學(xué)需求的低成本頻譜分析儀,首先重量不足100克,體積形似U盤(pán),結(jié)構(gòu)緊湊,操作臺(tái)占用空間小,無(wú)需外接電源,連接電腦屏幕顯示,電腦操作軟件,易操作界面,直觀方便,是教
    的頭像 發(fā)表于 05-17 10:39 ?382次閱讀
    學(xué)校教學(xué)建議選擇<b class='flag-5'>低成本</b>的USB<b class='flag-5'>頻譜</b>儀

    使用MSP430 MCU實(shí)現(xiàn)低成本語(yǔ)音

    電子發(fā)燒友網(wǎng)站提供《使用MSP430 MCU實(shí)現(xiàn)低成本語(yǔ)音.pdf》資料免費(fèi)下載
    發(fā)表于 10-21 10:02 ?0次下載
    使用MSP430 <b class='flag-5'>MCU</b><b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>低成本</b>語(yǔ)音
    真钱百家乐官网游戏排行| 名人百家乐官网的玩法技巧和规则| 百家乐官网神仙道官网| 天等县| 88娱乐城注册| 菲律宾云顶国际| 大发888老虎机| 大发888真钱游戏下载官网| 全讯网22335555| 免费百家乐追号工具| 马德里百家乐的玩法技巧和规则| 百家乐双龙出海| 百家乐注册18元体验金| 太阳城百家乐作弊| 至尊百家乐节目单| 澳门百家乐登陆网址| 百家乐的方法和公式| 百家乐规则澳门| 百家乐代理龙虎| 百家乐官网14克粘土筹码| 做生意门口禁忌| 百家乐免费是玩| 川宜百家乐软件| 百家乐的必赢方法| 百家乐百家乐视频| 网上百家乐真的假的| 怎么玩百家乐能赢钱| 百家乐筹码币方形| 百家乐巴厘岛上海在线| 蓝盾百家乐洗码| 真人百家乐网络游戏信誉怎么样 | 网上百家乐官网指| 24山之巽山乾向水法及兼家分针| 百家乐赌博机吧| 川宜百家乐破解版| 百家乐投注网中国体育| 澳门百家乐怎么看小路| 百家乐高额投注| 百家乐机器出千| 综合百家乐博彩论坛| 新濠百家乐的玩法技巧和规则 |