版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、 音頻接口程序設(shè)計(jì) 南京大學(xué) 黃開(kāi)成 101180046 摘要本實(shí)驗(yàn)通過(guò)對(duì)兩個(gè)音頻設(shè)備dsp和mixer的編程,學(xué)習(xí)了與數(shù)字音頻相關(guān)的幾個(gè)重要技術(shù)指標(biāo)(量化位數(shù)、采樣頻率、聲道數(shù)),完成了對(duì)音頻文件的播放和錄放音并且通過(guò)線程實(shí)現(xiàn)了對(duì)音量的實(shí)時(shí)控制。此外通過(guò)輸入正弦波觀察輸出到示波器和framebuffer的波形,驗(yàn)證了奈奎斯特采樣理論。鞏固了嵌入式開(kāi)發(fā)中驅(qū)動(dòng)程序、系統(tǒng)調(diào)用和應(yīng)用程序的關(guān)系。一、實(shí)驗(yàn)?zāi)康?、了解音頻編、解碼的作用和工作原理。2、學(xué)習(xí)Linux系統(tǒng)的音頻接口編程方法。二、原理概述1、數(shù)字音頻 音頻信號(hào)是一種連續(xù)變化的模擬信號(hào),但計(jì)算機(jī)只能處理和記錄二進(jìn)制的數(shù)字信號(hào),因而由自然音源得
2、到的音頻信號(hào)必須經(jīng)過(guò)一定的變換,成為數(shù)字音頻信號(hào)之后才能送到計(jì)算機(jī)中做進(jìn)一步的處理。模擬音頻信號(hào)數(shù)字化的典型方法是對(duì)時(shí)間坐標(biāo)按相等的時(shí)間間隔做采樣,對(duì)振幅做量化。從本質(zhì)上講,采樣是時(shí)間上的數(shù)字化,而量化則是幅度上的數(shù)字化。 數(shù)字化的過(guò)程中涉及到在編程過(guò)程中需要設(shè)置的三個(gè)重要的技術(shù)指標(biāo):(1)采樣頻率 單位時(shí)間內(nèi)的采樣次數(shù)稱為采樣頻率。依據(jù)奈奎斯特采樣理論:只有采樣頻率高于輸入信號(hào)最高頻率的兩倍才能從采樣信號(hào)序列中重構(gòu)原始信號(hào)。正常人聽(tīng)覺(jué)的頻率范圍大約在20Hz20kHz之間,因此為保證聲音不失真,采樣頻率應(yīng)該在40kHz左右。常用的音頻采樣頻率有8kHz、11.025kHz、22.05kHz、
3、16kHz、37.8kHz、44.1kHz、48kHz等。如果采用更高的采樣頻率,還可以達(dá)到DVD的音質(zhì)。(2)量化位數(shù) 數(shù)字化模擬音頻信號(hào)的幅度時(shí)決定模擬信號(hào)數(shù)字化以后的動(dòng)態(tài)范圍,常用的有8位、12位和16位。量化位越高,信號(hào)的動(dòng)態(tài)范圍越大,數(shù)字化后的音頻信號(hào)就越可能接近原始信號(hào),但所需要的存儲(chǔ)空間也越大。(3)聲道數(shù) 聲道數(shù)是反映音頻數(shù)字化質(zhì)量的另一個(gè)重要因素,有單聲道、雙聲道和多聲道之分。雙聲道又稱為立體聲,在硬件中有兩條線路,音質(zhì)和音色都要優(yōu)于單聲道,但數(shù)字化后占據(jù)的存儲(chǔ)空間的大小要比單聲道多一倍。多聲道能提供更好的聽(tīng)覺(jué)感受,不過(guò)占用的存儲(chǔ)空間更大。2、音頻設(shè)備文件 在8253驅(qū)動(dòng)編程
4、和IO接口實(shí)驗(yàn)中我們需要自己編寫(xiě)驅(qū)動(dòng)程序。而本次實(shí)驗(yàn)中,只要在內(nèi)核編譯時(shí)選中Sound ->Sound support和Intel PXA27x AC97 audio就可以將驅(qū)動(dòng)編譯進(jìn)內(nèi)核,我們只要通過(guò)閱讀內(nèi)核目錄/usr/include/linux下的soundcard.h頭文件就可以完成應(yīng)用程序的編寫(xiě)。應(yīng)用程序可以通過(guò)驅(qū)動(dòng)程序提供的系統(tǒng)調(diào)用來(lái)對(duì)以下的音頻設(shè)備文件進(jìn)行操作: /dev/dsp(主設(shè)備號(hào)14,次設(shè)備號(hào)3):負(fù)責(zé)音頻數(shù)據(jù)的輸入和輸出(即A/D、D/A),工作方式設(shè)置(采樣/輸出頻率、通道數(shù)、數(shù)據(jù)格式等)。簡(jiǎn)單而言就是向該設(shè)備寫(xiě)數(shù)據(jù)(write)即意味著激活聲卡上的D/A轉(zhuǎn)換
5、器進(jìn)行放音,而從該設(shè)備讀數(shù)據(jù)(read)則意味著激活聲卡上的A/D轉(zhuǎn)換器進(jìn)行錄音。 /dev/mixer(主設(shè)備號(hào)14, 次設(shè)備號(hào)0),將多個(gè)信號(hào)組合或者疊加在一起,對(duì)于不同的聲卡來(lái)說(shuō),其混音器的作用可能各不相同。通常負(fù)責(zé)混音、音量設(shè)置、音源、高低音等等。三、實(shí)驗(yàn)過(guò)程1.Dsp編程 在從dsp設(shè)備讀取數(shù)據(jù)時(shí),從聲卡輸入的模擬信號(hào)經(jīng)過(guò)A/D轉(zhuǎn)換器變成數(shù)字采樣后的樣本,保存在聲卡驅(qū)動(dòng)程序的內(nèi)核緩沖區(qū)中,當(dāng)應(yīng)用程序通過(guò)read系統(tǒng)調(diào)用從聲卡讀取數(shù)據(jù)時(shí),保存在內(nèi)核緩沖區(qū)中的數(shù)字采樣結(jié)果將被復(fù)制到應(yīng)用程序所指定的用戶緩沖區(qū)中。需要指出的是,聲卡采樣頻率是由內(nèi)核中的驅(qū)動(dòng)程序所決定的,而不取決于應(yīng)用程序從聲
6、卡讀取數(shù)據(jù)的速度。如果應(yīng)用程序讀取數(shù)據(jù)的速度過(guò)慢,以致低于聲卡的采樣頻率,那么多余的數(shù)據(jù)將會(huì)被丟棄;如果讀取數(shù)據(jù)的速度過(guò)快,以致高于聲卡的采樣頻率,那么聲卡驅(qū)動(dòng)程序?qū)?huì)阻塞那些請(qǐng)求數(shù)據(jù)的應(yīng)用程序,直到新的數(shù)據(jù)到來(lái)為止。 在向dsp設(shè)備寫(xiě)入數(shù)據(jù)時(shí),數(shù)字信號(hào)會(huì)經(jīng)過(guò)D/A轉(zhuǎn)換器變成模擬信號(hào),然后產(chǎn)生出聲音。應(yīng)用程序?qū)懭霐?shù)據(jù)的速度同樣應(yīng)該與聲卡的采樣頻率相匹配,過(guò)慢的話會(huì)產(chǎn)生聲音暫?;蛘咄nD的現(xiàn)象,而過(guò)快的話又會(huì)被內(nèi)核中的聲卡驅(qū)動(dòng)程序阻塞,直到硬件有能力處理新的數(shù)據(jù)為止。(1)打開(kāi)dsp設(shè)備 fd_dsp=open("/dev/dsp",O_RDWR); / 以讀寫(xiě)的方式打開(kāi)/de
7、v/dsp,以便同時(shí)進(jìn)行聲音的輸入和輸出if(fd_dsp<0) printf("open of /dev/dsp failed!n"); exit(1); (2)量化位數(shù)、聲道數(shù)、采樣頻率的設(shè)置 查看soundcard.h可知,聲卡默認(rèn)為8位無(wú)符號(hào)數(shù)據(jù)、單聲道、8KHz采樣率。有關(guān)三個(gè)參數(shù)設(shè)置的宏有: SNDCTL_DSP_SETFMT 聲卡采樣格式 SNDCTL_DSP_STEREO 聲卡工作時(shí)的聲道數(shù)目 SNDCTL_DSP_SPEED 聲卡采樣頻率還有一些別名的定義: /* Some alias names */ #define SOUND_PCM_WRITE
8、_BITS SNDCTL_DSP_SETFMT#define SOUND_PCM_WRITE_CHANNELS SNDCTL_DSP_CHANNELS#define SOUND_PCM_WRITE_RATE SNDCTL_DSP_SPEED 所以程序中使用SOUND_PCM_WRITE_RATE或者SNDCTL_DSP_SPEED來(lái)設(shè)置采樣頻率是一致的。實(shí)際編程如下: #define Rate 44100 #define Size 16 #define Channel 2 arg=Size; /量化位數(shù) status=ioctl(fd_dsp,SOUND_PCM_WRITE_BITS,&
9、;arg); if(status=-1|arg!=Size)printf("Unable to set sample sizen");arg=Channel; /設(shè)置聲道數(shù) status=ioctl(fd_dsp,SOUND_PCM_WRITE_CHANNELS,&arg); if(status=-1|arg!=Channel)printf("Unable to set channeln"); arg=Rate; /設(shè)置采樣頻率 status=ioctl(fd_dsp,SOUND_PCM_WRITE_RATE,&arg); if(stat
10、us=-1|arg!=Rate)printf("Unable to set raten");即通過(guò)ioctl()系統(tǒng)調(diào)用來(lái)設(shè)置。2.Mixer編程 混音器電路通常由兩個(gè)部分組成:輸入混音器和輸出混音器。輸入混音器負(fù)責(zé)從多個(gè)不同的信號(hào)源接收模擬信號(hào),這些信號(hào)源有時(shí)也被稱為混音通道或者混音設(shè)備。模擬信號(hào)通過(guò)增益控制器和由軟件控制的音量調(diào)節(jié)器后,在不同的混音通道中分別進(jìn)行調(diào)制,然后被送到輸入混音器中進(jìn)行聲音的合成?;煲羝魃系碾娮娱_(kāi)關(guān)可以控制不同通道中的信號(hào)與混音器相連,有些聲卡只允許連接一個(gè)混音通道作為錄音的音源,而有些聲卡則允許對(duì)混音通道做任意的連接。經(jīng)過(guò)輸入混音器處理后的信號(hào)
11、仍然為模擬信號(hào),它們將被送到A/D轉(zhuǎn)換器進(jìn)行數(shù)字化處理。 輸出混音器的工作原理與輸入混音器類似,同樣也有多個(gè)信號(hào)源與混音器相連,并且事先都經(jīng)過(guò)了增益調(diào)節(jié)。當(dāng)輸出混音器對(duì)所有的模擬信號(hào)進(jìn)行混合之后,通常還會(huì)有一個(gè)總控增益調(diào)節(jié)器來(lái)控制輸出聲音的大小,此外,還有一些音調(diào)控制器來(lái)調(diào)節(jié)輸出聲音的音調(diào)。經(jīng)過(guò)輸出混音器處理后的信號(hào)也是模擬信號(hào),它們最終會(huì)被送給喇叭或者其他的模擬輸出設(shè)備。 查看soundcard.h文件,可以看到幾個(gè)主要的用于混音器控制命令的宏:#define SOUND_MIXER_NRDEVICES25 /獲取設(shè)備數(shù)量#define SOUND_MIXER_VOLUME 0 /總音量設(shè)置
12、, 其取值范圍為0100#define SOUND_MIXER_BASS 1 /低音設(shè)置#define SOUND_MIXER_TREBLE 2 /高音設(shè)置#define SOUND_MIXER_PCM 4 /主D/A轉(zhuǎn)換器#define SOUND_MIXER_SPEAKER 5 /PC喇叭#define SOUND_MIXER_LINE 6 /音頻線輸入#define SOUND_MIXER_MIC 7 /麥克風(fēng)輸入#define SOUND_MIXER_CD 8 /CD輸入#define SOUND_MIXER_ALTPCM 10 /從D/A轉(zhuǎn)換器#define SOUND_MIXER_
13、RECLEV 11 /錄音音量#define SOUND_MIXER_IGAIN 12 /輸入增益#define SOUND_MIXER_OGAIN 13 /輸出增益#define SOUND_MIXER_LINE1 14 /聲卡的第1輸入#define SOUND_MIXER_LINE2 15 /聲卡的第2輸入#define SOUND_MIXER_LINE3 16 /聲卡的第3輸入在進(jìn)行混音器編程時(shí),可以使用如下方式來(lái)讀取混音通道的增益大?。篗IXER_READ(dev)讀取混音通道的增益大小MIXER_WRITE(dev)設(shè)置混音通道的增益大小 其中dev可以是具體的通道名稱或是soun
14、dcard.h所提供的名稱后面對(duì)應(yīng)的數(shù)字。 例如在獲取麥克風(fēng)的輸入增益時(shí),可以使用如下的代碼: fd_mixer = open("/dev/mixer", O_RDONLY); if(fd_mixer<0) printf("open of /dev/mixer failed!n"); exit(2); int vol; ioctl(fd_mixer, MIXER_READ(SOUND_MIXER_MIC), &vol); printf("Mic gain is %d %n", vol); 對(duì)于只有一個(gè)混音通道的單聲道設(shè)備
15、來(lái)說(shuō),返回的增益大小保存在低字節(jié)中。 而對(duì)于支持多個(gè)混音通道的雙聲道設(shè)備來(lái)說(shuō),返回的增益大小實(shí)際上包括兩個(gè)部分,分別代表左、右兩個(gè)聲道的值,其中低位字節(jié)保存左聲道的音量,而高位字節(jié)則保存右聲道的音量。 類似的,設(shè)置麥克風(fēng)的輸入增益時(shí),可以使用如下代碼: vol=(right<<8&0xff00)|(left&0x00ff); ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_MIC),&vol); 此外,因?yàn)椴煌穆暱ㄋ峁┑幕煲羝髻Y源是有所區(qū)別的,所以需要檢查混音設(shè)備的有效性,聲卡驅(qū)動(dòng)程序提供了多個(gè)ioctl系統(tǒng)調(diào)用來(lái)獲得混音器
16、的信息,它們通常返回一個(gè)整型的位掩碼,其中每一位分別代表一個(gè)特定的混音通道,如果相應(yīng)的位為1,則說(shuō)明與之對(duì)應(yīng)的混音通道是可用的。soundcard.h文件提供了如下的宏:SOUND_MIXER_READ_DEVMASK 獲取的位掩碼指示可用混音通道SOUND_MIXER_READ_RECMASK 獲取的位掩碼指示可作為錄音源的通道例如,檢查麥克風(fēng)輸入是否是一個(gè)有效的混音通道:ioctl(fd_mixer, MIXER_READ(SOUND_MIXER_DEVMASK), &devmask); if (devmask & SOUND_MIXER_MIC) printf("
17、;The MIC input is supported"); 在上文中已經(jīng)提到,每個(gè)混音通道都有一個(gè)相應(yīng)的數(shù)字與之對(duì)應(yīng),代碼中將位掩碼與SOUND_MIXER_MIC相與(即和7相與),返回值非零的話就說(shuō)明該混音通道是有效的。檢查麥克風(fēng)輸入是否一個(gè)有效的錄音源:ioctl(fd_mixer, MIXER_READ(SOUND_MIXER_RECMASK), &recmask); if (recmask &SOUND_MIXER_MIC) printf("The MIC input can be a recording source"); 實(shí)際編程如
18、下: int left=80, right=80; vol=(right<<8&0xff00)|(left&0x00ff); /設(shè)置混音器mixer音量 ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_VOLUME), &vol); vol=88; /主D/A轉(zhuǎn)換器 ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_PCM), &vol); vol=100; /麥克風(fēng)輸入 ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_MIC), &vol); vol=1
19、00; /輸入增益 ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_IGAIN), &vol);3.終端重定向?qū)崿F(xiàn)錄放音功能對(duì)聲卡的操作可以簡(jiǎn)單的通過(guò)設(shè)備文件節(jié)點(diǎn)/dev/dsp來(lái)進(jìn)行。#cat /dev/dsp >voice (錄音)c#cat voice>/dev/dsp (放音)能夠不失真的將錄入的聲音放出來(lái)。將wav文件重定向到/dev/dsp如下:#cat hello.wav >/dev/dsp 能夠播放hello.wav文件。關(guān)于重定向:利用shell重定向操作符,用戶可以更改從何處得到輸入以及把輸出發(fā)送到哪里的命令。輸出重定
20、向允許用戶把進(jìn)程的輸出保存在文件中,然后用戶就可以對(duì)此進(jìn)行編輯等操作。4.編寫(xiě)程序?qū)崿F(xiàn)錄放音功能(1)錄音放音 前面已經(jīng)說(shuō)過(guò)向/dev/dsp寫(xiě)數(shù)據(jù)(write)即意味著激活聲卡上的D/A轉(zhuǎn)換器進(jìn)行放音,而從/dev/dsp讀數(shù)據(jù)(read)則意味著激活聲卡上的A/D轉(zhuǎn)換器進(jìn)行錄音。因而實(shí)際編程如下:unsigned char bufLenth*Rate*Size*Channel/8;/用于保存錄音數(shù)據(jù)的內(nèi)存緩沖區(qū) printf("nSay something:n"); status = read(fd_dsp, buf, sizeof(buf); /read,即錄音 if
21、 (status != sizeof(buf) perror("nread wrong number of bytes"); printf("You said:n"); status = write(fd_dsp, buf, sizeof(buf); /write,即放音 /在繼續(xù)錄音前等待錄音結(jié)束 if (status != sizeof(buf) perror("nwrote wrong number of bytes"); status = ioctl(fd_dsp, SOUND_PCM_SYNC, 0); /等待聲卡把緩沖區(qū)的
22、內(nèi)容播放完 if (status = -1) perror("nSOUND_PCM_SYNC ioctl failed"); 程序?qū)崿F(xiàn)了正常的錄音和放音。(2)播放wav文件 Wav是一種古老的音頻文件格式,由微軟開(kāi)發(fā),應(yīng)用非常廣泛。它使用三個(gè)參數(shù)來(lái)表示聲音:采樣位數(shù)、采樣頻率和聲道數(shù)。Wav都有一個(gè)文件頭,這個(gè)文件頭音頻流的編碼參數(shù)。Wav格式文件所占容量(KB) = (取樣頻率 *量化位數(shù) * 聲道) * 時(shí)間 / 8 ,其大小不隨音量大小及清晰度的變化而變化。 實(shí)現(xiàn)代碼如下: unsigned char buffer100; FILE * wav; wav=fopen
23、("hello.wav","r"); /把音頻文件打開(kāi)為文件流 puts("open successedn"); while(!feof(wav) fread(buffer,sizeof(buffer),1,wav); /將文件流讀入緩沖區(qū) write(fd_dsp,buffer,sizeof(buffer); /write,即播放音頻文件 其中feof(FILE *stream)為測(cè)試文件尾函數(shù),當(dāng)文件讀完時(shí)返回非零值。 程序?qū)崿F(xiàn)了歌曲的播放。 此時(shí)聯(lián)想到播放器應(yīng)該能夠控制音量,于是利用ioctl對(duì)/dev/dsp進(jìn)行設(shè)置,用按鍵&
24、#39;4'、'5'代表+ -音量實(shí)現(xiàn)調(diào)節(jié)音量功能。起初我把按鍵識(shí)別放在主函數(shù)的兩個(gè)case中,程序?qū)崿F(xiàn)的現(xiàn)象是在放音的過(guò)程中按下4,音量并沒(méi)有馬上增加而是直到下一次放音的時(shí)候音量才增加。這與設(shè)計(jì)初衷在任何時(shí)刻按下鍵音量就能夠得到改變不同。檢查程序邏輯確實(shí)不能使音量馬上改變,于是決定用多線程來(lái)實(shí)現(xiàn)這一功能。實(shí)現(xiàn)程序如下: int vol_set(int left ,int right) /調(diào)節(jié)音量子函數(shù) int arg; int ret_val; int fd_mixer; fd_mixer = open("/dev/mixer",O_RDWR);
25、arg=(right<<8&0xff00)|(left&0x00ff); ret_val=ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_VOLUME),&arg); return ret_val; void key() char c; while(1) c=getchar(); switch(c) case '4': printf("the left volume is %d%, the right is %d%n",left,right); if(left<100) left+=10
26、; else printf("warn:highest volume"); if(right<100) right+=10; else printf("warn:highest volume"); vol_set(left,right); printf("the left volume is %d%, the right is %d%n",left,right); break; case '5': printf("the left volume is %d%, the right is %d%n&quo
27、t;,left,right); if(left>0) left-=10; else printf("warn:lowest volume"); if(right>0) right-=10; else printf("warn:lowest volume"); vol_set(left,right); printf("the left volume is %d%, the right is %d%n",left,right); break; int main() pthread_t keyscanf; /保存進(jìn)程號(hào) pthr
28、ead_create(&keyscanf,NULL,(void*)key,NULL); /創(chuàng)建一個(gè)進(jìn)程 查看pthread_create的聲明:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 其中 thread用于返回創(chuàng)建的線程的ID;attr用于指定的被創(chuàng)建的線程的屬性,上面的函數(shù)中使用NULL,表示使用默認(rèn)的屬性; start_routine是一個(gè)函數(shù)指針,指向線程被創(chuàng)建后要調(diào)用的函數(shù); arg用于給線程傳遞參
29、數(shù),在上面的函數(shù)中沒(méi)有傳遞參數(shù),所以使用了NULL。 注意:在頭文件要加上 #include <pthread.h> 在編譯時(shí)要加上 -lpthread 在目標(biāo)機(jī)終端 /lib (即動(dòng)態(tài)鏈接libpthread-o.10.so) 最終實(shí)現(xiàn)的結(jié)果是在任意時(shí)刻按下4或者5都能夠立即改變音量,并且在屏幕上顯示改變前和改變后兩個(gè)聲道的百分比音量。把錄放音、播放wav文件以及實(shí)時(shí)控制音量和退出寫(xiě)在同一個(gè)程序中,見(jiàn)附程序。4.用信號(hào)源輸出正弦波接到mic端并用示波器觀察mic端和輸出端波形 在設(shè)置dsp時(shí)采樣頻率為44100Hz,雙通道。 測(cè)得當(dāng)輸入峰峰值超過(guò)250 mVpp時(shí)輸出波形出現(xiàn)飽和
30、失真。思考原因如下:聲卡輸入端有放大器將輸入信號(hào)放大,當(dāng)輸入信號(hào)過(guò)大可能導(dǎo)致聲卡輸入前級(jí)放大器飽和也可能導(dǎo)致A/D轉(zhuǎn)換時(shí)超過(guò)了轉(zhuǎn)換的電壓范圍而最終使波形失真。 調(diào)節(jié)輸入頻率,當(dāng)輸入頻率超過(guò)22kHz時(shí)輸出波形有嚴(yán)重失真。這也驗(yàn)證了奈奎斯特采樣理論。5.利用framebuffer顯示輸入波形 由于前階段做了framebuffer圖形用戶界面,所以在這里把輸入波形畫(huà)出來(lái)并不困難,只需將buf的數(shù)據(jù)傳遞給畫(huà)點(diǎn)函數(shù)即可。 在錄音中加上如下程序: printf("nSay something:n"); status = read(fd, buf, sizeof(buf); /錄音 m
31、emset(fbp,0,screensize); /清屏 for(x=0;x<640;x+=2) draw_point(x, 240+bufi/100,0xffff); /畫(huà)點(diǎn)函數(shù) i=i+2; /雙聲道,只取一個(gè)聲道注:此時(shí)framebuffer設(shè)備打開(kāi),地址映射,畫(huà)點(diǎn)函數(shù)的編寫(xiě)都已寫(xiě)在程序中,不再贅述。成功畫(huà)出波形如下圖:注意的是這里只是畫(huà)出了波形,但并沒(méi)有幅值上的對(duì)應(yīng)關(guān)系。 附完整程序#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/ioctl.
32、h>#include <stdlib.h>#include <stdio.h>#include <linux/soundcard.h>#include <unistd.h>#include <pthread.h>#defineLenth 10#defineRate 44100#defineSize 16#defineChannel 2unsigned char bufLenth*Rate*Size*Channel/8;/用于保存錄音數(shù)據(jù)的內(nèi)存緩沖區(qū)unsigned char buffer100; char choice=0; i
33、nt flag_stop=1; int flag=1; int left=80, right=80; int vol_set(int left ,int right)/音量設(shè)置函數(shù)int arg;int ret_val;int fd_mixer;fd_mixer = open("/dev/mixer",O_RDWR);arg=(right<<8&0xff00)|(left&0x00ff);ret_val=ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_VOLUME),&arg);return ret_val;
34、 void key() char c; while(1) c=getchar(); switch(c) case '1': choice='1'break; case '2': choice='2'break; case '3': choice='3'break; case '4': printf("the left volume is %d%, the right is %d%n",left,right); if(left<100) left+=10; e
35、lse printf("warn:highest volume"); if(right<100) right+=10; else printf("warn:highest volume"); vol_set(left,right); printf("the left volume is %d%, the right is %d%n",left,right); break; case '5': printf("the left volume is %d%, the right is %d%n",
36、left,right); if(left>0) left-=10; else printf("warn:lowest volume"); if(right>0) right-=10; else printf("warn:lowest volume"); vol_set(left,right); printf("the left volume is %d%, the right is %d%n",left,right); break; case '6': flag=0;break; default:break
37、; int main() int fd_dsp,fd_mixer,status; int arg; int vol; pthread_t keyscanf; /保存進(jìn)程號(hào) pthread_create(&keyscanf,NULL,(void*)key,NULL); /創(chuàng)建一個(gè)進(jìn)程 /*打開(kāi)音頻/dev/dsp*/ fd_dsp=open("/dev/dsp",O_RDWR); if(fd_dsp<0) printf("open of /dev/dsp failed!n"); exit(1); /*打開(kāi)混音器設(shè)備/dev/mixer*/ f
38、d_mixer = open("/dev/mixer", O_RDONLY); if(fd_mixer<0) printf("open of /dev/mixer failed!n"); exit(2); /*設(shè)置dsp量化位數(shù)、聲道數(shù)、采樣頻率*/ arg=Size; /量化位數(shù) status=ioctl(fd_dsp,SOUND_PCM_WRITE_BITS,&arg); if(status=-1|arg!=Size)printf("Unable to set sample sizen"); arg=Channel;
39、 /設(shè)置聲道數(shù) status=ioctl(fd_dsp,SOUND_PCM_WRITE_CHANNELS,&arg); if(status=-1|arg!=Channel)printf("Unable to set channeln"); arg=Rate; /設(shè)置采樣頻率 status=ioctl(fd_dsp,SOUND_PCM_WRITE_RATE,&arg); if(status=-1|arg!=Rate)printf("Unable to set raten"); /*設(shè)置混音器mixer音量、主D/A轉(zhuǎn)換器、麥克風(fēng)輸入、輸入增
40、益*/ vol=(right<<8&0xff00)|(left&0x00ff); ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_VOLUME), &vol); vol=88; ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_PCM), &vol); vol=100; ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_MIC), &vol); vol=100; ioctl(fd_mixer,MIXER_WRITE(SOUND_MIXER_IGAIN), &vol); /*按鍵選擇界面*/ flag=1; printf(
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2022年大二學(xué)年總結(jié)自我鑒定5篇
- 【模塊二名篇名句默寫(xiě)】【高分攻略】高考語(yǔ)文一輪復(fù)習(xí)學(xué)案
- 石河子大學(xué)《數(shù)字信號(hào)處理》2022-2023學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《口腔解剖生理學(xué)二》2021-2022學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《工程項(xiàng)目管理》2021-2022學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《波斯文學(xué)史》2023-2024學(xué)年第一學(xué)期期末試卷
- 沈陽(yáng)理工大學(xué)《數(shù)學(xué)物理方法》2022-2023學(xué)年第一學(xué)期期末試卷
- 沈陽(yáng)理工大學(xué)《英國(guó)文學(xué)史》2022-2023學(xué)年第一學(xué)期期末試卷
- 《論語(yǔ)》導(dǎo)讀(2021下)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 沈陽(yáng)理工大學(xué)《電子技術(shù)基礎(chǔ)》2021-2022學(xué)年期末試卷
- 《分散系》說(shuō)課課件
- 小升初數(shù)學(xué)蘇州外國(guó)語(yǔ)學(xué)校數(shù)學(xué)模擬試卷答案版蘇教版精
- 抗痙攣體位專題知識(shí)講座
- 19規(guī)則值班水手英語(yǔ)聽(tīng)力與會(huì)話
- 廣東省3證書(shū)高職高考語(yǔ)文試卷和答案
- 茶多酚性質(zhì)功效及應(yīng)用
- 安全文明作業(yè)方案及措施
- 平行四邊形的面積學(xué)習(xí)單
- 境外項(xiàng)目緊急撤離方案
- 愛(ài)普化工新材料建設(shè)項(xiàng)目環(huán)境影響報(bào)告書(shū)
- 函數(shù)的零點(diǎn)與方程的解(說(shuō)課稿)
評(píng)論
0/150
提交評(píng)論