キノコの自省録

テクノロジーとコンテンツの融合を目指して

音符の長さの計算式

ただのおおまぬけな話。

以前のエントリで、音符の長さとテンポから、実時間長を計算する式を公開しました。

X分音符の時間長と音階周波数の計算メソッド - キノコの自省録

こんな感じです。ついでに、C/C++版も追加しておきます。

def get_duration(tempo = 120, note_len = 4):
    base_ms = 60.0 / tempo
    note_rate = 4.0 / note_len
    return base_ms * note_rate
double getDuration(double tempo, int note_len) {
    double base_ms = 60.0 / tempo;
    double note_rate = 4.0 / note_len;
    return base_ms * note_rate;
}

この式は全く正しいので、問題なく使用できます(tempoに0を入力すると落ちますが)。

以下、音符の長さにまつわる間抜けなお話。

符点4分音符は3分音符ではない

「2分音符と4分音符の間なんだから、3分音符と同じでしょ」と、ずっと勘違いしていました。同様に、符点8分音符は6分音符だと思っていたということです。

当たり前ですが、X分音符というのは、その長さが「全音符/X」という意味です。4分音符は1/4=0.25, 8分音符は1/8=0.125, 合わせると符点4分音符は0.375になります。一方、3分音符は1/3=0.333なので、微妙に短いということがわかります。ちなみに3分音符は2分音符の3連符と同じです。

符点4分音符をX分音符で表現できるか、というと、それは無理です。計算すると、8/3(≒2.67)分音符になります。

なんで気づいたかというと、作ったばかりのMMLパーサに対して、符点やタイなどのチェックをしている時です。やたらと酷い音ズレが発生したため、シーケンサーのコードのせいなのか、パーサのコードのせいなのか、上記音符の時間長計算のせいなのかと色々調べた結果、あっと気づいてしまったわけです。

パーティクルで魔法エフェクト(3) - 氷魔法編

関連記事

パーティクルで魔法エフェクト(1) - 炎魔法編 - キノコの自省録

パーティクルで魔法エフェクト(2) - 光魔法編 - キノコの自省録

f:id:kinokorori:20170327235357p:plain:w120

ウィッチクライドでは、いくつかの魔法をParticle Systemを使って表現しています。

今回は氷魔法を紹介。

氷魔法概要

前回も書きましたが、ウィッチクライドの攻撃魔法は、エフェクトを詠唱の長さに応じて3レベルに分けています。長いほど派手です。今回紹介するのは1レベル目。一番シンプルなエフェクトです。

ターゲットに雪の結晶っぽいパーティクルをワッと表示させ、外側に向かって移動+小さくなっていくエフェクトです。画像にするとこんな感じです。

f:id:kinokorori:20170410214620j:plain:w250f:id:kinokorori:20170410214622j:plain:w250f:id:kinokorori:20170410214623j:plain:w250

ムービーはこちら。

youtu.be

エフェクト実装解説

見た通り非常にシンプルで、基本は1秒間パーティクルシステムを表示しているだけです。パーティクル単体はこれです。実装にも使われています。完全不透明なので、アルファブレンディングしません。

f:id:kinokorori:20170410214913p:plain

パーティクルシステムの実装をそのまま載せておきます。Cocos-2d2なので、Objective-Cですが、他のパーティクルシステムでも基本大差ありません。

+ (CCParticleSystem*)particleIce {
    CCParticleSystem* particle = [CCParticleSystemQuad node];
    particle.texture = [[CCTextureCache sharedTextureCache] addImage:@"ice@2x.png"];
    
    particle.totalParticles = 20;
    particle.life = 1.0;
    particle.lifeVar = .3;
    particle.startSize = 60;
    particle.startSizeVar = 20;
    particle.endSize = 0;
    particle.endSizeVar = 0;
    particle.angle = 0;
    particle.angleVar = 360;
    particle.startSpin = 0;
    particle.startSpinVar = 360;
    particle.endSpin = 0;
    particle.endSpinVar = 360;
    particle.position = ccp(0,0);
    particle.posVar = ccp(10,10);
    
    //emitter setting
    particle.emissionRate = 400;
    particle.emitterMode = kCCParticleModeGravity;
    particle.duration = .3;
    particle.speed = 50;
    particle.speedVar = 20;
    particle.gravity = ccp(0, 0);
    particle.radialAccel = .2;
    particle.radialAccelVar = 0;
    particle.tangentialAccel = .3;
    particle.tangentialAccelVar = 0;
    
    //Color setting
    particle.startColor = ccc4f(5.0, 6.0, 1.0, 0.6);
    particle.endColor = ccc4f(1.0, 1.0, 1.0, 0.4);
    particle.startColorVar = ccc4f(0, 0.03, 0.01, 0);
    particle.endColorVar = ccc4f(0.04, 0.02, 0.02, 0);
    
    particle.autoRemoveOnFinish = YES;
    
    return particle;
    
}

ポイントとしては、まずターゲット中央付近、(-10,-10)〜(10,10)にエミッションします。

    particle.position = ccp(0,0);
    particle.posVar = ccp(10,10);

さらに、パーティクルに回転をかけます。

    particle.startSpin = 0;
    particle.startSpinVar = 360;
    particle.endSpin = 0;
    particle.endSpinVar = 360;

進行方向を360°全方位として、速度を30〜70の間に設定します。

    particle.angle = 0;
    particle.angleVar = 360;
    particle.speed = 50;
    particle.speedVar = 20;

パーティクル終了時のサイズを0に固定しているので、どんどん小さくなります。

    particle.endSize = 0;
    particle.endSizeVar = 0;

主な設定値はこんなところです。ゲーム中では、1秒経過後にパーティクルを削除しています。

パーティクルで魔法エフェクト(2) - 光魔法編

関連記事 パーティクルで魔法エフェクト(1) - 炎魔法編 - キノコの自省録

f:id:kinokorori:20170327235357p:plain:w120

ウィッチクライドでは、いくつかの魔法をParticle Systemを使って表現しています。

今回は光魔法を紹介。

光魔法概要

ウィッチクライドの攻撃魔法は、エフェクトを詠唱の長さに応じて3レベルに分けています。長いほど派手です。今回紹介するのは2レベル目。ガンダム界隈ではゲロビとか言われている種類のやつです。

f:id:kinokorori:20170408193630j:plain:w200f:id:kinokorori:20170408193631j:plain:w200f:id:kinokorori:20170408193632j:plain:w200f:id:kinokorori:20170408193634j:plain:w200

このエフェクトのムービーはこちら。ムービーの方がどんな魔法エフェクトかわかりやすいと思います。

youtu.be

このエフェクトを3段階に分けて解説します。

1段階目

f:id:kinokorori:20170408193630j:plain:w200f:id:kinokorori:20170408193631j:plain:w200

チャージアクションです。これは、CCParticleSunをベースに、パーティクルカラーを白色半透明に固定したインスタンスです。このインスタンスに対し、1秒かけてスケールが0.5→3.0倍になるよう線形アニメーションを発生させています。

画像ではわかりませんが、チャージ完了後、発射アニメーションに移るまで、700msほどウェイトをかけて溜めを作っています。

これまた画像ではわかりませんが、チャージ音は機械系のSEを使用しています。ウィーンという感じの音です。

2段階目

f:id:kinokorori:20170408193632j:plain:w200

発射アクションです。1段階目で作ったチャージ用パーティクルはそのままにしています。レーザー本体もパーティクルで、やはりCCParticleSunをベースにした、白色半透明のパーティクルを使用しています。

実は発射中はアニメーションを発生させていません。パーティクルを横に30倍、縦に5倍引き延ばして表示させているだけです。パーティクルのうにょうにょが、それっぽく見せているため、何か流動性のあるアニメーションが起こっているように見えます。

3段階目

f:id:kinokorori:20170408193634j:plain:w200

発射後3秒経ったら、レーザー本体をスケール0倍になるまで300msでアニメーションさせ、エフェクトを終了させます。レーザー中心点に向かって縮小するので、レーザーがあたかも移動しているように見えます。トリックですね。

レーザー本体が閉じた後、1段階目のチャージパーティクルのリバースアニメーションを発生させ、完全に終了します。リバースアニメーションなので、1秒かけて3.0倍→0.5倍にするということです。

ソフト屋の技術区分

どうも非ソフト・非技術サイドからだと、一口にソフト屋といっても、いろんな人がいることがわかりにくいようです。というか、ソフト屋でもよくわかってないことが多い気がします。

ソフトと一括りにしてしまうと、組み込みでドライバー作っている人に、「Webクライアントアプリ書いてよ。ソフト屋なんだからできるでしょ?」みたいな話が罷り通ってしまいます。これは悲劇です。ソフト=コード書く人くらいな意識です。

ということで、ちょっとソフト屋区分を整理してみました。厳密ではなく、ああ、ソフトといっても結構幅が広いのね、くらいな気持ちで。

Webクライアント屋

Webブラウザ用アプリを作成する人です。今はhtml/css/js一択でしょう。jsと一口にいっても、jQueryをはじめ、AngularJSやReactJSなど、色々なライブラリが用意されてきている上、TypeScriptやCoffeeScriptCSSでもSCSSといった技術が最近矢継ぎ早に公開されており、それなりにキャッチアップが必要な分野でもあります。

こんなに技術の変化が激しくなったのも、Webブラウザの進化によるものです。Webクライアント用言語と言えばJavaScriptなものの、JavaScriptは仕様的にあまり大規模開発に向かないため、ライブラリがJavaScriptの欠陥を補う形で、要求に合わせてどんどん変化しているといった具合です。

また、デザイナーとのやり取りが多く発生する技術分野ということもあり、デザイナーとのコミュニケーションや納入、実装がかなりのウェートを占めると思います。一昔前のjQueryのみでのAjax実装だと、JavaScriptコードにhtmlやcssのコードが散乱して、めっちゃくちゃなことになっていました。そういうこともあって、ReactJSなどの技術が生まれているのではないかと思います。

Webサーバ屋

Webサーバ上のアプリを構築する人です。言語はPHP, Perl, Ruby, Javaあたりがメジャーで、最近ではNode.jsやPythonなども。大抵は外部公開部分(WebAPI)→コントローラ→データベースまでの処理を書くことがほとんどです。Webサーバにはデータベースがつきものなので、SQLの知識は必須です。

Webサービスがビジネスの根幹を担うことが多いこともあって、JavaPHPが書ければ食いっぱぐれないと言われるくらい、お仕事が見つかる分野でもあります。

フルスクラッチですべて書き起こすことは稀で、大抵はRailsやCake, Laravelなどのフレームワークに乗っかって実装を行います。最近は、サーバレスと言われるアーキテクチャが登場しており、それを使うならば機能モジュールの組み合わせでシステムを実装することになります。

Webサーバアプリは、コントローラ層のアーキテクチャ、データベース処理、セッション管理、セキュリティ、並列化あたりがカギだと勝手に思っています。この辺の設計が適切に行えるかどうか。

昔は、負荷分散や冗長化、デプロイやステージングといったインフラ部分を含むことが多かったですが、最近ではその部分はインフラ担当として明確に分けられていると思います。

サーバインフラ屋

サーバのインフラ担当です。あまりコードを書くことはしませんが、OSとネットワークの知識(主にLinux)が必須で、各種開発支援ツールのconfファイルの編集、シェルスクリプトなどを組んで自動化したりといったことを担当します。また、サーバ保守も大抵の場合担当します。

クラウドサービスが主流となったことで、インフラ周りも随分様変わりしたように思います。クラウドサービスが流行る前は、自社内でブレードサーバを物理的に組み上げて、サーバ自体の冗長化NIC冗長化、ハブ・スイッチの冗長化など、自分たちで色々考えて信頼性を担保していました。いわゆるオンプレミスというやつです。

昨今のクラウドサービスでは、冗長化はもちろん、スケールアウト(負荷に応じてサーバを増やす)も自動でやってくれますし、スケールアップ(サーバ自体の性能を上げる)もポチポチするだけで終わってしまいます。凄い時代になったものです。

かといって、インフラ屋がやることなくなったかというと、そんなことはなく、物理的な心配がなくなっただけです。デプロイやステージングを考えたり、JenkinsやGit、SlackやRedmineといった開発支援のためのツールをうまく組み合わせて導入したり、シェルスクリプトを書いて自動化したりと、結構大変です。特に、ツールは流行り廃りもあるため、常にアンテナを高く張っておかないと、ついていけなくなったりします。

また、最近のクラウドサービスでは、普通のサーバインスタンス(AWSならec2)だけでなく、色々なモジュール(AWSならLambdaやAPIGatewayなど)が用意されるようなってきています。どういったものがあるかといった知見も広げておく必要があると思います。

DeepLearningなどでビッグデータを扱うとき、クラウド上で実験すると課金死するため、HadoopやSparkなどの分散処理システムを組み上げる必要に迫られます。この辺をスッとできると途轍もないイケメンです。

Webクラサバ・インフラをひっくるめて一人でできるスキルを持った人を、フルスタックエンジニアと呼んでいたこともありますが、最近でも言うのかどうか不明。

システムエンジニア

いわゆるSEです。この人は基本的にコードを書きません。要求されたシステムをどう組み上げればよいか、どういう技術と人が必要で、どれくらいかかりそうかを見積もって、スケジュールを立てる人です。QCDの番人。

コードを書かないからと言って、コードが書けなくてもいいわけではありません。自身の経験が、それぞれのタスクがどれくらいかかるかの工数見積もり精度に跳ね返ってきます。

また、浅くても良いので広い知識が必要です。「IoTデバイスから収集したデータをスマートフォンで閲覧できるシステム」の構成を考えなければならない時、IoTデバイスはサーバにどうやってデータを上げるのか、iOS/Android特有の癖、データベースはどうするのか、リアルタイム性はどこまで求められるのかなどを把握する必要があります。OSI参照モデル7層って何?httpなにそれ、iOS/Androidよく知りません、RDBMS/KVSって何?WebAPIって何?では仕事にならないでしょう。

システムが担うドメインの知識も必要になりますが、そこは知らなくても、客先やプロダクトオーナーから話を聞き出したり、不明な点を洗い出したりすることで補うことは可能です。逆に言うと、「不明な点」を正確に捉える能力が必要です。

プロダクトオーナー(プロデューサー)との連携も密に取る必要があり、場合によっては客先に技術説明をしに行ったり、技術的な不明点をヒアリングしに行くこともあります。

フレームワーク屋・ソフトウェアアーキテクト

こういう区分でいいのか迷うところですが、大き目の社内開発プロジェクトのソフトウェア構成を統括する設計者です。

この世には汎用フレームワークSDK、例えばUnityなんかもそうですが、そういったものが数多あります。しかし、それらはあくまで汎用であって、個別プロジェクトに最適化されているわけではありません。そのため、SDKだけ無計画に社内プロジェクトに導入しても、即座に破たんします。そのため、全体的なソフト設計、および適切なルール作りが必要になります。

この役割の人は、オブジェクト指向デザインパターンを適切に行使でき、プロジェクトで使用する言語のイディオムを把握している必要があります。ドメインの知識も必要で、開発チーム間の調整も多く発生します。決断力がない人や手持ち選択肢の少ない人にはあまり向きません。また、この役割の人が適当な指示を出すと、開発後段になって工数が雪だるま式に増えていき、バグつぶしがモグラ叩きの様相を呈するようになります。そしてメンバーは終わりの見えないプロジェクトに嫌気が差し、心を病むようになります。

また、同じ業務をずっとやっている人より、色々なシステムや言語を触ったことのある人の方が適任です。

フロントエンド・アプリ屋(Web以外)

これもまた定義が難しいところではありますが、提供されたSDKやプラットフォームAPIをたたいて、GUIアプリケーションを作り上げる人です。フロントエンドと一口に言っても、Windowsなら大抵C#.NET、MacならCocoaマルチプラットフォームならJavaAIR、Qtなど、多岐にわたります。インタフェース記述言語もFormデザイナ、InterfaceBuilderやXAML, Flex, QtQuickなどバラバラです。

GUI設計においては、どうすれば使いやすいかといった、ユーザビリティ的な考えだけでなく、どうすれば楽しく操作できるかといった観点も結構重要で、UIの工夫がそのまま強力な特許となることが多々あります。ソフトウェア特許でUI発明というのは、侵害検知が非常に簡単なため割と重宝されます。

GUIとプラットフォームとを繋ぐ部分については、システムによってサイズが大きく異なります。1人で開発できる程度のものから、1モジュールだけで1チームが割り当てられるものまで様々です。1チーム必要なレベルのモジュールが入っている場合、それがその企業のソフトウェア価値に直結することが多いのではないかと思います。専門部隊とか呼ばれたりします。

スマホアプリ屋

フロントエンド・アプリ屋の一種で、スマホ、主にiOS/Androidアプリを作る人です。スマホアプリといっても、FGOやデレステみたいな大規模なものではなく、ここでは1,2人程度で作成する小規模なものを想定しています。

iOSならばObjective-C/Swift, AndroidならJava, UnityやXamarinなどを使用するならC#も絡みます。スマートフォンは結構癖の強いデバイスのため、開発言語だけでなく、それぞれのプラットフォーム固有の知識が多く必要になります。開発経験が全くないと、HelloWorldプロジェクトのビルドすら難しかったりします。また、iOSが出来るからと言ってAndroidが出来るとは限らず、逆も然りです。実際、どっちも書ける人はそんなにいません。Androidが出来るんだったらiOS版も作ってと気軽に言ってはいけません。

繰り返しになりますが、スマートフォンは癖の強いデバイスで、完全に独自の世界を構築しています。AndroidiOSも、ビックリドッキリ機能やお約束があったりするので、開発未経験の人に仕事を振っても、そうそうすぐにアウトプットは出てこないと思った方が良いでしょう。

ミドル・BSP・ドライバー

組み込み系の人たちです。ざっくりまとめてしまいましたが、組み込みといえばここがメインです。大抵の場合、使用する言語はC/C++です。

この界隈の人たちは、バイナリデータを扱うことが多く、デバッグコンソールに表示された16進の羅列を読み取る変な能力が身に付きます。かなりハードウェアに近いところにいるためか、あまりソフトウェアの設計能力は高くなく、C++であっても、Better Cとして扱うことを好む人が多いように見えます。

この人たちのやっていることは、Androidスマホを思い浮かべるとちょっとわかりやすいかもしれません。Androidは、Androidプラットフォームだけが共通で、ハードウェアはそれぞれの会社が独自で用意します。Androidスマホの性能を語るとき、PCと同じようにCPU+メモリ性能で考える人がそれなりにいますが、そう単純ではありません。Androidスマホは組み込み機器です。例えば、SoC基板、WiFiモジュール、GPSモジュール、Bluetoothモジュール、タッチパネル、物理キー、マイク、スピーカー、LTEモジュール、バッテリー、センサー等々が、メーカーごとに異なります。ということで、これらが1つの機器上で動作するように制御するのが組み込みエンジニアの仕事です。

これらのハードウェアをぐさっと繋いだら動くかというと、当然そんなわけはなく、まずは全てドライバーを用意しないと動いてくれません。で、ドライバーが全て用意されたらOKかというと、そんなことはなく、システムとして全体を繋いだり、キャリブレーションしたりする必要があります。システムとして繋いだらOKかというとそんなことはなく、SDK側から呼び出し可能なようにAPIを整理しなければなりません。

音声経路、映像経路(フレームバッファ)も、何もしなくても出力してくれるようなことはありません。ちゃんと制御が必要です。音声ドライバはAndroidだとALSAを使うことが多いと思いますが、音なんか鳴ればいいんじゃない?みたいに設計すると遅延が酷くなります。

Androidスマホの品質がメーカーによって異様なほどバラバラで、PC的なスペックの観点があてにならないのは、これでなんとなく想像つくのではないでしょうか。組み込みエンジニアというのは、こういう世界の人たちです。

マイコン

マイクロコンピュータ用の制御コードを書く人で、組み込みエンジニアの一種です。回路屋に一番近い位置にいます。

AVRやH8などの小規模マイコンと、FPGAなどの高性能マイコンがあり、前者はCやアセンブラ、後者はVHDLを使用します。最近では、VHDLの代わりにSystemCが用いられることも増えてきたとかいう話も聞きます。

マイコンが必要になるのは、在りもののモジュールでは事足りず、ハードウェアを独自に制御する場合です。そのため、通信プロトコル仕様も、開発者が考える必要があります。この仕様を、ある程度将来の拡張に備えて設計しないと、通信プロトコルがころころ変わることになり、その度にドライバー屋が苦労します。

ちなみに私はAVRをたたいたことがある程度で、この分野詳しくありません。まあ、7年前に書いた下記エントリー見れば推して知るべしというところではありますが・・・

ソフト屋はハードウェアがわからない - キノコの自省録

コンピュータサイエンティスト

計算機科学の研究者です。圧縮技術、映像・音声符号化、暗号、機械学習、最適化、データサイエンスなど、色々なテーマがあります。この分野の人たちは、C++, Python, R, Matlabあたりを使うことが多いと思います。大抵のソフトウェアエンジニアリングの業務は、高等数学や物理の知識なんかほとんど必要ありませんが、コンピュータサイエンティストには必須です。

エンジニアではなく研究者のため、専門以外は実はよく知らないという人も結構いたりします。大学ではなく、コーポレートラボ付きの人であっても、ソフトウェアのトレンドに全く詳しくないということもザラです。ただ、地頭の良い人が多いため、何も知らない状態でも、しばらくするとあっさりキャッチアップしたりします。恐るべし。

終わりに

ということで、最近のソフト技術区分をなんとなく書いてみました。ソフトと一口にいっても、こんなに種類があるのか、と思っていただければ。

X分音符の時間長と音階周波数の計算メソッド

YMZ294を弄っていて必要になったので、公開しておきます。これ使って風色メロディ鳴らすことができたので、たぶん合っていると思います。

Raspberry piで遊んでいるので、コードはpythonです。

# ymz294_util.py
# -*- coding:utf-8 -*-

__scale_freq = []

C = 0
Cs = 1
Db = 1
D = 2
Ds = 3
Eb = 3
E = 4
F = 5
Fs = 6
Gb = 6
G = 7
Gs = 8
Ab = 8
A = 9
As = 10
Bb = 10
B = 11

def get_duration(tempo = 120, note_len = 4):
    base_ms = 60.0 / tempo
    note_rate = 4.0 / note_len
    return base_ms * note_rate

def get_freq(scale=A, octave=4):
    scale_number = 12 * octave + scale
    return __scale_freq[scale_number]    

for scale in range(88):
    ex = (scale - 57) / 12.0
    f = (2 ** ex) * 440
    __scale_freq.append(f)

ymz294_util.get_freq(scale, octave)を呼び出すと、その音階の周波数を返します。ymz294_util.get_duration(tempo, note_len)を呼び出すと、テンポと音符から算出したノートオン時間を秒単位で返します。

YMZ294のエンベロープについて

ちょっぴりとっつきにくいYMZ294のエンベロープについて。

YMZ294には、音量を増減させるためのエンベロープ機能が用意されています。音量だけなので、今ならソフトウェア的に強引に変えたり、回路工夫すればこれ使わなくても表現できますけど、せっかく用意されている機能なので、使わない手はないでしょう。

PSGのエンベロープとの出会いは、私が小学生の頃、MSX時代に遡ります。しかし、当時はエンベロープパターンと周期の関係がいまいち理解できず、謎の機能としてなんとなく使用していました。

どうでもいい話はおいといて、エンベロープの設定は、次のように行います。

エンベロープ周期

エンベロープ周期は、16bitで設定します。0~65535です。確か、MSXMMLでも、この値を入力していた記憶があります。

YMZ294の値指定はだいたいどれもそうなのですが、この値が直接使われる、つまり、この値=周波数ということはありません。仕様書に記載の通り、

fe =  fsc / 256EP(Hz)

です。EPは入力値、fscは2,000,000です。つまり、65535を入力すると、fe=0.1192(Hz)となります。値が大きいほど、周波数が小さくなります。

EPの値域は0~65535のため、エンベロープ周波数の値域は、0.1192 < fe < 7812.5と求まります。

fe=1Hzだと、エンベロープパターンを1秒に1回繰り返す、fe=1000Hzだと、エンベロープパターンを1秒に1000回繰り返すということです。念のため。

エンベロープパターン

エンベロープパターンは、仕様書に書いてある通りです。単純に減衰したり、ギザギザの音量変化をしたりといった具合です。ただ、これエンベロープ周期との関係がいまいちわかりにくいです。

一応書いてあるのですが、最初見たとき意味がわかりませんでした。この赤線のところに書いてあります。

f:id:kinokorori:20170405232017j:plain

何を言っているのかというと、fe=1Hzの時、→| |←これで示される幅が1周期分だということです。例えば、単純な減衰の場合、fe=1Hzだと、ちょうど1秒で音量が0になります。山型のエンベロープの場合、fe=1Hzの時、2秒で登って下ります。

エンベロープ使用上の注意

これも仕様書に書いてありますが、エンベロープパターンをレジスタに書き込むと、YMZ294内部のカウンター(5bit)をクリアして、カウントを開始します。繰り返し系のエンベロープの場合は問題ありませんが、繰り返しのないエンベロープパターン(0, 4, 9, 11, 13, 15)は、一度カウンタが上がりきってしまうと、そこでストップしてしまいます。

つまり、メロディーを1音鳴らすたびに、エンベロープパターンをYMZ294に書き込んで、カウンタをリセットする必要があります

エンベロープサンプルムービー

エンベロープなし、9番0.8Hz, 10番10Hz, 10番100Hzです。ギザギザ系のエンベロープは、周波数を上げると歪んで聞こえるようになります。ちなみに曲は風色メロディ。

youtu.be

YMZ294で音が鳴らないときのチェック項目

一通り鳴らないやらかしをやったので、備忘録的に。

配線は間違っていないか

YMZ294以前の話というか基本中の基本ですが、何しろ線が多いので、よくミスります。例えば、Arduino NanoでPORTDを使用する時、D0とD1を逆にしないよう気を付けましょう。

また、ブレッドボードでの確認を最初にすると思いますが、配線が浮いていないか、導通しているか確認しましょう。

秋月で買った場合、C012100という水晶がついてきますが、脚を間違いやすいので、よく確認しましょう。

SO-GND間の抵抗

SOはソースフォロワだそうです。1KΩ程度の抵抗をGNDにつながないと、電圧が変化せず、音が鳴りません。

WRCS, A0

レジスタアドレスやレジスタ値を変更するときは、以下の手順で行います。

  1. /WR /CSをLOWに落とす
  2. A0やD0~D7のLOW/HIGHを設定
  3. /WR /CSをHIGHに変更

/WR /CSがLOWでセットアップ、HIGHでホールドということです。ホールド時に値を変更しないようにしましょう。

また、A0はLOWでレジスタアドレス、HIGHでレジスタ値です。逆にしないよう注意しましょう。

ボリューム、ミキサー、楽音

出力したいチャネルのボリュームを設定しましょう。チャネルAの場合、レジスタアドレス0x8に対して、0xfを書きましょう。レジスタ値を0x10とするとエンベロープモードになりますが、エンベロープは直感的にわかりにくい上、音が鳴らない原因にもなるので、音出し確認までは避けた方が無難です。

ミキサーの設定(0x7)は、鳴らしたいチャネルのビットを0にします。チャネルAのみを出力するのであれば、とりあえず0x7に対して0x3e(=0b00111110)を書き込みます。

楽音の設定は、チャネルAの場合、鳴らしたい音をレジスタ0x0, 0x1に書き込みます。秋月の資料にならって、0x0に0x1c, 0x1に0x1を書くのがとりあえず良いかと思います。

ソフト的には、これらボリューム、ミキサー、楽音の設定が最低限必要です。