WAVファイルを作成する・読む

WAVファイルを作成する

 WAVファイルのフォーマットは, 通信用語の基礎知識 で知ることができます。
 その情報を利用すると,16ビットステレオのWAVファイルを次のプログラムで作ることができます。
 プログラムは,一旦,ファイルに保存してから実行してください。130行で指定する BeatWave.WAV はプログラムを保存したのと同じフォルダに生成されます。
 140行と150行は,左右各チャンネルの波形です。引数tの単位は秒です。値が±1の間に納まるように定義してください。外部関数定義に変更することも可能です。
 160行で,継続時間を秒数で指定します。
 400行のPLAYSOUNDは,サウンドファイルを演奏する命令です(Windows版のみ)。

110 OPTION ARITHMETIC NATIVE
120 DECLARE EXTERNAL FUNCTION DWORD$, WORD$
130 LET file$="BeatWave.WAV"
140 DEF wl(t)=SIN(2*PI*440*t) 
150 DEF wr(t)=SIN(2*PI*441*t) 
160 LET duration=5  ! 継続時間(秒)
170 LET fs=44100    ! 標本化周波数(Hz)
180 LET SIZE=duration*fs
190 OPEN #1: NAME file$
200 ERASE #1
210 PRINT #1: "RIFF";
220 PRINT #1: DWORD$(SIZE*2*2 + 36);
230 PRINT #1: "WAVE";
240 PRINT #1: "fmt ";
250 PRINT #1: DWORD$(16);
260 PRINT #1: WORD$(1);        ! リニアPCM
270 PRINT #1: WORD$(2);        ! チャンネル数=2(ステレオ)
280 PRINT #1: DWORD$(fs);      
290 PRINT #1: DWORD$(fs*2*2);  ! データ速度(byte/sec) 
300 PRINT #1: WORD$(2*2);      ! ブロックサイズ
310 PRINT #1: WORD$(16);       ! ビット数
320 PRINT #1: "data";
330 PRINT #1: DWORD$(SIZE*2*2); ! 波形データバイト数
340 FOR i=0 TO SIZE-1 
350    LET t=i/fs
360    PRINT #1: WORD$(ROUND(32767*wl(t)));
370    PRINT #1: WORD$(ROUND(32767*wr(t)));
380 NEXT i
390 CLOSE #1
400 PLAYSOUND file$
410 END
1000 ! 外部関数定義 DWORD$ (32ビット整数化した文字列(4バイト)) 
1010 EXTERNAL FUNCTION DWORD$(n)
1020 OPTION ARITHMETIC NATIVE
1030 OPTION CHARACTER byte
1040 LET r=MOD(n,2^8) 
1050 LET s$=CHR$(r) 
1060 LET n=(n-r)/2^8 
1070 LET r=MOD(n,2^8) 
1080 LET s$=s$ & CHR$(r) 
1090 LET n=(n-r)/2^8 
1100 LET r=MOD(n,2^8) 
1110 LET s$=s$ & CHR$(r) 
1120 LET n=(n-r)/2^8 
1130 LET r=MOD(n,2^8) 
1140 LET DWORD$=s$ & CHR$(r) 
1150 END FUNCTION
1160 ! 外部関数定義 WORD$(16ビット整数化した文字列(2バイト))
1170 EXTERNAL FUNCTION WORD$(n)
1180 OPTION ARITHMETIC NATIVE
1190 OPTION CHARACTER byte
1200 LET r=MOD(n,2^8) 
1210 LET s$=CHR$(r) 
1220 LET n=(n-r)/2^8 
1230 LET r=MOD(n,2^8) 
1240 LET WORD$=s$ & CHR$(r) 
1250 END FUNCTION


 文字列処理を利用して16ビット整数を生成しているので,実行速度は低速です。
 十進BASIC 7.4.8(以降),BASIC Accerelator 0.9.3.0(以降)は,WORD$, DWORD$を組込関数として持つので,120行のDECLARE FUNCTION行と1000行以降を削除すると少し速くなります。

WAVファイルを読む

次のプログラムの9000行以降で定義されたモジュールWAVは,WAVファイルを読みます。 リニアPCM 16ビット(モノラルまたはステレオ)に対応します。
初めに,WAV.OPENでWAVファイルを指定します。
WAV.SIZEは波形データの個数,WAV.RATEはサンプリングレートです。
WAV.READ(L,R)で,波形データを1組ずつ読み取ります。 変数L,Rに,左右各チャンネルの波形データが−1以上1未満の値として取得されます。 (モノラルの場合には,L,Rに同じ数値が代入されます。)

100 OPTION ARITHMETIC NATIVE
110 DECLARE EXTERNAL SUB wav.open, wav.read, wav.close
120 DECLARE EXTERNAL NUMERIC wav.size, wav.rate, wav.NChannels
130 DECLARE NUMERIC i,L,R,t,d
140 DECLARE STRING FName$
150 FILE GETNAME FName$, "WAV"
160 CALL wav.open (FName$)
170 PRINT FName$
180 PRINT "サンプリングレート(Hz)", wav.rate 
190 IF wav.NChannels=1 THEN PRINT "モノラル" ELSE PRINT "ステレオ"
200 PRINT "長さ(秒)", wav.size / wav.rate
210 LET d=1/32
220 SET WINDOW 0, d , -2, 2
230 FOR i=0  TO wav.size-1
240    LET t = i/wav.rate
250    LET t = MOD(t,d)
260    IF t < 1/wav.rate THEN
270       WAIT DELAY d
280       CLEAR
290       PLOT LINES
300    END if
310    CALL wav.read(L,R)   
320    PLOT LINES :t,L+R;
330 NEXT i 
340 CALL wav.close
350 END
360 
9000 MODULE WAV
9010 MODULE OPTION ARITHMETIC NATIVE
9020 PUBLIC SUB OPEN, READ, CLOSE
9030 PUBLIC NUMERIC  SIZE        ! サンプル数。size/rateで時間になる
9040 PUBLIC NUMERIC  RATE        ! サンプリングレート
9050 PUBLIC NUMERIC  nchannels   ! チャンネル数 1または2
9060 SHARE  STRING FNAME$
9070 SHARE NUMERIC count
9080 SHARE FUNCTION DWORD, INT16
9090 SHARE FUNCTION Chars4$
9100 SHARE CHANNEL #1
9110 LET count=0
9120 
9130 EXTERNAL SUB OPEN(f$)
9140    DECLARE NUMERIC n,id,blocksize
9150    DECLARE STRING s$
9160    OPEN #1: NAME f$, ACCESS INPUT
9170    LET s$=Chars4$
9180    IF s$<>"RIFF" THEN CAUSE EXCEPTION 999
9190    LET n=DWORD     ! これ以降のファイルサイズ(無視)
9200    LET s$=Chars4$
9210    IF s$<>"WAVE" THEN CAUSE EXCEPTION 999
9220    LET s$=Chars4$
9230    IF s$<>"fmt " THEN CAUSE EXCEPTION 999
9240    LET n=DWord
9250    IF n<>16 THEN CAUSE EXCEPTION 999
9260    LET id=int16
9270    IF id<>1 THEN CAUSE EXCEPTION 999
9280    LET nchannels =int16    ! チャンネル数
9290    LET Rate = dword        ! サンプリングレート
9300    LET n=DWORD             ! データ速度(無視)
9310    LET BlockSize=int16     ! ブロックサイズ
9320    LET n=int16             ! 8 or 16
9330    IF n<>16 THEN CAUSE EXCEPTION 998
9340    LET s$=Chars4$
9350    IF s$<>"data" THEN CAUSE EXCEPTION 999
9360    LET SIZE=DWORD/BlockSize  
9370 END SUB
9380  
9390 EXTERNAL SUB READ (L, R)
9400    IF count < SIZE THEN
9410       LET L=int16/2^16
9420       IF nchannels=2 THEN
9430          LET R=int16/2^16
9440       ELSE 
9450          LET R=L
9460       END IF
9470       LET count=count+1
9480    ELSE
9490       CAUSE EXCEPTION 997
9500    END if
9510 END SUB
9520  
9530 EXTERNAL FUNCTION Chars4$
9540    OPTION CHARACTER byte
9550    DECLARE STRING s$
9560    CHARACTER INPUT #1: s$
9570    CHARACTER INPUT #1: s$(2:2)
9580    CHARACTER INPUT #1: s$(3:3)
9590    CHARACTER INPUT #1: s$(4:4)
9600    LET Chars4$=s$
9610 END FUNCTION
9620 
9630 EXTERNAL FUNCTION DWord
9640    OPTION CHARACTER byte
9650    DECLARE NUMERIC n
9660    DECLARE STRING s$
9670    CHARACTER INPUT #1: s$
9680    LET n=ORD(s$)
9690    CHARACTER INPUT #1: s$
9700    LET n=n + ORD(s$)*2^8
9710    CHARACTER INPUT #1: s$
9720    LET n=n + ORD(s$)*2^16
9730    CHARACTER INPUT #1: s$
9740    LET n=n + ORD(s$)*2^24
9750    LET DWord=n
9760 END FUNCTION
9770 
9780 EXTERNAL FUNCTION Int16
9790    OPTION CHARACTER byte
9800    DECLARE NUMERIC n
9810    DECLARE STRING s$
9820    CHARACTER INPUT #1: s$
9830    LET n=ORD(s$)
9840    CHARACTER INPUT #1: s$
9850    LET n=n+ORD(s$)*2^8
9860    IF n>=2^15 THEN LET n=n-2^16
9870    LET int16=n
9880 END FUNCTION
9890 
9900 EXTERNAL SUB CLOSE
9910    CLOSE #1
9920 END SUB
9930 END MODULE 

参考

マイクロフォンなどの音源からWAVファイルを作成するのに,Windows95〜XPではWindowsアクセサリーのサウンドレコーダが使えます。
Windows Vista/7 でWAVファイルを作成したい場合は,次のフリーソフトが使えると思います(未テスト)。
Re:Sound - 帰ってきた サウンド レコーダー


戻る