スプーキーズのちょっとTech。

SPOOKIES社内のより技工的な、専門的なブログページです。

エイチームさん主催の勉強会に行ってきた

技術ブログの方では「はじめまして」になります、アルバイトの 本田 です!

急ではありますが、スプーキーズには勉強会参加支援制度があります。

勉強会参加支援制度とは、勉強会に参加する費用を会社から出してもらう代わりに、

学んできたことを社内にフィードバックする制度です!

今回は、僕が勉強会参加支援制度を使って参加してきたエイチームさん主催の勉強会について、

社内だけでなく、社外にもお伝えできれば!と思います。


↓ 以下本編↓

TL;DR

  • エイチームさんが実際のサービスで使った便利なミドルウェアやツールの紹介
  • MySQLオンラインマイグレーションツールgh-ostで深夜メンテ回避
  • RUNDECKでジョブを一元管理
  • VSCodeが熱い!(Emacs民に人権なし。悲しみ。)
  • MySQL界隈が熱い!
  • 俺はエンジニアだ!俺は速くしたい!(パフォーマンスチューニングの話)

勉強会情報

  • イベント名:ATEAM TECH 大阪「見せます!Webサービス開発を支えるミドルウェア/ツール」
  • 主催:エイチームさん(大阪支社)
  • 主題:Web開発において便利なミドルウェアやツールを紹介。主にサーバサイド
  • イベントリンク:https://ateam.connpass.com/event/104825/

キーノート おおざっぱまとめ

【発表01】MySQLオンラインマイグレーションツールgh-ostで深夜メンテナンスを無くした話

発表者:s2terminal さん

ある日、深夜メンテナンスが必要となった

  • エイチームさんのとあるサービス

    • DAU:数十万
    • Monthle Page View:億以上
  • そのサービスで使用しているDB

    • MySQL
      • 構成:master/slave
      • donwloads:600万件以上
      • データベースI/O:数十/秒(同社サービス内トップ?)
  • あるテーブルに新しくカラムを追加しないといけなくなった

    • 現在DBに格納されているレコード数は膨大
    • migrateに時間がめちゃくちゃかかる

↓でもでも

  • サービスを止めるわけにはいかない…(じゃあ、深夜メンテ?)
  • 深夜メンテは絶対にしたくない…
  • なにか良い方法はないか…

GitHubがいい感じのツールをOSSで開発してるよ

その名は 『gh-ost』

  • Github:https://github.com/github/gh-ost
  • 正式名称:GitHub's Online Schema Migrations for MySQL
  • オンラインマイグレーションツール
  • 本番で動いているテーブルのコピー(ゴーストテーブル)を作成し、そっちにmigrateかけて、できあがったら本番のものと入れ替える
  • 本番用のテーブル内のデータが更新されたときは、非同期でゴーストテーブルも更新する。
    • レプリケーションの作成って非同期ですよね?それと同じ仕組みを使うことで、gh-ostも非同期で、データ同期できます!
      • すなわち、binary logを見てる

gh-ostのいいところ

  • 実行状況をGUIで確認できる
  • migrateが完了したゴーストテーブルと本番テーブルの入れ替えは手動で行える
    • gh-ostにmigrate作業を深夜のうちにやっておいてもらい、担当者が出社してきたら、テーブルの入れ替えをコマンドひとつでぽちーっとやって、動作チェックできる!
    • もちろん全て自動で行うことも可能!

つまり、深夜メンテしなくてよくなった!

感想

エイチームさんが運用している大きなサービスで実際に使ったツールに関する話で、動かしてみてどうだったかというところも聞けたのでかなりおもしろい話だった。

自分も来年から大規模なサービスに関わるので、こういった知識は大変ためになる。

【発表02】サービスを支えるジョブ管理システム

発表者:kytiken さん

エイチームにおけるジョブ(バッチ処理)

  • アフィリエイトサービスにおける、クライアント企業へのレポートメールなどはジョブとして、定期的に自動で行っている。

ジョブ管理システム有名所

  • cron
    • 管理するジョブが増えてくると分かりづらい(ただのコマンドの列挙だし)
    • サーバが増えてくると、あのcronどこで管理してたっけ?ってなる
    • エラー時のログが分かりづらい

解決策 『RUNDECK』

  • RUNDECK
    • ジョブスケジューラ
    • 実行されるジョブ一覧を管理画面で確認できる
    • 実行状況をリアルタイムで確認できる
      • パーセンテージ表示
    • rundeckがssh接続でサーバにアクセスしジョブを実行する(エージェントレス)
    • cronと同じ形式で記述可能(cronからコピペするだけでいい)
    • webhook対応(slackへの通知も可能)
    • fluentdにログ保存可能
    • rundeckのGUIでジョブ登録可能(コマンドとかジョブ名、実行サーバ名とか入力するだけ)

rundeckで運用してみて

  • rundeck自体が落ちたら全ジョブが死ぬ(当たり前)
    • 対策:クラスタモード
  • 動作が重い
    • t2.smallで運用していたが、ジョブが増えるにつれて重くなった
    • 対策:JVMのチューニング
  • h2databaseがデフォルトDB
    • Java動作で負荷が高くなった(重い?)
    • 対策:外部DBに変更
  • ジョブの頻度が多い場合に負荷が高くなり始めた
    • ログが大量になったため負荷が高くなった
    • 対策:ログを定期的に削除
      • APIが存在するが、全削除しかなくて困る(対策要検討)

感想

こちらの話も実際にRUNDECKで運用してみてどうだったかという話まで聞けたので、参考になった。

ジョブは一元管理するか、ドキュメント作ったりしないと、すぐに迷子になってしまうものだと思っているので、こういうツールはいいと思いました。

ただ、デメリットも多い模様で、使うときは要検討!

【発表03】サービスで活用したRailsパフォーマンスチューニングツールの話

発表者:@sakupa さん(エイチームの方)

パフォーマンスチューニングをやることになった経緯

  • 開発優先でパフォーマンスチューニングできてなかった
  • ISUCONに出て刺激を受けた
    • 大会でやったことを業務に活かす!
  • なぜパフォーマンスチューニング?
    • 俺はエンジニアだ!俺は速くしたい!
      • ↑かっこよすぎる

パフォーマンスチューニングにおける優先度を決定

  • CV(コンバージョン)に繋がるページ
    • コンバージョン:Webサイト上で獲得できる最終的な成果
  • できるだけ小さい改修
  • あくまでリファクタリング

パフォーマンス監視サービスの導入

  • New Relic(ニューレリック)
    • ローカル段階から導入できる!
    • Railsならgemいれるだけで動く

発行クエリ数が多いぞ!?

  • New Relicにより発見
  • 続けてrack-mini-profilerで調査するとN+1問題が発生していることも見つけた
  • bulletでN+1問題の場所特定
  • チューニング!

パフォーマンスチューニングにおいて大事なこと

  • ボトルネックを細かく追うこと

感想

パフォーマンスチューニングをやるさいに、先輩からなぜやるのか聞かれたそうですが、「俺はエンジニアだ!俺は速くしたい!」と言い切ったそうです。 こういうエンジニアになりたいです。

プロファイラは僕も触ったことがありますが、導入が大変だったのを覚えています。 RailsならGem入れるだけでごにょごにょしてくれるらしい!(それがいいのか悪いのかは置いといて…)

LT大会 おおざっぱまとめ

【LT01】Effective Debugging React Apps in VSCode

発表者:むらじゅん(@murajun1978)さん

宣伝

どのエディタ使ってますか?

  • VSCodeが大半
  • Emacs民の人権なし

No more Print Debug

  • print debug は無駄が多い
  • VSCodeのデバッグ機能をどんどん活用していこうという話
    • ただし、Railsでは ruby-debug-idedebase gemが必要
      • 最新版はうまく動作しないから、Beta版使わないといけない
  • VSCode Recipes にデバッグのサンプルいっぱい
  • なにやらVSCodeのデバッグに関する設定ファイル?について話されていたが、そもそもVSCode使っていない僕にはなんのことか分からなかった…(ここが本題だったのに…)

感想

最近、VSCodeが熱い!って話をよく聞くけど、会場の8割型がVSCodeユーザだったのは焦った。

自分もちょっと試してみようかな!

【後日談】

家に帰って試してみました。 結論としては、以下の理由で即アンインストールしました。 - 自分の用途の範囲では、別にVSCodeだからできることがなかった - Emacsのキーマップにしましたが、デフォルトのキーマップとコンフリクトしまくり

感想:エディタひとつでなんでもやってしまいたい人にはいいのかも。でも、僕はIDEはIDE。エディタはエディタで分けたい人。… アンインストール!

【LT02】MySQL InnoDB Cluster

発表者:@masayuki14 さん(スプーキーズのアンバサダーです!)

発表資料:https://speakerdeck.com/masayuki14/mysql-innodb-cluster-woshi-tuteyun-yong-woshou-ba-kisiyou

MySQL InnoDB Cluster がすごい

  • 3つのコンポーネントを使って作る高可用性構成
  • セットアップが簡単
    • MySQL Shell で簡単にセットアップ
  • 自動フェイルオーバー
  • マスターの自動昇格
  • M/Sの接続を自動で切り替える
  • スケールアップが容易

感想

他の参加者の方がMySQL Routerが単一障害点になるからどうなんだろう…って議論されていて、それを聞くのも、またおもしろかったです! (確かにMySQL Routerが死ぬと終わりですね…)

↓ 社内勉強会にて @masayuki14 さんからもらった補足コメント

MySQL Routerは、Appサーバーに同梱して動作させる使い方がいいのだけど、 昨今のコンテナを使ってやる場合、AppコンテナとMySQLRouterコンテナに分離すると MySQLRouterが単一障害点になるんじゃないか、っていうはなし。

MySQLRouterコンテナも一つじゃなくて複数建てれば分散できる。 MySQLRouterの死活をチェックして別の接続先に切り替える、 みたいな冗長化するのはあんまり意味ないんじゃないか、というところ。


全体を通じての感想

f:id:spookies_honda:20181206201659p:plain:w350
お酒!ピザ!お寿司!

Meet Up 形式のイベントだったため、 勉強会スタート前からお酒飲んだり、ご飯を食べたり、かなりアットホームな雰囲気で始まりました。

エイチームさんが実際に使っているツールを知ることができ、加えて、実運用においてどうだったかというところまで教えてもらえたので、かなり有意義な時間でした。

次は来年の1, 2月ごろ開催だそうです。 また参加したい!

はんなりPython#3 で発表してきました

アンバサダーの id:masayuki14です。はんなりPython#3という勉強会で発表してきました。 この勉強会は「はんなりPythonの会」という京都のpythonコミュニティが主催していて、私も運営で参加しています。

今回は「JupyterNotebook入門」というタイトルで発表を行いました。 JupyteNotebookはPythonでのデータサイエンスには必須のツールなので、セットアップ方法や簡単な使い方を紹介しました。

speakerdeck.com

スライドなどの資料はこちらでも公開しています。 例として福井県の積雪量をグラフにしたんですが、今年以上に昭和の豪雪がすごかったことがわかりました。

f:id:masayuki14:20180226110359p:plain

さて、次回は 3/16 にはんなりPython #4 LT大会 with Beerが開催されます。 我らが専務 id:spookies-nishimura 氏も参加しLTを行います。 お近くの方はぜひ参加して下さい。

connpass.com

3Dモデルを作りたい2

こんにちはntykです。

f:id:spookies_nytk:20170714100033p:plain

以前は↑の画鋲モデルを作成しましたが、今回はこれより凝ったやつを作りたいと思います。

前回についてはこちら

labs.spookies.co.jp

今回もMetasequoia LEで作成しています。

今回はタイヤを作りましょう!

f:id:spookies_nytk:20171109121254p:plain

まず断面を作ります。 前回書いた回転体を使えばタイヤっぽくなりそうです。

でも、下半分がないように見えますね。

下半分はミラーリングで作っちゃいます。 ミラーリングとは画像を反転させてくっつけるやつですね。

f:id:spookies_nytk:20171109122112p:plain

Y軸に対して対称になるように設定します。 ついでに回転体も使っています。

f:id:spookies_nytk:20171109122323p:plain

なんだかタイヤっぽく見えませんか

f:id:spookies_nytk:20171115184148p:plain

今回はフリーズという機能を使って回転体の情報から頂点を作成します

f:id:spookies_nytk:20171115184235p:plain

ミラーも回転体も使ったので両方チェックを入れますね。(使ってない時はそもそもチェックできないです)

f:id:spookies_nytk:20171115184112p:plain

このように頂点を作成します。

f:id:spookies_nytk:20171109122639p:plain

さらに黒っぽい材質を設定して

f:id:spookies_nytk:20171109122717p:plain

タイヤっぽくします。 このままではゴムだけで味気ないですね。

f:id:spookies_nytk:20171109122852p:plain

真ん中に置く板っぽいやつを作りましょう。

枠の部分は回転体で、十字部分はミラーリングで簡単に作れます。

f:id:spookies_nytk:20171109123112p:plain

板をはっつけたらだいぶタイヤっぽくなりました。 次回以降もパーツを作って最終的に車のモデルを作ろうと思います。

Are you Spookies?? 機械学習で顔の画像認識をしよう

最近、アニメを見まくっているIoT開発部の西村です。
こんにちは。
感動シーンでナミダしている僕の横で、犬がうるせーなって顔してるのがたまらないです。
どうぞよろしくお願い致します。

課題・モチベーション

ということで 人の顔を機械学習で覚えさせ、メンバーが来たかもよ君にバージョンアップだ!

Spookiesメンバーの顔画像認識パターンモデルを作ってみる

顔画像の収集

毎日顔を合わせて一緒に仕事してますが、いざメンバーの顔写真が必要となっても、あまり持っていないもんです。 携帯で何枚か撮ったかもしれませんが、そんなに数は無いですよね。

合宿等の写真を拾い集める

会社の共有フォルダーに、合宿の写真が入ってました。

  • 沖縄合宿
  • 和歌山合宿
  • 淡路島合宿

こちらを使いましょう。

DLしてフォルダを開くと、こんな写真がいっぱいあります。

f:id:spookies-nishimura:20171014200226p:plain

顔画像のみ抽出

さて、ここから顔画像を取得しましょう。
一つのフォルダの中に全ての画像をぶち込んで、OpenCVを使って画像を切り出しましょう。

OpenCVには、画像から顔を抽出するCascade Classifier=分類器と呼ばれるものが公開されてるので、それを使って顔だけを切り出します。

さらにデータが少ないので、反転・コントラスト調整を行い、画像の水増しを行います。

寺師君の結果
f:id:spookies-nishimura:20171014200300p:plain

ではこれらのデータを使って、モデルを作ります。

モデルの作成

機械学習ライブラリといえば、TensorFlow
但し、素人にはなかなか扱いづらい為、日本語ドキュメントが完備されているラッパーライブラリの Keras を使いました。

from keras.models import Sequential
from keras.layers import Dense, Activation

# 画像データ読込(txtファイルは画像パスとラベルを設定した一覧)
(X_train, y_train)= train_input.read_data('./face_detect/train.txt') # X_train: 学習データ, y_train: 学習ラベル
(X_test, y_test)= train_input.read_data('./face_detect/test.txt') # X_test: テストデータ, y_test: テストラベル

### モデル定義 ###
# Sequentialはただ層を積み上げるだけの単純なモデル
model = Sequential()

model.add(Conv2D(32, (3, 3), padding='same', input_shape=X_train.shape[1:])) # 2次元畳み込み層
model.add(Activation('relu'))   # 活性化関数(レイヤをつなぐもの)
model.add(Conv2D(32, (3, 3)))
model.add(BatchNormalization()) # 誤差・分類性能向上の層
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))   # レイヤ縮小を行い、扱いやすくする層
model.add(Dropout(0.25))    # 過学習の防止

model.add(Flatten())    # 入力を平滑化
model.add(Dense(512)) # 全結合(クラス分類)
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(nb_classes)) 
model.add(Activation('softmax')) # 活性化関数

# compile
model.compile(loss='categorical_crossentropy',  # 損失関数
              optimizer='adam', # 最適化関数
              metrics=['accuracy']) # 評価指標のリスト

### 学習させる ###
model.fit(X_train, Y_train,
          batch_size=batch_size,
          nb_epoch=nb_epoch,
          validation_data=(X_test, Y_test),
          shuffle=True,
          callbacks=[csv_logger, cp_cb, stopping])

...

これでモデル作成です。(MacBookPro で 2時間くらいかかりました)

実験

では、早速できたモデルを使って画像認識してみました。

f:id:spookies-nishimura:20171014203702p:plain:w300 (パジャマですみません)

oops!!!! takanoになってる!

京都オフィスでも何名か試してもらいましたが、だいたい takano になってしまいました orz

原因

今回、精度が出なかった原因としては

  • 元画像の質が悪すぎる
  • 学習データ量が圧倒的に少ない

ですかね。

まとめ

残念ながら現在は takano が来たかもよ君になってしまいましたが、新しい事をするのは凄く楽しいですね。
引き続き精度を向上を図り、ラズパイにも組み込みたいと考えております。 f:id:spookies-nishimura:20171014200226p:plain

イエェェェイ!

f:id:spookies-nishimura:20171014193126j:plain:w100

labs.spookies.co.jp

プログラミングをやってみよう

プログラミングに興味はあるけど何やったらいいの?

こんにちは、ももです。

スプーキーズで働きはじめて1ヶ月。

ちょっとプログラミングの話もしてみたいなと思っておりました。

ただ、スーパープログラマではないひよっこですので技術的なことはまだまだです。

そこで今回は、プログラミング初心者である私がどんなサービスを利用してきたのかご紹介したいと思います。

私は、基本的にはWEBで提供されているものを利用していました。

プログラミングをやってみたいけど...

何したらいいかわからない

どんなことするの?

状態の方はまずは無料のWEBプログラミング学習サービスを利用してみましょう。

有名なものは

・ドットインストール

https://dotinstall.com/

・Progate

prog-8.com

・CODEPREP

codeprep.jp

でしょうか

私はこの3つをまんべんなく利用しています。

こちらは基本無料で、興味が湧いてきたら、月額の有料会員に切り替えが可能になります。

私は、ドットインストールとCODEPREPは無料会員ですが、Progateは有料会員です。

3つもあるけどどれがいいの?と思われるかもしれませんが

オススメはProgateとCODEPREPです。

ProgateかCODEPREPから始めると、プログラミングに必要な環境が整った状態ですので

簡単にプログラミングを体験することができます。初心者にはわかりやすいと思います。

私はとてもわかりやすかったです。

無料の部分でまずはプログラミングってどんな感じか試してみましょう。

触ってみると自分がプログラミングが好きか嫌いかもわかるのではないかと思います。

次に、ドットインストールですが、こちらは一回3分の動画をみる形の学習スタイルになります。

私がドットインストールに大変お世話になったのは、開発環境の構築です。

ドットインストールのいいところって隣でプログラミングを教えてくれてる感じがあるんですよね。

実際に画面上のどの部分を選択するのだとか、動作がとてもわかりやすいです。

私は、いろんなものを試したかったのでまんべんなくスタイルですが

一つに絞ってやるのも、もちろん人それぞれだと思います。

プログラミングに慣れてくるときっとWEBサービスだけでは、物足りなくなってくると思います。

そんな時がくれば、興味のある言語を選んで参考書を買ってみましょう!

もっと楽しい世界が広がると思いますよ!!私もそうでした

ちなみにスプーキーズでは、会社の参考書の貸し出しも行っていて自由に借りて、勉強できる制度も整っています。

プログラミングに興味があって勉強する意欲のある方!ぜひ、一緒にスプーキーズで働いてみませんか?

スプーキーズでは、一緒に働く仲間を募集しています!

f:id:spookies_momo:20170928191623j:plain

JavaScriptを高速化する5つの手法

こんにちは、モリタです。

JSを高速化 する

f:id:moritanian:20170926151527p:plain:w160

nativeに比べて遅いと言われるjsですがパフォーマンスチューニングによりずいぶん改善しているようです。しかしながらWebGLなどまだまだ高速化が必要な分野も数多くあります。そこで、今回はjavascriptを高速化する手法を簡単に見ていきたいと思います。

Typed Array

動的な配列であるjsの通常の配列に対し、固定長の配列であるTypedArrayが用意されています。低機能ですが、各要素に高速でアクセスする事ができます。以下のようにまずサイズを決めてバッファを確保してからTypedArrayを生成します。 canvasの getImageData () で取得できる画像データもTypedArrayのようですね。

var buffer = new ArrayBuffer(8); // 8byteのサイズのバッファ確保
var arr   = new Int32Array(buffer); // 32bit(4byte)のint配列
console.log(arr); // [0, 0]

WebAssembly

動的型付け言語であるJsは実行時に型チェックや型変換が行われ、それがネイティブに比べて遅くなる原因のひとつになっていました。そこでMozillaからasm.jsという手法が提案されました。asm.jsでは全ての変数が静的な型付けを行います。TypedArrayの考え方をさらに推し進めたものと言えるでしょう。

このasm.jsに対して各ブラウザベンダーが協力して策定しているバイナリフォーマットの規格がwebAssemblyです。 webAssemblyを利用するにはc, c++ コードをEmscriptenツールによって.wasmバイナリに変換するのが一般的なようです。  各ブラウザの実装状況は以下のようにデスクトップではほぼすべてのブラウザ最新で実装されています。 f:id:moritanian:20170926114309p:plain

また、unityのwebGLビルドでもオプション設定でwebAssemblyを使用できるようです。

WebWorker

jsは本来シングルスレッドで動作しますが、webWorkerを利用することでマルチスレッド動作を実現できます。 以下のように new Worker("ファイル名") で実行することができます。 また、postMessage() , onmessage() でスレッド間でデータをやり取りできます。

main.js

var myWorker = new Worker("worker.js"); // worker.js  を別スレッドで実行
 myWorker.postMessage([first.value,second.value]); // Sending message as an array to the worker
myWorker.onmessage = function(e) {
        result.textContent = e.data;
        console.log('Message received from worker');
    };

worker.js

onmessage = function(e) {
  console.log('Message received from main script');
  var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
  console.log('Posting message back to main script');
  postMessage(workerResult);
}

参考

github.com

gpgpu

gpgpuとは本来画像処理に使われるgpuの計算資源を画像処理以外の演算に使うことです。gpuは行列計算など計算密度が大き(条件分岐などが少ない)く、並列度が大きい演算に関してCPUに比べて性能を発揮します。最近は機械学習が利用例としてホットですね。 gpgpuを利用するために以下のライブラリがあります。 gpu.rocks

github.com

gpu.jsでは以下のように記述できます。

const gpu = new GPU();
const multiplyMatrix = gpu.createKernel(function(a, b) {
  var sum = 0;
  for (var i = 0; i < 512; i++) {
    sum += a[this.thread.y][i] * b[i][this.thread.x];
  }
  return sum;
}).setOutput([512, 512]);

const c = multiplyMatrix(a, b);

Simd

こちらも並列化により高速化を実現する試みの一種で命令セットレベルの並列化を実現します。 以下ではベクトル演算を並列化しています。

var a = SIMD.Float32x4(1, 2, 3, 4);
var b = SIMD.Float32x4(5, 6, 7, 8);
var c = SIMD.Float32x4.add(a,b); // Float32x4[6,8,10,12]

残念ながらEcmascriptでまだドラフト段階のためリリース版ブラウザの実装はまだのようです。

番外編

javasciptで演算子オーバーロードしたい

高速化とは全く関係ありませんがみなさんも一度はjsでも演算子オーバーロードしたいと思ったことがあるはずです。いや、そんなことはないですね。 少し気になったので調べてみたのですが結論としては、 【Javascript】演算子をオーバーロードしたい話 - Qiita にある通り普通のやり方では実現できずコードを構文解析して演算子オーバーロードしている箇所を書き換える必要があるようです。 そこで実際に実装してライブラリ化してみました!

GitHub - moritanian/minamike.js: このライブラリに過度な期待はしないでください

f:id:moritanian:20170926124329p:plain

このライブラリでCのstd::cout 風に記述するとこのようになります

const cout = "std::cout";
String.prototype.__operators__ = {
    "<<" : function(s1, s2){
        console.log(s2);
    }
  };
 
 
 cout << "Hello World!";

まあ、全く需要なさそうですが。

それではよきjsライフを!

Web Audio APIを用いた自動作曲

こんにちは、ロックです!

今回は先々週ぐらいに社内で行った勉強会の内容となります。

ブログを書く手番が回ってきたので、書いていきたいと思います。

概要

  • 日頃からの思いとして、音楽に携わるプログラミングも興味があった
  • 最近AIがブーム

ということで、プログラミングを通じて作曲できないかな?

さらにAIブームに乗って、作曲の自動化とか行けそうではないだろうか。

何を使って実現する?

普段の趣味ではC言語なので、C言語ベースでやろうと思いましたが、

Webで簡単に音を出せるらしいので、そちらで実現していきます。

Web Audio API

HTML5 で音関連も強化されているようです。

ノード同士を繋げていく仕組み

仕組み解説(音量操作の例を通して)

1. 音を出す

音の発生源(node)出力(node) に繋げた(connect)状態で再生(start)を行うと音が聞こえてくる。

f:id:ishiyamacocoa:20170919164857p:plain

2. 音量を調整してみる

音量(node)を間に挟むことで音量を調節できる。

f:id:ishiyamacocoa:20170919164901p:plain

3. 複数音を鳴らしたい!

新しい音の発生源2(node)音量(node)に繋げればok

f:id:ishiyamacocoa:20170919164905p:plain

4. 音の発生源1だけ少し音量を上げたいなあ

音の発生源ごとに音量(node)を作り、全体音量(node)と繋げるようにするとok

マスターボリュームと個別のボリューム!!

f:id:ishiyamacocoa:20170919164909p:plain

以上のようにノードを繋げていく。

音の発生源から出力の間にいろいろ挟むことで楽しくなる。

音程を求める

440Hzが世界標準でラ(A)の音

※例えばドの音は262Hz

周波数を求める式として MIDI tuning standard というもの存在する

2note_number - 69/12・440Hz

※note_number = MIDI のノート番号(0 ~ 127)

ノート番号で言うと、69が440Hzのラ(A)の音である

参考URL :MIDIノート番号と音名、周波数の対応表

無限に鳴らす

音も出せるようになり、音程も操れるようになったので、無限に鳴らせれば任務完了です。

今回は javascript を使っているので、 setInterval() でok

ちょっと音楽っぽくする

和音というものがあります。

いわゆる ドミソ

ピアノで言う左手(コード、ベース)

音楽といえばメロディもありますよね

ランランララランランラン♪

ピアノで言う右手(メロディ、コード)

和音

  • メジャーコード
  • マイナーコード

を選べるようにしておきました。

メジャーコードを選んだら全てメジャーコードに

マイナーコードを選んだら全てマイナーコードになります。

メロディ

和音は3つの音で構成されています(4つとかもあるが)

メロディはこの和音に出てくる音の3つのうちからランダムで流れるようにしてます。

これだけで案外メロディっぽくなるものなのです。

設定項目

  • スケール(今回は全て長調)
  • 和音(メジャーかマイナーを選べる)
  • オクターブ
  • BPM(3桁まで入力可能)

見た目

autoMusic_Image.png (4.3 kB)

実際のものがこちら

autoMusic.html (4.0 kB)

Webに公開する力がなかったので生ファイル。

DLしてブラウザで開くと見れる(はず)

展望

  • コード進行を考えるともっと音楽っぽくなる
  • 対応スケールを増やす
  • パーカッションとかを入れる(楽器を増やせるようにする)

反省

  • AI関係なくなってしまった(一晩でどうにかなるものでもなかった)

先日見かけた自動作曲記事

『Scalaで自動作曲の練習』を社内勉強会で話した - Sexually Knowing

参考サイト(Web Audio API)

Web Audio API - Web API インターフェイス | MDN

HTML5 の Web Audio API で音楽してみる | CYOKODOG

https://www.html5rocks.com/ja/tutorials/webaudio/intro/