以下のソースはHSPコンテストに出した作品「FFTモジュール活用例1スペクトラムアナライザー」のソースです。
下の方にあるfftモジュールは著作権フリーなので自由に使って下さい
「fft」の使い方ですが、まずこの命令を使うには変数
「beki」
「LIST_SIZE」
「LIST_SIZE2」
「LIST_SIZE8」
の作成をしておいて下さい。
beki には高速フーリエ変換するサンプル数(2^n)のnを入れます。以下のソースで言うとサンプル数を32768個作りたかったので
beki=15
になっています。
LIST_SIZEには2^beki を入れて下さい
LIST_SIZE2はLIST_SIZE\2を、LIST_SIZE8にはLIST_SIZE×8を代入して下さい。
高速フーリエ変換したい実数(虚数)配列は当然ddim で作り、配列数はLIST_SIZEを指定して下さい
ここで注意ですがbeki には整数しか指定出来ませんので、変換する配列数は2のべき乗に限られます
命令「fft」の引数は3つで
・実数部(浮動小数点配列)
・虚数部(浮動小数点配列)
・逆変換か否か(1 or -1 -1で逆変換)
です。命令を実行すると実数部、虚数部に変換後の値が入っています。
下の方にあるfftモジュールは著作権フリーなので自由に使って下さい
「fft」の使い方ですが、まずこの命令を使うには変数
「beki」
「LIST_SIZE」
「LIST_SIZE2」
「LIST_SIZE8」
の作成をしておいて下さい。
beki には高速フーリエ変換するサンプル数(2^n)のnを入れます。以下のソースで言うとサンプル数を32768個作りたかったので
beki=15
になっています。
LIST_SIZEには2^beki を入れて下さい
LIST_SIZE2はLIST_SIZE\2を、LIST_SIZE8にはLIST_SIZE×8を代入して下さい。
高速フーリエ変換したい実数(虚数)配列は当然ddim で作り、配列数はLIST_SIZEを指定して下さい
ここで注意ですがbeki には整数しか指定出来ませんので、変換する配列数は2のべき乗に限られます
命令「fft」の引数は3つで
・実数部(浮動小数点配列)
・虚数部(浮動小数点配列)
・逆変換か否か(1 or -1 -1で逆変換)
です。命令を実行すると実数部、虚数部に変換後の値が入っています。
#const beki 15
#const LIST_SIZE 1<<beki
#const LIST_SIZE2 LIST_SIZE>>1
#const LIST_SIZE3 LIST_SIZE<<1
#const LIST_SIZE8 LIST_SIZE<<3
#const lstdim LIST_SIZE3/4+11
_MSGothic = "MS ゴシック"
font _MSGothic,80,1
mes "※音量注意!"
font _MSGothic,30,1
mes "本ソフトは音声再生機能があります。\n注意して下さい"
wait 100
ddim onryo,5
randomize
onryo=570.0,50.0,2.0,0.012,0.00007
pos 140
datamode=0;0でロードしたデータ、1ブラウン2ピンク3ホワイト4ブルー5パアプル
gosub*syokika
sdim pinkname,64,5
pinkname="ブラウンノイズ","ピンクノイズ","ホワイトノイズ","ブルーノイズ","パープルノイズ"
objsize 140,40
pos 40,0
button gosub "波形読込",*load
pos 180,0
button gosub "波形連続再生or停止",*saisei
pos 320,0
button gosub "カラードノイズ試験生成",*colorz
objsize 52,24
pos 165,213
button gosub "wav解析",*fft0
pos 445,257
button gosub "wav復元",*fft1
sdim aaaaa,300
aaaaa="x1\nx10\nx100\nx10^3\nx10^4\nx10^5\nx10^6\nx10^7"
yokojiku1=0
tatejiku1=0
objsize 40,24;縦軸
pos 0,160
combox tatejiku1,,aaaaa
pos 55,193;横軸
combox yokojiku1,,aaaaa
repeat -1;メインルーチン
mbeki=beki0
await 15
if mbeki!beki0:gosub*syokika
redraw 0
gosub*byouga
redraw 1
loop
*syokika
ddim schasr,LIST_SIZE
ddim schasi,LIST_SIZE
ddim schasr2,LIST_SIZE
ddim schasi2,LIST_SIZE
ddim itjr,LIST_SIZE
ddim itji,LIST_SIZE
ddim hakei,LIST_SIZE
ddim bunkai,LIST_SIZE
if datamode=5{;読み込みデータの解析
if sampkz<LIST_SIZE{
dialog "波形データが短いです"
}else{
repeat LIST_SIZE
dataitj=wpeek(wavedata,sampt*cnt+wbit*hidari)\(1<<(wbit*8))
if wbit=2:if dataitj>32767:dataitj=dataitj-65536
if wbit=1:dataitj-=128:dataitj*=256
schasr.cnt=double(dataitj)
loop
hakeistk hakei,schasr,schasi
}
}else{
gosub*rando
mcis1
fft itjr,itji,1
repeat LIST_SIZE;周波数ごとにいじる
scare=onryo.datamode*expf(logf(sqrt(1.7+cnt))*(datamode-2))
itjr.cnt*=scare
itji.cnt*=scare
loop
hakeistk bunkai,itjr,itji
mcsi2
fft itjr,itji,-1
mcsi1
hakeistk hakei,schasr,schasi
}
return
*load
dialog "wav",16,"WAVEファイル"
exist refstr
dim wavedata,strsize/4+1
bload refstr,wavedata
wbit=wavedata.4/8
streo=wavedata.5/65536;1でモノラル2でステレオ
sampt=wbit*streo;サンプリング単位(byte)
sampkz=(strsize-44)/sampt
hidari=0
if streo=2:dialog "音声はステレオです\n左の音声を使用しますか?\n(いいえ選択で右)",2:if stat=7:hidari=1
datamode=5;0でロードしたデータ、1ブラウン2ピンク3ホワイト4ブルー5パアプル
gosub*syokika
return
*rando
gk=0.0
repeat LIST_SIZE;ランダムノイズ作る
r=double(rnd(32768)-16384)
schasr.cnt=r
gk+=r
loop
gk/=LIST_SIZE
repeat LIST_SIZE
schasr.cnt-=gk
loop
return
*colorz
datamode=rnd(5)
gosub*syokika
dialog pinkname.datamode+"を生成しました"
return
*saisei
if playon{
mmstop:playon-
}else{
dim wf,lstdim
wf=1179011410,36+LIST_SIZE3,1163280727,544501094,16,65537,44100,88200,1048578,1635017060,(LIST_SIZE3-82)
repeat LIST_SIZE
wpoke wf,44+cnt*2,limit((hakei.cnt+32768)\65536,0,65535)
loop
memfile wf ; ストリームの直前で指定してください
mmload "MEM:a.wav",0,1 ; 画像の拡張子識別のためダミー名a.jpgを使用
sdim wf,64 ; もったいないのでbufのメモリ領域を小さくしておきます
mmplay 0:playon+
}
return
*byouga
pget -1:boxf
font _MSGothic,100
color 128,128,128
pos 140,193
mes "▼"
pos 420,200
mes "▲"
font _MSGothic,10
pos 8,183:mes "縦軸\n /横軸"
tt="1"
repeat 5
pos 132.87712*cnt+25,450
mes tt+"Hz"
tt+="0"
loop
;グラフ形
repeat 2
color 200,200,200:boxf 40,47+255*cnt,640,191+255*cnt
loop
;波形
color ,165
yokoj600=LIST_SIZE>>yokojiku1
tatej600=expf(logf(10)*tatejiku1)
repeat 600
limi=limit(180-hakei(yokoj600*cnt/600)*tatej600*0.001983642578,50,180)
if cnt=0:pos cnt+40,limi
line cnt+40,limi
loop
;波形2
tatej600=1
bxs=40
clf=0
getkey key,1
repeat 600
mtatej600=tatej600
tatej600=int(expf(logf(LIST_SIZE-2)*(1.0*cnt/599.0)))
if mtatej600!tatej600{
limi=446-limit(logf(bunkai.tatej600)*12.5076816-144,0,144)
itjint=cnt+41
color clf*80,165
if abs(mousey-375)<73:if bxs<=mousex:if mousex<itjint:color :if key{
repeat tatej600-mtatej600,mtatej600+1
itjdl=expf(((446.0-mousey)*0.07995087+11.512925))
nanbai=itjdl/bunkai.cnt
schasr2.cnt*=nanbai
schasi2.cnt*=nanbai
bunkai.cnt=itjdl
loop
}
boxf bxs,limi,itjint-1,446
bxs=itjint
clf=1-clf
}
loop
return
*fft0
mcis1
fft itjr,itji,1
mcsi2
hakeistk bunkai,schasr2,schasi2
return
*fft1
mcis2
fft itjr,itji,-1
mcsi1
hakeistk hakei,schasr,schasi
return
;if 0 {
#deffunc fft array A,array B,int inv
ddim c,LIST_SIZE
ddim d,LIST_SIZE
repeat beki;fft
bekii=LIST_SIZE>>(cnt+1)
repeat LIST_SIZE2
t2 = cnt\bekii;
t0 = (cnt/bekii)*bekii*2 + t2;
t1 = t0+bekii;
r4=A(t1)
i4=B(t1);
rm0=A(t0)-r4
im0=B(t0)-i4;
pii=3.14159265358979323846264338328*t2/bekii*inv;
dsin=sin(pii)
dcos=cos(pii);
A(t0) += r4;
B(t0) += i4;
A(t1) = rm0*dcos-im0*dsin;
B(t1) = rm0*dsin+im0*dcos;
loop
loop
repeat LIST_SIZE;ビット逆順
ic=cnt/65536
ic = (ic&0x00005555)<<1 | (ic&0x0000AAAA)>>1;
ic = (ic&0x00003333)<<2 | (ic&0x0000CCCC)>>2;
ic = (ic&0x00000F0F)<<4 | (ic&0x0000F0F0)>>4;
ic = (ic&0x000000FF)<<8 | (ic&0x0000FF00)>>8;
iic=cnt\65536
iic = (iic&0x00005555)<<1 | (iic&0x0000AAAA)>>1;
iic = (iic&0x00003333)<<2 | (iic&0x0000CCCC)>>2;
iic = (iic&0x00000F0F)<<4 | (iic&0x0000F0F0)>>4;
iic = (iic&0x000000FF)<<8 | (iic&0x0000FF00)>>8;
ic=(iic*32768+ic/2)>>(31-beki);
C(cnt)=A(ic)
D(cnt)=B(ic)
loop
if inv=-1{
repeat LIST_SIZE
a.cnt=c.cnt/LIST_SIZE
b.cnt=d.cnt/LIST_SIZE
loop
}else{
memcpy a,c,LIST_SIZE8
memcpy b,d,LIST_SIZE8
}
return
#deffunc hakeistk array A,array B,array E
repeat LIST_SIZE
a.cnt=sqrt(B(cnt)*B(cnt)+E(cnt)*E(cnt))
loop
return
#deffunc mcis1
memcpy itjr,schasr,LIST_SIZE8
memcpy itji,schasi,LIST_SIZE8
return
#deffunc mcis2
memcpy itjr,schasr2,LIST_SIZE8
memcpy itji,schasi2,LIST_SIZE8
return
#deffunc mcsi1
memcpy schasr,itjr,LIST_SIZE8
memcpy schasi,itji,LIST_SIZE8
return
#deffunc mcsi2
memcpy schasr2,itjr,LIST_SIZE8
memcpy schasi2,itji,LIST_SIZE8
return
;}