新しく発言する EXIT インデックスへ
質問です

  質問です たかし 2005/01/14 14:28:06 
  sinをsgnで囲えばいいかな。 青木太一 2005/01/14 15:57:40 
   └ご丁寧な説明ありがとうございます。 たかし 2005/01/14 19:18:06 
    └鋸刃の振幅は-1〜1ですか? 青木太一 2005/01/14 20:20:37 
     └返事ありがとうございます。 たかし 2005/01/15 10:08:02 
      └左右同じ波形にしたいのなら 青木太一 2005/01/15 10:27:38 
       └返事ありがとうございます たかし 2005/01/16 22:00:54 
        └なるほど... 青木太一 2005/01/16 23:19:22 
         └私の場合全ての領域において超初心者レベル... たかし 2005/01/17 14:26:13 
          └どこかで公開されたプログラムでは無かった... 青木太一 2005/01/18 08:30:07 
           └また、質問です たかし 2005/01/18 16:25:23 
            └今までのパターンから、どういうふうに書け... 青木太一 2005/01/18 22:32:27 
             └f(x)の範囲が-1〜1を超える事に関しては、特... たかし 2005/01/19 16:10:44 
              └事情はわかりましたが、十進BASICのヘルプは... 青木太一 2005/01/19 22:28:37 
               └えーと、ごめんなさい、残りの気になってた... 青木太一 2005/01/20 03:18:00 
                └!なお、フーリエ級数展開の低い項からだんだ... 青木太一 2005/01/20 03:19:13 
                 └返事遅れて申し訳ありません たかし 2005/01/20 14:21:45 
                  └fori=1tod*fs 青木太一 2005/01/20 18:03:51 
                   └詳しい説明ありがとうございます。 たかし 2005/01/20 21:54:47 
                    └音=振動の形が波形なのですから、音だって... 青木太一 2005/01/20 22:17:06 
                     └返事ありがとうございます たかし 2005/01/22 11:01:09 
                      └前の発言の回答ではだめですか?視野の広さ... 青木太一 2005/01/23 01:27:31 
                       └なるほど!?返事ありがとうございます たかし 2005/01/24 14:22:52 
                        └>>7項だとか25項だとかおっしゃるのはナン... 青木太一 2005/01/24 17:37:57 
                         └返事ありがとうございます たかし 2005/01/25 11:35:49 
                          └しっかり見ていませんが、16bitの範囲を越え... 青木太一 2005/01/25 12:31:05 
                           └f(x)=x/pi(-pi<x<=pi) たかし 2005/01/26 16:16:00 

  質問です たかし 2005/01/14 14:28:06  ツリーへ

質問です 返事を書く
たかし 2005/01/14 14:28:06
以下のプログラム(私が作ったわけではありません)は、正弦波と白色雑音をそれぞれ左、右チャネルに出力するプログラムですがこのプログラムを変形して矩形波を出力するプログラムを作りたいのですが、どこを変えればいいのでしょうか?できれば完成版を作ってくださるとありがたいのですが

REM testwave.bas 十進BASICによる音声ファイル生成プログラム
REM (L:1KHz -10dB 正弦波、R: 振幅 -10dB {パワーは-11.76dB} 白色雑音)
REM chr$関数の引数として全ての1バイト整数が許される様に、オプションメニューの
REM 「互換性」「動作」で「文字列処理の単位」を「バイト」に設定して実行すること
let d=10 !継続時間(秒)
let f0=1000 !正弦波周波数(Hz)
let db=-10 !生成波形の最大値(±32767を0dBとする)
let fs=44100 !標本化周波数(Hz)
let bps=fs*4 !1秒当りのデータ量(ステレオ16ビット量子化)
let dsize=d*fs*4 !オーディオデータサイズ
let fsize=dsize+36 !ファイルサイズ(先頭8Bを除く)
let fmtsize=16 !フォーマットサイズ
let channel=2^17+1 !ステレオPCMデータの指定
let reso=2^20+4 !16ビットの指定
let a=10^(db/20)
open #6 : name "test.wav" !ファイルを開き、この名前のファイルが
erase #6 !既に存在していた場合には上書きを指定
let t0=time
print #6 : "RIFF"; !以下、wavファイルのヘッダーを作成
call out4(fsize) !
print #6 : "WAVEfmt "; !
call out4(fmtsize) !
call out4(channel) !
call out4(fs) !
call out4(bps) !
call out4(reso) !
print #6 : "data"; !
call out4(dsize) !ここまでがヘッダー用の出力
let al=a*32767 !左チャネル係数
let ar=a*65535 !右チャネル係数
let k=f0/fs*pi*2 !引数の刻み
let audio$="" !オーディオデータバッファを初期化
let count=0 !カウンタをリセット
for i=1 to d*fs
let lch=int(sin(i*k)*al+0.5) !左チャネルは1kHz正弦波
if lch<0 then let lch=lch+65536 !負の数は補数表現
let rch=int((rnd-0.5)*ar+0.5) !右チャネルは白色雑音
if rch<0 then let rch=rch+65536 !負の数は補数表現
LET audio$=audio$&chr$(mod(lch,256))&chr$(int(lch/256))&chr$(mod(rch,256))&chr$(int(rch/256))
LET count=count+1
if count=64 then !バッファデータが所定の長さ(64サンプル256Bがほぼ最適)に達したら
print #6 : audio$; !データをファイルに出力して
let audio$="" !バッファを初期化し
let count=0 !カウンタをリセット
end if
next i
print #6 : audio$; !バッファに残ったデータを出力して
close #6 !ファイルを閉じる
print "elapsed time = ";time-t0;"seconds"
sub out4(i4) !4バイト整数の出力(little endian)
LET j4=i4
for m=0 to 3
print #6 : chr$(mod(j4,256));
LET j4=int(j4/256)
next m
end sub
END

  sinをsgnで囲えばいいかな。 青木太一 2005/01/14 15:57:40  ツリーへ

Re: 質問です 返事を書く
青木太一 2005/01/14 15:57:40
sinをsgnで囲えばいいかな。

ちゃんとコードを読み通してないのですが、パッと見た感じではsinが使われている唯一の箇所

let lch=int(sin(i*k)*al+0.5) !左チャネルは1kHz正弦波



let lch=int(sgn(sin(i*k))*al+0.5)

にすればいいのかな? と思います。
sgnとはその引数の符号を出す関数です。下のプログラムを動かせばどういうことになるかわかります。
!SGN(x) xの符号(sign)
! x>0のときSGN(x)=1,
! SGN(0)=0,
! x<0のときSGN(x)=-1
set window -10,10,-10,10
draw grid
for x=-10 to 10 step 0.1
plot lines:x,sin(x);
next x
plot lines
set line color 2
for x=-10 to 10 step 0.1
plot lines:x,sgn(sin(x));
next x
END

本当に矩形かどうかわかりませんが、
音質も確かに変わっているようでした。
(sgnは0のとき0を出力するので、厳密に考えると立ち上がり、立下りがちょっとなまるかも。
より矩形っぽくしたかったらそこをどうにかしたほうがいいのかな?)

ところで
>REM chr$関数の引数として全ての1バイト整数が許される様に、オプションメニューの
>REM 「互換性」「動作」で「文字列処理の単位」を「バイト」に設定して実行すること
とありますが、
OPTION CHARACTER BYTE
を書けばいちいちメニューから設定しないでもよくなりますよ。既知なら失礼。

P.S.
こうやればwavファイルが生成できるんですね。おもしろいなあ。

   └ご丁寧な説明ありがとうございます。 たかし 2005/01/14 19:18:06  ツリーへ

Re: sinをsgnで囲えばいいかな。 返事を書く
たかし 2005/01/14 19:18:06
ご丁寧な説明ありがとうございます。

OPTION CHARACTER BYTEを書けば設定の変更をしなくてよかったんですね。知らなかったです

あと、このプログラムを変形させて鋸歯状波は、作る事はできますか?
よろしくおねがいします

    └鋸刃の振幅は-1〜1ですか? 青木太一 2005/01/14 20:20:37  ツリーへ

Re: ご丁寧な説明ありがとうございます。 返事を書く
青木太一 2005/01/14 20:20:37
鋸刃の振幅は-1〜1ですか?
sinのかわりにこのsaw関数を使ってみてください

!sin(x) -> saw(x)=mod(x,2*pi)/pi-1
set window -10,10,-10,10
draw grid
for x=-10 to 10 step 0.1
plot lines:x,sin(x);
next x
plot lines
set line color 2
def saw(x)=mod(x,pi*2)/pi-1
for x=-10 to 10 step 0.1
plot lines:x,saw(x);
next x
END

そういえば矩形のときもですが、左チャンネル係数「al」は、
何か違う値にしたほうがいいのかもしれません。
これで本当に指定したdBになるのかわかりません。ちょっとdBについて理解が足りないので...
勉強しなおせば正確なところがわかるはずなのですが、ちょっと今忙しいので...不正確さを残す内容でごめんなさい。

     └返事ありがとうございます。 たかし 2005/01/15 10:08:02  ツリーへ

Re: 鋸刃の振幅は-1〜1ですか? 返事を書く
たかし 2005/01/15 10:08:02
返事ありがとうございます。
鋸刃の振幅は、自分では決めてなかったのでその値でかまいません

あと、もう一つ質問したいのですが左チャネル、右チャネル両方で矩形波を出力するプログラムを作るには、一番最初のスレッドにのせたプログラムをどのように変えたらいいのでしょうか?

      └左右同じ波形にしたいのなら 青木太一 2005/01/15 10:27:38  ツリーへ

Re: 返事ありがとうございます。 返事を書く
青木太一 2005/01/15 10:27:38
左右同じ波形にしたいのなら

let lch=int(sin(i*k)*al+0.5) !左チャネルは1kHz正弦波
if lch<0 then let lch=lch+65536 !負の数は補数表現
let rch=int((rnd-0.5)*ar+0.5) !右チャネルは白色雑音
if rch<0 then let rch=rch+65536 !負の数は補数表現

この4行のうち、後半二行を
rch=lch
に変えればいいと思います。
たかしさん、もうちょっとこのプログラムがどういう仕組みなのか理解に努めた方がいいのでは...
偉そうなこと言ってごめんなさい。

       └返事ありがとうございます たかし 2005/01/16 22:00:54  ツリーへ

Re: 左右同じ波形にしたいのなら 返事を書く
たかし 2005/01/16 22:00:54
返事ありがとうございます
本当に超初心者なので、こうゆうプログラムを理解するのはかなり難しい状態です。またわからない事ができたら質問させていただきますのでこれからもよろしくお願いします。

        └なるほど... 青木太一 2005/01/16 23:19:22  ツリーへ

Re: 返事ありがとうございます 返事を書く
青木太一 2005/01/16 23:19:22
なるほど...

なぜああ書いたかというと、どこまで質問者の方がわかっていらっしゃるのかがわからないと、回答しずらいのですよね。
理解できなくてもいいので、理解に努めてどこでつまづいたかを聞けるとありがたいのですよ。
今回の場合、問題は複数の領域
・デジタル音声の概論
・wavファイルの規格
・十進BASICプログラミング
にまたがっているので、それぞれどこまで理解していて、どこからわからないのかなーと思いまして。
ちなみに私自身は
・デジタル音声の概論
>非圧縮ならだいたいわかってるつもり。でもdBをどう定義するのかはわからない。
・wavファイルの規格
>ぜんぜん知らない
・十進BASICプログラミング
>6年ほどの経験があるが、バイナリファイルを扱った経験はなかった(OPTION CHARACTER BYTEを使ったことはなかった)
です

ところでこのwavファイルを作成するプログラムですが、私には大変興味深いです
これはどこかのWebサイトか、なにかの本に載っているのですか?
それともたかしさんのお知り合いが書かれたのでしょう?
もし前者ならそのWebサイトなり本なりしょうかいしていただけたらありがたいのですが、いかがでしょう?

         └私の場合全ての領域において超初心者レベル... たかし 2005/01/17 14:26:13  ツリーへ

Re: なるほど... 返事を書く
たかし 2005/01/17 14:26:13
私の場合全ての領域において超初心者レベルですね。

私は、卒業研究で音を出力するプログラムを作る必要があり、何ヶ月か考えてわからなかったので、担当の教授に参考として一番最初に載せたスレッドのプログラムを作ってもらったわけです。教授に言わしてみればあのプログラムを私一人の力で作らせたかったようですが。無理ですよね。絶対に(笑)

          └どこかで公開されたプログラムでは無かった... 青木太一 2005/01/18 08:30:07  ツリーへ

Re: 私の場合全ての領域において超初心者レベル... 返事を書く
青木太一 2005/01/18 08:30:07
どこかで公開されたプログラムでは無かったのですか。残念。お返事ありがとうございます。

>あのプログラムを私一人の力で作らせたかったようですが。無理ですよね。絶対に(笑)
「そんなこと無い!がんばればできたはずだ。」
と言いたいところですが、自分も似たような経験が...
卒研がんばってください。

           └また、質問です たかし 2005/01/18 16:25:23  ツリーへ

Re: どこかで公開されたプログラムでは無かった... 返事を書く
たかし 2005/01/18 16:25:23
また、質問です
f(x)=4Sin(3x)/3π
              +4sin(x)/π
の音を出力するプログラムを一番最初のスレッドに示したプログラムを変形して作りたいのですがどうしたらいいのでしょうか?
よろしくお願いします

            └今までのパターンから、どういうふうに書け... 青木太一 2005/01/18 22:32:27  ツリーへ

Re: また、質問です 返事を書く
青木太一 2005/01/18 22:32:27
今までのパターンから、どういうふうに書けばいいのか想像して、とりあえず書いてみてはどうですか?
それでうまくいかないようなら先生に聞くなり、研究室の人に聞くなりしましたか?
なんでもかんでも掲示板で聞いていたら上達しませんよ。
せめて十進BASICのヘルプやチュートリアルのPDFを調べたうえで質問してください。

もしすでに自分でいろいろ勉強して、試して、先生や研究室の人にいろいろ聞いたうえで、うまくいかず、先生にもアクセスつかない事情があるなどのことでしたら、話は別です。偉そうなこといってごめんなさい。

その場合は、自分でどう試してどうだめだったのか、その試してだめだったコードも含めて書いてください。

あと、上の式ではf(x)の範囲が-1〜1を超えますけど、それについてはどうお考えなのでしょう?
その点を詰めていただかないことには、たとえコードを書かさせていただこうと思っても書けません。

             └f(x)の範囲が-1〜1を超える事に関しては、特... たかし 2005/01/19 16:10:44  ツリーへ

Re: 今までのパターンから、どういうふうに書け... 返事を書く
たかし 2005/01/19 16:10:44
f(x)の範囲が-1〜1を超える事に関しては、特に考えていません。
今回の研究では矩形波などの波形をフーリエ級数展開したとき項数を増やすと波形としてどのように近づくか、項数を増やすと音として聞くとどのような差異があるかについて研究しているので、-1〜1の範囲に収まらない波形の音も出す必要があります

担当の先生は、非常に厳格な先生で、このような細かい事まで聞ける勇気がありません。また、うちの研究室は、部屋はありますが、ほとんど使われていない状態で、卒論生や院生とのコミュニケーションは、ほとんどありません。また、研究テーマもバラバラです。基本的に自分自身で研究しなければいけない状況にあります。だから私にとっては、この掲示板しか頼れるところはありません。
あと、卒論要旨を今週中に提出しなければいけないので、もう時間がありません。どうかよろしくお願いします!!!

自分で考えた結果以下の部分を書き換えればいいのでしょうか?
let lch=int(sin(i*k)*al+0.5) !左チャネルは1kHz正弦波
の部分を
let lch=int(4*sin(3*i*k)*al/3*pi+4*sin(i*k)*al/pi+0.5)
にする

              └事情はわかりましたが、十進BASICのヘルプは... 青木太一 2005/01/19 22:28:37  ツリーへ

Re: f(x)の範囲が-1〜1を超える事に関しては、特... 返事を書く
青木太一 2005/01/19 22:28:37
事情はわかりましたが、十進BASICのヘルプはごらんになられましたか?
あと、書いていただいたコードではうまくいかなかったですか?うまくいかなかったのなら、どううまくいかなかったのか書いてください。
(まあ、三つほどうまくいかないだろうなと感じる点がありますが...)

基本的には、お考えのようにlet lch=...の行を書き換えればいいです。ただし、たかしさんの書いたコードにはいくつか問題があります。
>f(x)=4Sin(3x)/3π
>              +4sin(x)/π

>let lch=int(4*sin(3*i*k)*al/3*pi+4*sin(i*k)*al/pi+0.5)

第二項はそれでいいと思います。
第一項は「4*sin(3*i*k)*al/3*pi」では「4πSin(3x)/3」になってしまいます。
「4*sin(3*i*k)*al/(3*pi)」に書き直してください。

他の気になる二点はあとから書きます

               └えーと、ごめんなさい、残りの気になってた... 青木太一 2005/01/20 03:18:00  ツリーへ

Re: 事情はわかりましたが、十進BASICのヘルプは... 返事を書く
青木太一 2005/01/20 03:18:00
えーと、ごめんなさい、残りの気になってたところ二点は私の勘違いと心配しすぎでした。

まず、矩形波のフーリエ級数展開でくくりだされる係数が4/piではなくpi/4なのだと勘違いしていたのですが、たかしさんの式の4/piであっていますね。
(そう、くくりだした方が、数式を読みやすいし、プログラムも若干高速になりますよ(いちいち各項ごとに乗算をしないでいいから))

あと、-1〜1を越えてしまうことで、wavファイルにしたときに16bitの範囲を超えてしまい、想定しているのと違う音になってしまう可能性を心配していました(音が割れた感じになる)。
そのために、-1〜1の範囲を外れることに対しては、どうお考えなのかとお尋ねしたしだいです。
しかし、矩形波のフーリエ級数展開であれば、最初のコードのように-10デシベルでやるかぎりは問題なさそうですね。
フーリエ級数展開していったときに、不連続点付近のオーバーシュートなどが徐々に大きくなって16bitを越えることがあるのではないかと心配していました。
しかし、実際には積み重なっても極値どんどん大きくなるということは以下のページを見るとなさそうでした(むしろ極値は小さくなっていくのかな)。
矩形波のフーリエ級数展開の極値については以下のギブス現象のページを参考にしました。(あんまりしっかり読んでいませんが)
http://homepage1.nifty.com/th3/gibbs.htm
http://www.sosmath.com/fourier/fourier3/gibbs.html


なお、フーリエ級数展開について詳しいわけではないので、間違っていたらごめんなさい。
また、ギブス現象についてわかっていたため-10dBなら16bitの範囲を超えることはないとわかったうえで-1〜1の範囲を越えることは心配ないとおっしゃっていたのでしたら、失礼。

                └!なお、フーリエ級数展開の低い項からだんだ... 青木太一 2005/01/20 03:19:13  ツリーへ

Re: えーと、ごめんなさい、残りの気になってた... 返事を書く
青木太一 2005/01/20 03:19:13
!なお、フーリエ級数展開の低い項からだんだん足しあげていって矩形波にちかづくようすは以下のプログラムでつくったwavファイルで確認できました。
!たかしさんの卒論なので書かないほうがいいかもしれないとも思ったのですが、せっかく書いてみたので載せます。

!矩形波と、それをフーリエ級数展開したときの低い項から項数を増やしたときどうなるか
option character byte
REM testwave.bas 十進BASICによる音声ファイル生成プログラム
REM (LR:1KHz -10dB 正弦波)
REM chr$関数の引数として全ての1バイト整数が許される様に、オプションメニューの
REM 「互換性」「動作」で「文字列処理の単位」を「バイト」に設定して実行すること
LET nn=20 !<--------------------------------------------------------------------第何項まで行うか
let d=20 !継続時間(秒)
let f0=1000 !正弦波周波数(Hz)
let db=-10 !生成波形の最大値(±32767を0dBとする)
let fs=44100 !標本化周波数(Hz)
let bps=fs*4 !1秒当りのデータ量(ステレオ16ビット量子化)
let dsize=d*fs*4 !オーディオデータサイズ
let fsize=dsize+36 !ファイルサイズ(先頭8Bを除く)
let fmtsize=16 !フォーマットサイズ
let channel=2^17+1 !ステレオPCMデータの指定
let reso=2^20+4 !16ビットの指定
let a=10^(db/20)
open #6 : name "test.wav" !ファイルを開き、この名前のファイルが
erase #6 !既に存在していた場合には上書きを指定
let t0=time
print #6 : "RIFF"; !以下、wavファイルのヘッダーを作成
call out4(fsize) !
print #6 : "WAVEfmt "; !
call out4(fmtsize) !
call out4(channel) !
call out4(fs) !
call out4(bps) !
call out4(reso) !
print #6 : "data"; !
call out4(dsize) !ここまでがヘッダー用の出力
let al=a*32767 !左チャネル係数
let ar=a*65535 !右チャネル係数
let k=f0/fs*pi*2 !引数の刻み
let audio$="" !オーディオデータバッファを初期化
let count=0 !カウンタをリセット
for i=1 to d*fs
LET nnn=int((nn+1)*i/(fs*d))
if nnn>0 then!時間がたつにつれフーリエ級数展開の低い項からだんだんと増えていく
LET omega_t=i*k
LET v=0
for j=1 to nnn*2 step 2
LET v=v+sin(omega_t*j)/j
next j
LET v= pi/4*v
else!まずは矩形波をきかせる(nnn=0のとき)
LET v=sgn(sin(i*k))
end if

let lch=int(v*al+0.5) !左チャネルは1kHz正弦波
if lch<0 then let lch=lch+65536 !負の数は補数表現
LET rch=lch

LET audio$=audio$&chr$(mod(lch,256))&chr$(int(lch/256))&chr$(mod(rch,256))&chr$(int(rch/256))
LET count=count+1
if count=64 then !バッファデータが所定の長さ(64サンプル256Bがほぼ最適)に達したら
print #6 : audio$; !データをファイルに出力して
let audio$="" !バッファを初期化し
let count=0 !カウンタをリセット
end if
next i
print #6 : audio$; !バッファに残ったデータを出力して
close #6 !ファイルを閉じる
print "elapsed time = ";time-t0;"seconds"
sub out4(i4) !4バイト整数の出力(little endian)
LET j4=i4
for m=0 to 3
print #6 : chr$(mod(j4,256));
LET j4=int(j4/256)
next m
end sub
END

                 └返事遅れて申し訳ありません たかし 2005/01/20 14:21:45  ツリーへ

Re: !なお、フーリエ級数展開の低い項からだんだ... 返事を書く
たかし 2005/01/20 14:21:45
返事遅れて申し訳ありません
あと、夜遅い時間まで私のためにプログラムを作って頂いた事、本当に感謝いたします。これで卒論の要旨は、完成しそうです。あと、ギブス現象の事などは、知りませんでした。いい勉強になりました。
先ほど載せて頂いたプログラムで最初に矩形波を出さずに出力したいのですが、プログラムを改良(IF文を削除しただけですが)しても最初の1秒間が無音になってしまいます。以下にプログラムを載せますのでアドバイスよろしくお願いします。

option character byte
REM testwave.bas 十進BASICによる音声ファイル生成プログラム
REM (LR:1KHz -10dB 正弦波)
REM chr$関数の引数として全ての1バイト整数が許される様に、オプションメニューの
REM 「互換性」「動作」で「文字列処理の単位」を「バイト」に設定して実行すること
LET nn=20 !<--------------------------------------------------------------------第何項まで行うか
let d=20 !継続時間(秒)
let f0=1000 !正弦波周波数(Hz)
let db=-10 !生成波形の最大値(±32767を0dBとする)
let fs=44100 !標本化周波数(Hz)
let bps=fs*4 !1秒当りのデータ量(ステレオ16ビット量子化)
let dsize=d*fs*4 !オーディオデータサイズ
let fsize=dsize+36 !ファイルサイズ(先頭8Bを除く)
let fmtsize=16 !フォーマットサイズ
let channel=2^17+1 !ステレオPCMデータの指定
let reso=2^20+4 !16ビットの指定
let a=10^(db/20)
open #6 : name "test.wav" !ファイルを開き、この名前のファイルが
erase #6 !既に存在していた場合には上書きを指定
let t0=time
print #6 : "RIFF"; !以下、wavファイルのヘッダーを作成
call out4(fsize) !
print #6 : "WAVEfmt "; !
call out4(fmtsize) !
call out4(channel) !
call out4(fs) !
call out4(bps) !
call out4(reso) !
print #6 : "data"; !
call out4(dsize) !ここまでがヘッダー用の出力
let al=a*32767 !左チャネル係数
let ar=a*65535 !右チャネル係数
let k=f0/fs*pi*2 !引数の刻み
let audio$="" !オーディオデータバッファを初期化
let count=0 !カウンタをリセット
for i=1 to d*fs
LET nnn=int((nn+1)*i/(fs*d))

LET omega_t=i*k
LET v=0
for j=1 to nnn*2 step 2
LET v=v+sin(omega_t*j)/j
next j
LET v= pi/4*v
let lch=int(v*al+0.5) !左チャネルは1kHz正弦波
if lch<0 then let lch=lch+65536 !負の数は補数表現
LET rch=lch

LET audio$=audio$&chr$(mod(lch,256))&chr$(int(lch/256))&chr$(mod(rch,256))&chr$(int(rch/256))
LET count=count+1
if count=64 then !バッファデータが所定の長さ(64サンプル256Bがほぼ最適)に達したら
print #6 : audio$; !データをファイルに出力して
let audio$="" !バッファを初期化し
let count=0 !カウンタをリセット
end if
next i
print #6 : audio$; !バッファに残ったデータを出力して
close #6 !ファイルを閉じる
print "elapsed time = ";time-t0;"seconds"
sub out4(i4) !4バイト整数の出力(little endian)
LET j4=i4
for m=0 to 3
print #6 : chr$(mod(j4,256));
LET j4=int(j4/256)
next m
end sub
END

                  └fori=1tod*fs 青木太一 2005/01/20 18:03:51  ツリーへ

Re: 返事遅れて申し訳ありません 返事を書く
青木太一 2005/01/20 18:03:51
>for i=1 to d*fs
>LET nnn=int((nn+1)*i/(fs*d))
>LET omega_t=i*k
>LET v=0
>for j=1 to nnn*2 step 2
>LET v=v+sin(omega_t*j)/j
>next j

この部分ですが、iが1からd*fsに増えていくにしたがって、
nnnは0,0,0..0,0,1,1,1..1,1,2,2,2,...nn-1,nn-1,nn-1,nn,nn,nn...nn,nn,nn,nn+1
というような感じで増えていきますね。
nnnが0の間は
>for j=1 to nnn*2 step 2
がいきなり失敗するのでvは0のままとなります。だから最初は無音になります(もともとこの部分に矩形波をいれるためにそうしていました)。

さて、ではどうすればnnnをiが増えるにしたがって
1,1,1,...1,1,2,2,...........nn,nn,nn,nn+1
にできるでしょうか?(まあ最後の一回だけnn+1になる必要はないのですが、どうせ耳に聞こえる波形にはあまり関係ないので、コードが書きやすいようnn+1を書きました。)
>LET nnn=int((nn+1)*i/(fs*d))
をいじればいいはずです。

で、できればご自分で考えていただきたいのですが、一応答えをのせます。

nnn=1+int(nn*i/(fs*d))

なぜこれでいいのか、BASICのヘルプでintの役割などを調べて理解してください。
すでにintについて知っていたり、行き違いでもう解決方法がわかっていらっしゃったら失礼。

                   └詳しい説明ありがとうございます。 たかし 2005/01/20 21:54:47  ツリーへ

Re: fori=1tod*fs 返事を書く
たかし 2005/01/20 21:54:47
詳しい説明ありがとうございます。

これは、十進BASICとは、関係ないのですが、なぜ波形をフーリエ級数展開したとき項数を増やすと波形としては、少しずつ矩形波に変化していくのに対して音としては、6段階程度で矩形波の音に変化していくのでしょうか?

                    └音=振動の形が波形なのですから、音だって... 青木太一 2005/01/20 22:17:06  ツリーへ

Re: 詳しい説明ありがとうございます。 返事を書く
青木太一 2005/01/20 22:17:06
音=振動の形が波形なのですから、音だって同じように項数を増やしていくと少しずつ矩形波に変化していきますよ。

ただ、人間の耳はあまり小さい音や、高すぎる音は聞こえません。

6項目でしたら、まず音の大きさが波形の振幅で1/11になっていますから、かなり聞こえにくいのではないでしょうか。

次に音の高さですが、基本的に人間の耳は20kHzくらいの音が聞くことのできる高さの限界ではなかったでしょうか、CDがその説に基づいていたような。(もっと高い音も聞こえるという説もあるそうですが)
ですから、まだ限界ではありませんが、6項目の11kHz=(1kHz*(2*6-1))くらいからでも十分に聞こえにくいのではないでしょうか。

そういうことを言っているのではないなら失礼

                     └返事ありがとうございます たかし 2005/01/22 11:01:09  ツリーへ

Re: 音=振動の形が波形なのですから、音だって... 返事を書く
たかし 2005/01/22 11:01:09
返事ありがとうございます
また、似たような質問で大変申し訳ありませんが矩形波をフーリエ級数展開したとき波形としては、第25項目くらいまでまで足し合わせた時、視覚的にはほぼ矩形波になりましたが、音としては、第7項目まで足し合わせた時点で矩形波と同じ音に聞こえました。第7項目までだと波形として見ると矩形波には、ほど遠いです。どうして波形の差異と聴感的な差異は、著しく異なるのでしょうか?よろしくお願いします

                      └前の発言の回答ではだめですか?視野の広さ... 青木太一 2005/01/23 01:27:31  ツリーへ

Re: 返事ありがとうございます 返事を書く
青木太一 2005/01/23 01:27:31
前の発言の回答ではだめですか? 視野の広さと解像度、耳のダイナミックレンジと周波数応答性によるものだと思います。

というか、7項だとか25項だとかおっしゃるのはナンセンスです。

波形を目で見るといっても、波形が小さければ第25項まで足しあげなくても矩形と見分けがつかなくなることがあるでしょうし(それこそ第7項で見分けつかなくなる)、
波形を耳で聴くといっても。もっと基準の周波数を1kHzではなく低くして振幅を大きくすれば、7項目では矩形と明らかに違うと感じられるかもしれませんよ。

                       └なるほど!?返事ありがとうございます たかし 2005/01/24 14:22:52  ツリーへ

Re: 前の発言の回答ではだめですか?視野の広さ... 返事を書く
たかし 2005/01/24 14:22:52
なるほど!?返事ありがとうございます

>7項だとか25項だとかおっしゃるのはナンセンスです。
他に言い方が見つからないのでこういう言い方にしました。
何て言えば正しいですか?

本当に度々質問して申し訳ありませんが今、鋸歯状波で第1項目まで足し合わせた音を出力するのプログラム、第2項目まで足し合わせた音を出力するのプログラム、第3項目まで足し合わせた音を出力するプログラム…と順番にプログラムを作っているのですが、第5項目まで足し合わせた音を出力するプログラムを実行してWAVファイルを聞くと明らかに変なノイズが入ってしまいます。同様に第6項目まで足し合わせた場合の音、第7項目まで足し合わせた場合の音も同じでした。どうすればいいのでしょうか?
よろしくお願いします

                        └>>7項だとか25項だとかおっしゃるのはナン... 青木太一 2005/01/24 17:37:57  ツリーへ

Re: なるほど!?返事ありがとうございます 返事を書く
青木太一 2005/01/24 17:37:57
>>7項だとか25項だとかおっしゃるのはナンセンスです。
>他に言い方が見つからないのでこういう言い方にしました。
>何て言えば正しいですか?
そもそも質問自体がナンセンスだったので、正しく言うことはできないと思います。(先に書いたように、波形を図にしたときの見やすさと、音にしたときの聞きやすさを((図の大きさや音の周波数などで))調節すれば、第何項で矩形と見分け/聞き分けできなくなるかはどうとでもなるので)
逆に、ナンセンスさに気づいてなかったからには、あのような言い方しかなかったのではないでしょうか。
私も一瞬そのナンセンスさに気づきませんでしたので。
(「ナンセンス」ってもっとやわらかい言い方はないものかな...)

鋸歯に関してはコードを見せていただかないことにはアドバイスしようがありません。
見せていただかない段階で勝手に想像して考えられるのは
・フーリエ級数展開を間違っているか、実装が間違っている
・フーリエ級数が16bitの範囲を越えてしまって、
 つくられるwavファイルの波形が思ったものと違っている。
 (前に-1〜1の範囲を越えていると心配した件です)
・問題ない。おかしい気がするだけ。
といったところでしょうか。

                         └返事ありがとうございます たかし 2005/01/25 11:35:49  ツリーへ

Re: >>7項だとか25項だとかおっしゃるのはナン... 返事を書く
たかし 2005/01/25 11:35:49
返事ありがとうございます

以下のプログラムは、鋸歯状波で第5項目まで足し合わせた音を出力するプログラムです。よろしくお願いします。

REM testwave.bas 十進BASICによる音声ファイル生成プログラム
REM (L、R:1KHz -10dB 鋸歯状波)
REM chr$関数の引数として全ての1バイト整数が許される様に、オプションメニューの
REM 「互換性」「動作」で「文字列処理の単位」を「バイト」に設定して実行すること
let d=10 !継続時間(秒)
let f0=1000 !正弦波周波数(Hz)
let db=-10 !生成波形の最大値(±32767を0dBとする)
let fs=44100 !標本化周波数(Hz)
let bps=fs*4 !1秒当りのデータ量(ステレオ16ビット量子化)
let dsize=d*fs*4 !オーディオデータサイズ
let fsize=dsize+36 !ファイルサイズ(先頭8Bを除く)
let fmtsize=16 !フォーマットサイズ
let channel=2^17+1 !ステレオPCMデータの指定
let reso=2^20+4 !16ビットの指定
let a=10^(db/20)
open #6 : name "test.wav" !ファイルを開き、この名前のファイルが
erase #6 !既に存在していた場合には上書きを指定
let t0=time
print #6 : "RIFF"; !以下、wavファイルのヘッダーを作成
call out4(fsize) !
print #6 : "WAVEfmt "; !
call out4(fmtsize) !
call out4(channel) !
call out4(fs) !
call out4(bps) !
call out4(reso) !
print #6 : "data"; !
call out4(dsize) !ここまでがヘッダー用の出力
let al=a*32767 !左チャネル係数
let k=f0/fs*pi*2 !引数の刻み
let audio$="" !オーディオデータバッファを初期化
let count=0 !カウンタをリセット
for i=1 to d*fs
let lch=int((2*sin(5*i*k)*al)/5-(sin(4*i*k)*al)/2+(2*sin(3*i*k)*al)/3-sin(2*i*k)*al+2*sin(i*k)*al+0.5)!
if lch<0 then let lch=lch+65536 !負の数は補数表現
rch=lch
LET audio$=audio$&chr$(mod(lch,256))&chr$(int(lch/256))&chr$(mod(rch,256))&chr$(int(rch/256))
LET count=count+1
if count=64 then !バッファデータが所定の長さ(64サンプル256Bがほぼ最適)に達したら
print #6 : audio$; !データをファイルに出力して
let audio$="" !バッファを初期化し
let count=0 !カウンタをリセット
end if
next i
print #6 : audio$; !バッファに残ったデータを出力して
close #6 !ファイルを閉じる
print "elapsed time = ";time-t0;"seconds"
sub out4(i4) !4バイト整数の出力(little endian)
LET j4=i4
for m=0 to 3
print #6 : chr$(mod(j4,256));
LET j4=int(j4/256)
next m
end sub
END

                          └しっかり見ていませんが、16bitの範囲を越え... 青木太一 2005/01/25 12:31:05  ツリーへ

Re: 返事ありがとうございます 返事を書く
青木太一 2005/01/25 12:31:05
しっかり見ていませんが、16bitの範囲を越えてしまっているようです。
てっとりばやい対処としては、デシベルをさげることです。

たかしさんはフーリエ級数の近似する鋸波関数として
f(x)=x (-pi < x <= pi)
を選んだようですが、これは出力する値が-pi〜piです。
今までのように-1〜1の範囲で出力する関数の方がいいのではないですか?
つまり
f(x)=x/pi (-pi < x <= pi)
にした方がいいと思います。

しっかり調べてないのでもしかしたら間違っているかもしれません。
では

                           └f(x)=x/pi(-pi<x<=pi) たかし 2005/01/26 16:16:00  ツリーへ

Re: しっかり見ていませんが、16bitの範囲を越え... 返事を書く
たかし 2005/01/26 16:16:00
f(x)=x/pi (-pi < x <= pi)
にしたらうまくいきました。

これでわからないことは、全て解決したと思います。
何とか卒論を仕上げる事ができそうです。
本当に今までありがとうございましたm(__)m
マジで青木さんと出会えなかったら卒業出来なかったかもしれmせん

またわからないことがでてきたら質問させていただきますので
そのときはよろしくおねがいします。


インデックスへ EXIT
新規発言を反映させるにはブラウザの更新ボタンを押してください。