前回のブログを書いた後、大きな改変がありましたので
予定を変更して、前回話した新和音関数について
新しくなった部分を綴っていきます。
ただ、まだ進行形状態なので自分用メモに近い形ですがご容赦ください。
真・新和音関数
新和音関数の更なる細分化をする
前回作った新和音関数は1音鳴らす時にwait_ms()を使い
音の出る長さを調整していました。
が、コンマ何秒という拘束時間が生まれてしまいます。
そこで、wait_ms()の中身で使っているtimerという変数を使い
今までwait_ms()で拘束していた時間分も音を分けて鳴らす仕組みを作ります。
このままでは何のこっちゃと思われるので解説をしていきます。
wait_ms()では音が鳴ってる間、何も出来ませんが
timerでカウントする事により、1ms単位で曲の進行、中断が出来ます。
では、どうやってtimerを使って和音関数を新しくするか
の前にwait_ms()関数とtimerという変数について説明します。
wait_ms()とは
サンプルプログラムのmisc.cというファイルの中身はこうなっています。
extern volatile unsigned int timer; void wait_ms(int wtime) //mS単位で待ち時間を生成する { unsigned int start_time; start_time = timer; while( (timer - start_time) < wtime) ; }
この仕組みを流用するのですが、timerの動きがわからないと説明が出来ないので、
interrupt.cにあるint_cmt2を見てもらいます。
void int_cmt2(void) //1msタイマー用 { timer++; //1mSごとにカウントアップ battery_save(getBatteryVolt()); //バッテリ監視 }
ここにtimerの正体があります。
注釈にある通り、割り込みで1ms毎にカウントアップされている変数です。
これとwait_ms()の仕組みを新和音関数に使わせてもらいます。
新和音関数の再構築
前回紹介したbwsoukou()を再構築すると
void bwsoukou(float w1, float w2, float w3) { switch(skds2) { case 1: waon(5,w1); break; case 2: waon(5,w2); break; case 3: waons(2,w3); break; } }
こうなります!
はい、これでは全然わからないので説明します。
今回複数個の和音関数を作る際に簡単に作れる様に中身も関数化しました。
waon(5,w1)の5の部分を変えて和音バランスの違う関数を作ります。
この5という数字は旧和音関数のwait_ms(yy*5)の5にあたります。
3和音それぞれに振ったこの数字の合計を一定にし、それぞれのバランスを変える事で
和音として聴こえる様にいくつもバランスの違った関数を作ります。
というのはこれまでの復習ですね。
ではwaon()の中身はどうなっているのかというと
void waon(int krk, float oto1) { SET_BUZZER_FREQ(oto1); ENABLE_BUZZER; if(sktm0 == 0){ sktm0 = timer; } else{ sktm = timer - sktm0; } if(sktm > yya*krk){ skds2++; sktm=1,sktm0=0; DISABLE_BUZZER; } }
大雑把に言うと最初に言った通り旧和音関数にwait_msの仕組みを入れて
1ms毎の曲の進行が出来る。というものです。
timerはただひたすらカウントし続ける変数なので、この関数に入った時の基準の数値として
sktm0にその時の数値を入れます。
後は、timerの進み具合から先ほどの基準の数値を引けば
経った時間が判るのでwait_ms(yy*5)で使っていたyy*5と比較すれば良い、という事です。
今回の改変に伴い、多数の変数をグローバル化したので
yyの部分も新しくyyaという変数になっています。
この関数を並べて行く事で和音になるのですが、最後だけは違う処理が必要なので
締めの処理は別にこう作りました。
void waons(int krk, float oto1) { SET_BUZZER_FREQ(oto1); ENABLE_BUZZER; if(sktm > yya*krk){ DISABLE_BUZZER; sktm=1,sktm0=0; skds++; if(skds > yya0){ skds=1; skds2=1; skd++; } else{ skds2=1; } } else{ if(sktm0 == 0){ sktm0 = timer; } else{ sktm = timer - sktm0; } } }
これも旧関数にtimerを入れて処理しているものです。
これで真・新和音関数の出来上がりです。
まとめ
これまでの参考資料からの曲の打ち込み易さを重要視しているので
特に曲の打ち込み方に大きな変更点はなく、ほぼ以前通りの作り方で
疑似和音の曲が作れる様にしていますが、細分化に伴い
どうしても追加しなければならない点があるので、次回
和音関数を使い、曲を作りながら解説します。