Windows .WAV 文件使用研究論文

時間:2022-09-17 05:29:00

導語:Windows .WAV 文件使用研究論文一文來源于網友上傳,不代表本站觀點,若需要原創文章可咨詢客服老師,歡迎參考。

Windows .WAV 文件使用研究論文

摘要該文介紹了Windows聲波文件(*.WAV)的格式,然后分析了在DOS下不使用聲音適配卡播放聲波文件的關鍵問題,并給出了程序清單。

關鍵詞DOS應用軟件開發多媒體聲波文件在DOS應用軟件開發過程中,我們非常希望能在不附加任何硬件設備的條件下實現一些簡單的多媒體功能。

過去許多文章中都討論過Windows圖像文件(*.BMP,*.PCX)的格式及其用于美化DOS程序界面的方法。在MSWIMDOWS3.1以后,Windows又提供了標準的聲波文件(*.WAV),因此我們可以利用已有的聲波文件鑲嵌在自己的軟件中,在DOS下實現語音或其它音響的播放,提高我們的軟件質量。

一、聲波文件格式分析

*.WAV文件作為多媒體中使用的聲波文件格式之一,它是以RIFF格式為標準的。RIFF是英文ResourceInterchangeFileFormat的縮寫,每個WAV文件的頭四個字節便是“RIFF”。

常見的聲波文件主要有兩種,分別對應于單聲道(11.025KHz采樣率、8Bit的采樣值)和雙聲道(44.1KHz采樣率、16Bit的采樣值)。這里,采樣率是指:聲波信號[模→數]轉換過程中單位時間內采樣的次數。采樣值是指每一次采樣周期內聲波模擬信號的積分值,在編程播放過程中我們認為它是揚聲器在此周期單位時間段的音量。

*.WAV文件由文件頭和數據體兩大部分組成。其中文件頭又分為RIFF/WAV文件標識段和聲波數據格式說明段兩部分。

WAV文件各部分內容及格式見附表。

對于單聲道聲波文件,采樣數據為八位的短整數(shortint00H-FFH);而對于雙聲道立體聲聲波文件,每次采樣數據為一個16位的整數(int),高八位和低八位分別代表左右兩個聲道。

@@03A04400.GIF;*.WAV文件格式說明表@@

二、WAV文件編程

在沒有聲音適配卡的條件下,利用PC機內部揚聲器發聲需解決幾個關鍵問題。

首先是如何產生按指定采樣率要求的標準時間間隔段,以此為基礎控制揚聲器發聲。

由于此時間段要求精確且非常短暫,因此實現起來有一定的難度。解決該問題的思路是修改8253定時器芯片的計數器0(地址:040H)的初始值,改變系統時鐘中斷頻率使其和采樣率相一致,建立用戶的時鐘中斷例程,最終產生標準的時間間隔段。但是在我們修改原有系統時鐘中斷(Int08H)以后,最終必須恢復原有18.2Hz的系統時鐘中斷。

其次是如何快速地打開和關閉揚聲器。解決這個問題的方法是直接向8255芯片端口(地址:061H)寫操作。由于PC機機內揚聲器發聲只有開/閉兩種狀態,并不能控制音量大小。

因此還須考慮如何通過開閉揚聲器來摸擬實現音量大小的控制。實現方法是:在每個時間單位內通過改變揚聲器打開延時的長短代表音量的大小。例如:對于8Bit單聲道聲波文件,采樣數據的最大值是0FFH,那么在每個標準時間單位內揚聲器打開時間應為Delay=(采樣值/256)*標準時間段長度。在此思想下可以將該方法簡化,設揚聲器延時只有0、1(時間單位)兩種情況,即在每個時間單位內,如果采樣值大于128則發聲,如果采樣值小于128就不發聲。顯然這樣做是以拋棄大量聲波信息為代價的,采用的信息量只占原有用信息的1/12

8,所以這種方法產生的音質較差。

三、程序實例

下面是一個能播放11.025KHz/8Bit/單聲道聲波文件的演示程序。關于使用*.WAV文件的其它細節,可通過閱讀本程序得到。它采用了第二種延時方式,如果讀者有興趣提高音質可將其改成使用第一種方法,只需將newint08h中的聲音開/關判斷(與128比較)部分改成循環等待即可。

循環次數通過i=int(vol[counter]/256)*MAXTIMES得到。

式中MAXTIMES為延長一個標準時間單位的循環次數。

程度運行環境:486兼容機,MSDOS6.0,TC2.0編譯系統。

/*/*/*

*.WAV文件播放程序DEMO.C,石寧1994.12

*/*/*/

#include"dos.h"

#include"stdio.h"

#include"string.h"

#defineMAXSIZE50000

structwave-file_head/*聲波*/

{/*文件頭*/

charriff_id[4];/*結構體*/

longintsize0;

charwave-fmt[8];

lontintsizel;

intfmttag;

intchannel;

longintsamplespersec;

longintbytepersec;

intblockalign;

intbitpersamples;

}filehead;

longintdatasize,counter=0;

unsignedcharvol[MAXSIZE];

unsignedclkdiv;

intoldclk=0,running=1;

voidsoundon();

voidsoundoff();

voidinterrupt(*oldint8h)();

voidinterruptnewint8h()

{/*用戶中斷例程*/

if(running)

unsignedinti;

disable();/*屏蔽中斷*/

running=0;

if(vol[counter]>=128)

{

i=inportb(0x61);/*開揚*/

i=i|0x03;

outportb(0x61,i);/*聲器*/

}

else

{

i=inportb(0x61);/*關揚*/

i=i&0x00fc;

outportb(0x61,i);/*聲器*/

}

counter+=1;

enable();/*打開中斷*/

if(counter>=datasize)counter=0;

outportb(0x20,0x20);

running=1;

}

}

voidsoundon()

{

clkdiv=1193180/filehead.samplespersec;

/*計算8253計數器0初始值*/

oldint8h=getvect(0x08);/*保存舊的08H中斷向量*/

setvect(0x08,newint8h);/*置新的08H中斷例程*/

outportb(0x43,0xB6);/*初始化*/

outportb(0x42,1);/*8253計數器3/

outportb(0x42,0)

;/*初始值*/

outportb(0x43,0x36);/*修改8253*/

outport(0x40,clkdiv&0x00ff);/*計數器0*/

outport(0x40,(clkdiv>>8)&0x00ff);/*初始值*/

}

voidsoundoff()

{

inti;

setvect(0x08,oldint8h);/*恢復舊的08H中斷向量*/

outportb(0x43,0x36);/*恢復正常*/

outport(0x40,0)/*的時鐘中*/

outport(0x40,0);/*斷頻率*/

i=inportb(0x61);/*關揚*/

i=i&0x00fc;

outportb(0x61,i);/*聲器*/

}

voidmain(intargc,char*argv[])

{

longj;

intkey;

char*s;

FILE*fp;/

if(argc==1)

{

printf("%s\n","AndTheWAVFilenameInCommandLine!");

exit(0);

}

else

{

if((fp=fopen(argv[l],"rb"))==NULL)

{

printf("CannotopentheDatafile%s\n",argv[1];

exit(0);

}

}

if(fread(&filehead,sizeof(structwave-file-head),1,fp)==NULL)

{

printf("FileReadError!\n");

exit(0);

}

fseek(fp,4,SEEK-CUR);

fread(&datasize,4,1,fp);

for(j=0;j<datasize;j++)vol[j]=getc(fp);

close(fp);

printf("%s\n","NowSoundOn,PressESCtoStop!");

soundon();

for(;;)

{

key=getch();

if(key==27)

{

soundoff();

printf("%s\n","Soundoff!");

break;