wavファイルを加工する
wavファイルを加工する
wavファイルはWinでよく使われる非圧縮の音声ファイルです。(圧縮もたまにある)
今回はそんな非圧縮wavファイルの加工をします。
とりあえずノーマライズに挑戦します。
手順は以下の通りです。
プログラムは以下のようになります。
普通のwavファイルのヘッダは決まりがあります。
それを素直にWAVEHEADER構造体にしています。
pcmデータは16bitしか扱えません。
入力ファイルはtest.wavです。出力はtest2.wavになります。
'ノーマライズ
#console
#include<vcrt71.sbp>
Type WAVEHEADER
RIFF[3] As Byte'"RIFF"
bytes As DWord'(ファイルのバイト数)-8
WAVE[3] As Byte' "WAVE"
fmt[3] As Byte '"fmt "
siz_wf As DWord'PCMWAVEFORMAT構造体のバイト数=常に16
'PCMWAVEFORMAT構造
wFormatTag As Word 'pcm=1
nChannels As Word 'ch数
nSamplesPerSec As Dword 'サンプリング周波数
nAvgBytesPerSec As DWord
nBlockAlign As Word
wBitsPerSample As Word '量子化数
data[3] As Byte'"data"
pcmbytes As DWord'波形データのバイト数
End Type
Dim fp As *FILE
Dim buf[100] As Byte
Dim pcm As *Integer'PCMは16bit決め打ち
Dim read As DWord
Dim wh As WAVEHEADER
Dim max As DWord
Dim n As DWord
Dim dB As Double
Dim gain As Double
fp = fopen("test.wav" , "rb")
If fp = NULL Then
printf(Ex"入力ファイルを開けません。\n")
exit(0)
End If
fread(VarPtr(wh) , sizeof(WAVEHEADER) , 1 , fp)
'wavフォーマットかどうか
memcpy(buf , wh.RIFF , 4)
memcpy(VarPtr(buf[4]) , wh.WAVE , 4)
memcpy(VarPtr(buf[8]) , wh.fmt , 4)
If strcmp(buf , "RIFFWAVEfmt ") <>0 Then
printf("wavフォーマットではありません")
exit(0)
End If
'フォーマットを表示
printf(Ex"%dch %dHz %dbit\n" , wh.nChannels , _
wh.nSamplesPerSec , wh.wBitsPerSample)
'データを読み込む
pcm = malloc(wh.pcmbytes)
fread(pcm , 1 , wh.pcmbytes , fp)
fclose(fp)
'ピークサーチ
For n=0 To wh.pcmbytes/2
If max < pcm[n] Then max = pcm[n]
Next
dB = 20*(log10(max)- log10(32767))
printf(Ex"最大値=%d [%4.4fdB]\n" , max, dB)
If max = 32767 Then
printf(Ex"ノーマライズの必要はありません。\n")
exit(0)
End If
'ノーマライズ
printf(Ex"ノーマライズ中...")
gain = 32767 / max
For n=0 To wh.pcmbytes/2
pcm[n] = pcm[n] * gain
Next
printf(Ex"終了しました。\n保存します。\n")
'保存
fp = fopen("test2.wav" , "wb")
If fp = NULL Then
printf(Ex"出力ファイルを開けません。\n")
exit(0)
End If
fwrite(VarPtr(wh) , sizeof(WAVEHEADER) , 1 , fp)
fwrite(pcm , 1 , wh.pcmbytes , fp)
fclose(fp)
printf(Ex"完了!\n")
system("pause")
exit(0)
その他
ピークサーチからノーマライズまでの部分を変えることで、以下のようなことが出来ます。
モノラルのwavファイルで行うと悲劇です。
wh.nChannels = 2のときのみ行うようにしてください。
LR反転するなら
'LR反転
printf(Ex"LR反転中...")
For n=0 To wh.pcmbytes/2 Step 2
pcm[n+1] = pcm[n] - pcm[n+1]
pcm[n] = pcm[n] - pcm[n+1]
pcm[n+1] = pcm[n+1] + pcm[n]
Next
カラオケモードにするなら
'カラオケ
printf(Ex"カラオケモード変換中...")
For n=0 To wh.pcmbytes/2 Step 2
pcm[n] = pcm[n] - pcm[n+1]
pcm[n+1] = pcm[n]
Next
モノラル化(擬似モノラル)するには
'擬似モノラル化
printf(Ex"擬似モノラルに変換中...")
For n=0 To wh.pcmbytes/2 Step 2
pcm[n] = (pcm[n] + pcm[n+1]) /2
pcm[n+1] = pcm[n]
Next
正しくモノラル化するには、
'モノラル化
printf(Ex"モノラルに変換中...")
For n=0 To wh.pcmbytes/2 Step 2
pcm[n/2] = (pcm[n] + pcm[n+1]) /2
Next
'フォーマットを書き換え
wh.nChannels=1
wh.nBlockAlign = wh.wBitsPerSample/8
wh.nAvgBytesPerSec = wh.nSamplesPerSec * wh.nBlockAlign
wh.pcmbytes = wh.pcmbytes / 2
wh.bytes = wh.pcmbytes + 44 -8