最近急に「川尻蓮さんすげえよ…」になっている経緯説明ブログ

普段のツイッターは映画の話が多いので、おそらくアイドルとかに興味のある層が殆どいないであろうTLの中で急にひと回り下ぐらいの男の子をすげえ応援しはじめるのもなんか不審みがあるなあと思い、一応これまでの経緯をざっと書いてみようかなとおもった次第です。

ちゃんと説明をした上で「やっぱり不審だな」とおもっていただければと。

誰なのか?

人生通してコンペ番組好き(ASAYAN世代だし、直近では”ソーイングビー”も”Next in Fashion”もハマっていたし、なんなら自身が出た経験もあり・・)というのがあって、GYAOでたまたま配信していた『PRODUCE 101 JAPAN』というオーディション番組も見始めたらすぐハマってしまったんですが。

これがどういう番組かというと、101人の候補者から国民投票で勝ち抜いた11人を最終的にアイドルグループとしてデビューさす、というもう見る前から理不尽さしか生まれないことが確約された、コンペ番組史上でも中々見ないレベルの残酷TVショーです。

なので、よほどコンペ番組マニアで耐性あるやつか、自分も地獄の一部になる覚悟のあるやつか、まじもんのサイコパスかしか見てはいけない番組なんですけど。

といいつつ、やっぱり単純に「人間」を見るのって面白いなという部分と、評価軸がどの辺にあるのかを見極めるゲーム性の高さで引き込まれちゃうんですよね(サイコパス側の意見)。

で、序盤で候補者101人が同じ曲をパフォーマンスする映像があったんですけど、そこで、”ただ向こうからこっちに歩いてくる”動作だけで「なんかこの人、やばいチャクラ開いてるな・・」と感じさせる人間がいたんですね。

ダンスやたら巧いを超えてなんなんですかねこの圧倒的に出来上がったカリスマ力。こんなカリスマを放った一般人が一般道あるいてたらビックリしちゃうけどな普通に。

というわけで世に出るべくして出てきた感じの川尻さん、初回から番組的にもちょっと一目置かれる存在になってたというか、「デビューを目指して頑張る」のが主旨のはずなのに川尻さんだけは既に「どのメンバーでデビューするか」まで先を見据えて番組やってた感があり、もはや『PRODUCE 101 JAPAN』というか『PRODUCE 101 KAWASHIRI』ですよ。

でもね、結局天才が一番努力しているんだなというのが垣間見えるシーンというのもあって、まあこれは川尻さんに限った話でなく他の技術力の高い練習生みんなそうだったんですけど、やっぱ人の100倍は練習しているんですよね。3日ぐらいでみんな明らかに瘦せたよなってぐらい滝汗流しながら練習してるシーンとかあって。※1

さらに川尻さんに至っては合宿所からお母さんに電話してる時にも話しながらフリの練習したり、夜食を食べてる時も空いている下半身のストレッチしていたらしいですね。

いやこれ、オーディションに参加してる練習生みんな合宿して番組とってて、その間スマホ使用禁止だから、家族に電話する決められた時だけ外部と通信していいっていう留置所スタイルなんですよね。だからみんな久しぶりに家族の声聞いてホームシックになって泣きだしたりとかしてるわけで。そんな中でもフリの練習を止めない川尻さん。そんなのもうジョンウィックとかのレベルですよ。アイドルとしての意識の高さを超してると思う。食ってる時も気を抜かないのはプロの暗殺者レベルの意識の高さ。ゾルディック家とかで育ったのかな。

しかしまあ恥ずかしながら自分が全然ストイックに頑張れないだらだらした人間なので、もうそういうのを見ると憧れの気持ちしか湧いてこない。尊敬ですよね普通に。自分より全然年下だけど、あっちはもっと凝縮された時間を生きてますからね。こっちは30越えて初めてピアス開けたりしてますけど川尻さんは中2ぐらいで4ついってるから(知らんけど)。相対性理論的には年齢いっしょと言っても過言ではないですね。

JO1の音楽性

そんなわけで川尻さんは『PRODUCE 101 JAPAN』で最後の11人まで残り、JO1というグループの一員としてプロデビュー。

その後オリコンで1位をとったりアジアの音楽祭で新人賞をとったりしているみたいなので世間的にはそこそこ知名度があるんでしょうが、私は邦楽の情報源がMステと関ジャムのどちらかのみという偏った人間だったので、今まで全くJO1を聴く機会がありませんでした(この2番組だけ綺麗に出てないJO1)。

なので最近になって初めてデビュー曲『無限大』を聴いたんですが・・・

いやめちゃ面白いやないか。

私の三大好きな音楽、ダンスミュージックとワールドミュージックとトンチキアイドルソング(少年隊の「デカメロン伝説」のような曲を指します)なんですけど、もうこの曲全部盛りですよ。テンション爆上がりしてしまいました。

まず、「So 俺が 無限大」ってリリック、ふつうだったら小学校3年生しか思い浮かばないですよ。これを大人が作るのは天才の仕事。

「無限のパワー(パワー!)起き上がれ(上がれ!)」という掛け合いもすごい。「無限のパワー」ってワードたぶん成人してから発したことない。絶対ライブでやりたいでしょこのレスポンスは。考えただけでわくわくしますね。

上腕二頭筋にキスするフリのところで「チン♪」みたいな効果音入れるセンスも可愛げありすぎです。いやーすばらしい。。

2ndシングル『Oh Eh Oh』もすごい。

まずMVが「あれっぽいな…」と思っていたら、本人たちがMVのメイキングで「ハイローみたいじゃん!」って言っちゃってましたね。言うんかい。

でも丁度ジャニーズとLDHとK-POPのいいところを取って混ぜたような曲になってて、面白いしよくできてますよね。

ジャケットぱたぱたさせる振り付け、高校生ダンス部活層をターゲットに仕掛けていってる感じあるのでMステさえ紹介してくれればもっと流行ったのでは・・

あと曲の構成もすごいですね。11人ぶん歌割らないといけないので、要素を詰め込まないといけないのは理解できるんですが、ちょっと普通には思いつかない組み立て方してますよね。かといって全然破綻してない。これは関ジャムでヒャダインさんあたりが喜んで語ってくれそうなポテンシャルあると思いますけどね。(結局その2番組)

そして川尻蓮さん流石カリスマ、演技をさせてもすごい。普通に目つきが怖すぎる。

急に普通にかっこいい曲。

これは私みたいにアイドルにトンチキを求めてる層以外にもちゃんと響く感。

途中でMJの Mama Say Mama Sa Mama Coosaみたいなフレーズ入るのもいいし、club remix作ったら絶対良いやつですね。

で、ここで私またびっくりしたんですけど、この「ボーントゥビーッワーーーーーーーーーー」って歌ってる人、一体誰?と。こんな声出る人いたっけと。どうやら河野純喜という人らしいと。

いや最初からいたんですけどね。でも『PRODUCE 101』の時は「カラオケ上手い兄ちゃん」ぐらいの印象だったので(声質は変わってないので、素材の良さは元々あったんでしょうが)、1、2年でこれだけの歌手になってるの凄いですよ。レコーディングマジックなのかと思いきやFIRST TAKEにも出ててやっぱり普通にうまい。歌ってやっぱり訓練なんだなーとなんか感動しますね。

あとなんか、韓国歌唱メソッドがすごいんですかね。みんなハイトーン出るようになるのかな。いいなあ、教わりたいよ同じ先生に。普通にカラオケで出ないのでJO1の歌の音域。。

川尻さん思っていたキャラと違かった問題

十分曲とパフォーマンスの力でやっていけそうなJO1、何故かバラエティ番組にめっちゃ出ているらしい(Mステと関ジャムには出ていないのに……)。

Gyaoでも『JO1 HOUSE』という冠番組を持っており、大喜利からバンジージャンプまでやっていて「この人たちは歌と踊りだけ頑張ればいいんじゃないかなあ」と思いつつ人となりを知るのが面白くてなんだかんだ見てしまっているんですが。

そういうのをちらほら見ていて発覚したんですけど、川尻蓮さん思っていたキャラと違うと。

オーディション番組に出ていた時は「孤高のカリスマ」「セーラームーンに出てくる美形の敵役」「踊ることだけを仕込まれたアサシン」みたいなイメージだったんですけど、実際のしゃべりはさかなクンぐらい優しくてびっくりしました。俺のカリスマのイメージが崩れてゆく…。いや優しいのはいいことです。※2

セールストークもこなせる川尻蓮さん。

いや、いいよ!あんなダンス踊れる人がそんなことまでできなくていいよ!この人営業力でまでGo To The Topいこうとしてますね。すごいなあ。昔ユースケ・サンタマリアが「ダンスやってるやつはなんでもできる」って言ってて、わたしも薄々「そうなのではないか」と思ってたけど、やっぱそうなんですね。

あと、推しからYSLの化粧品すすめられる世界があるんだなあというのも新鮮でした。ただ、「このYSLのナイトセラムを使うと、毛穴がなくなって、アップの撮影も自信が出ます!」とか言われても、こっちは毛穴を気にする人生もアップで撮影される人生も送ってないので、すまんな。。という気持ち。

しかし、番組とか見てると他のメンバーもみんな個性的で面白いですね。なんか変な人が多いですねJO1。これからも頑張ってほしいです。あとMステと関ジャムに出てほしいです。

そんなJO1を排出した『PRODUCE 101 JAPAN』は今月末まではGYAOで配信されているっぽいので、まあいないと思いますが、これを読んで気になった!という方は、一応見ることはできます。理論上はできますが、結構大変なので、あんまりおすすめはしません。(布教に後ろ向きなブログ)

※1:で、確かに努力は大事なんだけど、同じくらい持前のセンスと顔面も大事だよなという容赦ない現実を突きつけてくる川西拓実というすげえやつが登場するのはまた別の話

※2:でも川尻さんには肝試し的な脅かしとバラエティーでおなじみの手をビリビリするやつが全く効かないことが発覚したのでやっぱりゾルディック家に育てられたのかもしれない

デカフェレポ:ブルーボトルコーヒー

コフィノワの豆が爆速で無くなってしまったため、とりあえず通勤途中にあったブルーボトルコーヒーの店舗で豆を買ってみた。

やはしパッケージロゴがおしゃれなのでテンションがあがる。

値段設定はやや高めだけど、今回は送料がかかっていないから許せる。

グアテマラとインドネシアがブレンドされてて、クリーミーな味わい、とのことだったが、普通に飲みやすかったですね。

というか、「普通に飲みやすかったですね」以上の感想がもう出てこないですね。

デカフェレポとかいって色々飲んではみてるけど、「うまい」「ちょっとうまい」「ちょっとうまくない」以上に細かい味の解像度がないからこっちには結局。もうなんかはっきり言ってよく分からなくなってきたよ所詮素人だからね。

とかいうと終わっちゃうから関係ない話するけど、コーヒーはやっぱりクッキーとかお菓子と一緒に食べるといい感じになれるから、クッキーも自作したい!とおもって、ぶっこわれたまま10年ぐらい放置してたオーブンをこの前新調した。

で、クッキーとか材料混ぜて焼くだけだし楽勝だろ、とおもって実際やったらべちょべちょとぼそぼそが共存するきもーい物体が出来上がって落胆して、落胆ついでに「おれはなにをやってもまともにできない…」って自己嫌悪が爆発して生きていくのがつらくなったんだけど、それでも何回か挑戦してたらまともになってきたし(いまだにクオリティは安定しないが)、自分で作ったお菓子が美味くできると「生きてける気がする度」が向上するなってことが分かった。

タイムアタック要素の強い「炒める」という工程とか手先の器用さが関係してくる「包丁で切る」とかの工程が苦手だからいわゆる「料理」は苦手なんだけど、それに比べるとお菓子作りの工程は割とねるねるねるねの高尚版みたいな感じだから楽しい。

これからもコーヒーをおいしく飲むためにお菓子いろいろ作ってみたい。

デカフェレポ:コフィノワ

今回はコフィノワの「デカフェ メキシコ マウンテンウォータープロセス」。

通販だとやはし送料がネックになる。普通の宅急便で送ってくるものだと850円とかしたりして、もはや本体価格より高いまである。

ので今のところオンラインショップでは大体送料が安いショップを選んでいる。

今回頼んだコフィノワも500gまでクリックポストで全国一律200円で送ってくれるのでよかった。是非すべてのオンラインショップでクリックポストとかネコポスとかでの配送を採用してほしい。(梱包サイズの問題とか色々あるのかもだが。。)

しかもなんか頼んでから届くまでめちゃ早くてびっくりした。焙煎日とかとの兼ね合いが偶然よかったのかもしれないが助かる。。

常に写真撮るの下手

「酸味が少なくバランスのとれたカフェインレスコーヒー」と書いてあるので、飲みやすい感じなのかな、と予想はしていたが、実際飲んでみると、これはもう、水。(語弊がある言い方)

これはもう水、とかいうと、ネット構文みたいになってしまうけど、ほんと心のままの感想。水っていうか、白湯。白湯ですね。(語弊がある言い方)

というかコーヒーの感想で「雑味がない」っていうのが今までよく分かってなかったんだけど、これのことなのかもしれない。雑味がないので何杯でも飲める(雑味ゼロ理論)

そういうわけであっという間になくなってしまったので、今全部記憶でこれを書いているけど、なんか本当にそんなコーヒー存在したか?ぐらいの気持ちになってる。白湯を超えて霞に近い。(語弊がある言い方)

記憶を確かめるためにもこれはまた試してみたい。

processingでテクニカラー時代映画風の画像フィルターを作る

U-Nextに加入したので、MGMのテクニカラーのミュージカル映画とかを改めて観ていたらどれも夢みたいな色彩で素晴らしく、一体テクニカラーってどういう理屈で色を付けているのかな?と疑問におもった。

上の動画によると、映像を撮るときにRGB要素別に分解したネガを反転させ、それぞれの補色で染め、それをまた合体させる。。という原理のもよう。

要は元の絵からRGB分解したものを再度合体させているだけなので、デジタルでやると同じ手法をとってもオリジナルの色味がそのまま再現されてしまうだけ。

たぶん、アナログだとフィルム染めるときに色むらがあったり、合成するときのずれだったり、染料のシアンやマゼンダの色味とかが作用して独特のかんじになっているんだとおもう。

そりあえず彩度の高さとコントラストの強さ、あと滲んだムラのある感じを真似したらそれっぽくなるのかなとおもったので、画像の色情報を取って、ブレンドモードをハードライトにしてそのまま点描してみた。

PImage img;

void setup() {
  size(500, 1000); //画像のサイズ
  img = loadImage("img/input.jpg"); //画像読み込み
}

void draw() {
    noLoop();
    //ピクセル読み込み用
    loadPixels();
    img.loadPixels();
    //点描設定
    noStroke();
    blendMode(HARD_LIGHT); 
    float alpha = 40;
    float pointSize = 4;
    //画像サイズ分ループ
    for ( int y = 0; y < height; y++ ) {
        for ( int x = 0; x < width; x++ ) {
       //ピクセルごとの色情報の取得
            int loc = x + y * width;           
            float r = red( img.pixels[loc] );
            float g = green( img.pixels[loc] );
            float b = blue( img.pixels[loc] );
         //取得した色で円を描画
            fill( r, g, b, alpha );
            ellipse( x, y, pointSize, pointSize );
         }
     }    
 }
左がオリジナル、右が加工後

結構これだけでもそれっぽい感じの色味になった。

さらに、描画する円のサイズを細かくしたり、描画位置(ellipseの(x,y)部分)にランダムな値を加えたりしてフィルムグレインっぽさを追加すると昔っぽさがでる。

円描画にランダム要素を追加

ついでに、シアン、マゼンダ、イエローをブレンドモード=MULTIPYEで描画したあと、ハードライトでハイライトを追加するという加工も試してみた。

PImage img;

void setup() {
    size(500, 1000);
    img = loadImage("img/input.jpg");
}

void draw() {
    noLoop();
    loadPixels(); 
    img.loadPixels();
    noStroke();
    float alpha = 50;
    float pointSize = 8;
    
    for ( int y = 0; y < height; y++ ) {
        for ( int x = 0; x < width; x++ ) {
            int loc = x + y * width;
            float r = red( img.pixels[loc] );
            float g = green( img.pixels[loc] );
            float b = blue( img.pixels[loc] );
            float n = random(50); //ランダム値を作成
            //MULTIPLYモードでシアン、イエロー、マゼンダを描画
            //ランダム値を足して色むらを表現
            //描画位置をずらして版ずれ?っぽさを出す
            blendMode( MULTIPLY ); 
            fill( r+n, 225, 225, alpha );
            ellipse( x, y, pointSize, pointSize );
            fill( 225, g+n, 225, alpha );
            ellipse( x+2, y, pointSize, pointSize );
            fill( 225, 225, b+n, alpha );
            ellipse( x, y+1, pointSize, pointSize );            
            //HARD LIGHTモードでグレースケールを付加してハイライトを付ける
            blendMode( HARD_LIGHT ); 
            fill( ( r+g+b )/3+100, 15 ); //白っぽくするため100足してる
            ellipse( x, y, pointSize, pointSize );          
         }
     }
 }
 
乗算+ハードライト

これはこれで彩度の低さがレトロっぽくてロマンチックな気がするし、ぼやけ方が写ルンですっぽくもありエモ。

因みに使った写真はおととしタイに行ったときに撮ったもの。また行きたいなあ。。

デカフェレポ:innocent coffee

今回はinnocent coffeのデカフェ 浅煎りSAKURA

購入した時に、おススメドリップ方法とか会社の説明とかが書いてある小さい冊子がいろいろ付いてきたので嬉しかった。小さい冊子好き(ZINE的なものを感じる)。

innocent coffeは軽井沢焙煎所の豆を販売しているCafe‘ Sucre‘‘が母体にあり、その中のデカフェ専門コーナーとして存在しているらしい。ので、デカフェだけで種類が色々ある!ひとつのサイトの中でデカフェだけで深煎り・浅煎り、豆の種類がこんなに選べるのはまじ楽しい感謝。

今回は苦さ控え目で一番クセのないっぽいやつをチョイスしてみた。

浅煎りSAKURA

前に浅煎り飲んだ時も思ったけどやっぱり浅煎りは豆茶的な豆感がある。すごいマイルドなお茶って感じ。

で、これも前に浅煎り飲んだ時も思ったけど豆を買ってから1週間ぐらいすると明らかに味が変わってくる。

今回のは途中から若干酸味が増した気がする(酸化したということなのか?)。でもこれもまた前に浅煎り飲んだ時も思ったけど私は新鮮なやつよりちょっと置いてたやつの方が美味く感じる。

そういえば紅茶のティーバッグも賞味期限ギリギリのやつのほうが美味く感じたので、なんか肉も腐りかけが美味いっていうしそういうことなのかなと思うけど、もしかしたら私の舌のほうが腐っているだけなのかもしれない。

デカフェレポ:ミカドコーヒー

最初に試したchouette torréfacteur laboratoireの浅煎り豆がそろそろ切れる頃だったが、なんと低音焙煎の特性?で1週間ぐらいのうちにどんどん味が変化していって面白かった。

最初はシンプルに酸味がきりっとしてた印象だったけど、途中から香りが複雑になってきて、なんかこうワインみたいな?芳醇さが段々出てきた。。で、コーヒー界にも「エイジング」という観念があるらしいことを知る。ほえーー。やば。

今回は、渋谷に出たついでにデカフェ豆をゲットしようと目論んだが、これが意外と苦戦。渋谷なんてコーヒー豆売ってる店沢山あるだろと高を括っていて、実際その通りなんだが、デカフェの豆に限定して探すとなると一気に難易度が上がる。

そもそも置いてなかったり、取り扱い自体はあってもその日店頭には在庫がなかったりして、4軒ぐらい回ってへとへとに。

最終的に、もうこれでなかったら諦めて帰ろうと思って入った東急本店B1食品フロアでやっと発見。ミカドコーヒーの「カフェインレスコロンビア」

わかりやすいパッケージ

https://mikado-coffee.com/caffeinless/

ミカドコーヒーは食品売り場の片隅に急に出現する買い物に疲れたひとのオアシス的カフェエリアになっていて、ソフトクリームも売っててちっちゃい子がお母さんに買ってもらってた。えがったな~。

深煎りで苦み強めとの表示で、あんまり苦いの得意じゃないのでどうかなーとおもったけど、飲んでみたらそんなに嫌みのある苦みじゃなかったので全然いける。焦げた感じの苦みじゃなくて香ばしさのある苦み。

牛乳多めにしてカフェラテにしてもいい感じだった。

苦いの苦手だからといってミルクと砂糖を多めに入れてまでコーヒーを飲むアンビバレンツ。しかもカフェインのためでもない。なぜそうまでしてコーヒーを飲まねばならないのか。旅は続く。。

デカフェレポ:VERVE COFFEE

二回目にして番外編というか、今回は通販お取り寄せではなく実店舗に飲みに行ってみたレポ。

六本木、新宿、鎌倉に店舗があるVERVE COFFEEさん。

中は空間が広くて、大きな窓から景色がよく見えるので天気のいい日に行くとるんるんになれる。地元の人にも憩いの場所っぽくてレジには常に行列が。

おしゃれな店特有の、なんかあんまり長く座るのに適してなさそうな椅子と、椅子に対してやけに低めな机とかもあったが、初心者向けの席もちゃんとあるので安心。

「VANCOUVER DECAF」というデカフェコーヒーがあったので、さっそく注文。

注文したあと出来上がりの品は名前で呼んでくれる制度だったので、「〇〇さーーん!」と大声で本名を呼ばれるのがちょっと恥ずかしい。今度は偽名で行こう。

あと、コーヒーにこだわってる店特有の「基本みんなブラックで飲むよね?」コードがあるので、ミルクとシュガーを希望する場合は店員さんに言わないといけない。(感染症対策で表にミルクとシュガーを出していないだけかもしれないが。。)

で注文した品がこちら。

VANCOUVER DECAF

まずコーヒーカップじゃない。限りなく日本茶飲むやつ。前LATTE GRAPHICでもホットのカフェラテがお冷入れるコップみたいなやつに入れられてきてびっくりしたけど、おしゃれな店的にはカップの持つとこがダサいってことなの?

味はわたしが下手に説明するより雄弁かなとおもうので下記をご覧ください。

説明の紙

すごく飲みやすくて、確かに香りにチョコレートっぽさも感じた。

夏になったらアイスでも飲んでみたい。

デカフェレポ:chouette torréfacteur laboratoire

飲まず吸わずな生活をしているもので、嗜む品といえばコーヒーぐらいなんだから、ちょっと凝ってみてもいいのかな思いハンドドリップ道具を一式揃えてみたはいいものの、じわじわとカフェインアレルギーっぽい症状が出るようになって、ついにはコーヒーを飲んだあと調子が悪くなるようになってしまった。

なんか最近は胃が弱って激辛的なものも我慢して食べないようにしてるし、これでコーヒーまで飲めないとなるとこの世の楽しみがほぼすべてなくなってしまう。

ならばカフェインレスの豆を買えばいいかと近所の店で探してみるも、色んな豆の種類を置いてる店でも大体デカフェ豆は1種類しかなくて、飲み比べる楽しさみたいなのが全くない。

いよいよ俗世の楽しみを断ち切って悟りを開くしかないかーとなっていたが、どうやら日本にはカ〇ディ以外にもコーヒー豆を買える場所がいっぱいあるということに気付きはじめる。しかもお店で自家焙煎している店も結構あるらしい。ドトールとかスタバがソニーやエイベックスだとすると、そこに対するインディレーベルって感じだ。かっこいい。

通販で買える店が全国各地にあるのだから、色んなお店のデカフェコーヒー豆を飲み比べて楽しんでいけるんじゃないか。

というわけで、焙煎所を紹介してくれている「Only Roaster」というサイトから、初めてなので試しやすい100gから売っている所を探し、今回はchouette torréfacteur laboratoireの「COLOMBIA AGPROSEM Natural Decaf 100g Light roast」をオーダーしてみた。

密封状態で届いた豆。袋にチャックが付いているので、開封した後もそのまま保管できて便利。

開けてみると、豆の色が薄めなのと、苦みのある匂いがあんまりしないことに驚く。これが浅煎りというものなのか。よく考えてみると浅煎りって飲んだことがない。

豆もカラッとしていて硬めで、ミルで砕くときにかなりゴリゴリいく感じだった。

淹れている時からかなり酸味が際立ってたが、飲んでみると柑橘類みたいな酸味が。ある程度酸味があるコーヒーは飲んだことあったけど、こんな柑橘っぽい風味に感じたのは初めてかもしれない。舌に残るような苦さは全くなくてかなりすっきり。ブラックでも爽やかだけど、砂糖とミルクを入れるとコーヒーというよりもはや紅茶か?というぐらいのライトさを感じる。

初回にして中々驚きがある経験だった。コーヒー、幅が広い。。

これからも買ったらここに健忘録的に感想を書いていけたらと思う。まあ大して違いが分かる大人ではないから実のあるレビューは書けないけれども、細々続けていければ。

メロディー自動生成 in SuperCollider

Ableton and Max Community Japanが今月配信していた、「作曲 vs 生成音楽」をテーマにした番組が面白かった。(配信が2021/1/30までだったので今はもう見れない)

AbelteonとMAXを使ったアルゴリズム作曲の基礎を実践しつつ、自動生成音楽の歴史とか、作るときの考え方についての話もたっぷり聞けて親切な内容だった。

中でも、「どう禁則を作るか」というところに創作性が発生するというのは何か作るときのとっかかりとして心に留めておきたい。

その中でやっていた、MAXでマルコフ連鎖の手法を使ってメロディーを自動生成するというのが面白そうだったので、SuperColliderでも似たようなこと試せないのかな?と調べてみたところ、SuperColliderのチュートリアルに、Strategies for Algorithmic Compositionのページを発見。

マルコフ連鎖を使って3つのノートを鳴らす参考コードがあったので、ここから発展させて、任意のスケール内の音を鳴らすコードを作ってみることにした。

コード全体

//トリガー
(
    var state, key, scale, bpm, matrix;
    state = 7.rand;
    key = "F5".notemidi;
    scale = Scale.spanish;
    bpm = 90;
    
    matrix = [
    [ 0, 3, 1, 1, 1, 1, 3 ],
    [ 3, 0, 3, 1, 1, 1, 1 ],
    [ 1, 3, 0, 3, 1, 1, 1 ],
    [ 1, 1, 3, 0, 3, 1, 1 ],
    [ 1, 1, 1, 3, 0, 3, 1 ],
    [ 1, 1, 1, 1, 3, 0, 3 ],
    [ 3, 1, 1, 1, 1, 3, 0 ],
    ]/10;

    {
        inf.do{
            var midi = ( state.degreeToKey( scale ) + key );
            var octave = [ 0, 12 ].wchoose( [ 0.8, 0.1 ] );
            Synth( \saw, [ \midi, midi+octave ] );
            state = Array.series(7).wchoose( matrix[state] );
            ( 60/bpm/3 ).wait; //三連符
        };
    }.fork;
)
//シンセ
(
    SynthDef( \saw, { |midi=70|
        var freq, env, sn;
        freq = midi.midicps;
        sn = Saw.ar( freq, 0.2 );
        env = EnvGen.kr( Env.perc( 0.1, 1 ), doneAction:2 );
        Out.ar( 0, sn*env );
    }).add;
)

wchooseメソッドは、リスト内からどの値を選択するかに確率をつけることができる。

[1, 2, 3, 4].wchoose([0.1, 0.2, 0.3, 0.4]);

のようにすると1〜4の中で大きい数字ほど選ばれる確率を高くすることができる。

マルコフ連鎖的な仕組みのためには「今の状態からどの状態に推移するかを確率的に決めたい」ので、推移する状態の数ぶんの確率リストのテーブル(matrix)を作成し、現在の値によってどの確率リストを採用するか決めている。

state = Array.series(7).wchoose( matrix[state] );

今の状態(state)が0の場合、0〜6の値からmatrix[0]=[ 0, 3, 1, 1, 1, 1, 3 ]/10(合計1にするために/10している)の確率によって次の値が選ばれるので、0が選ばれる確率は0、2か6が選ばれる確率が高いことになる。

レクチャーの中では既存の楽曲のMIDIデータから確率テーブルを生成する仕組みも自動でやっていたが、そこまでやるのは大変そうだったのでここでは手動で確率を書いていってる。

一応、連続した値が選ばれず、隣り合った値に推移する確率が高い、という設計にしてみたけれど、より”音楽的”にするためにはもうちょっと確率の値を考える必要がありそう。

key = "F5".notemidi;
scale = Scale.spanish;
midi = ( state.degreeToKey( scale ) + key );

上の部分で選ばれたstateの値(0〜6)をmidiノートに変換している。

degreeToKeyメソッドに度数(ただし0はじまりで数える)として値を与えると、任意のスケール内で何番目の値になるか返してくれる。マイナースケールだったら、2を与えると3(減三度は0番目から数えて3番目)を返す。

そこに基準のキーを加算してmidiノートとしてシンセに与えている。

ついでに

さっきのページの最後のほうにロジスティック写像(logistic map)を使った音生成というのも紹介されていたのでちょっと試してみる。

x_{n+1}=ax_{n}(1-x_{n})

のaのところに適当な値を入れるとカオスっぽい結果が得られる、っていうのを利用するアルゴリズムのようだ。

試しにaの値3.94のときn=500までをプロットしたもの↓

aの値3.04のとき↓

(プロットするのに使ったコード)

(
    m = Array.new();
    a = 3.04;
    p = 0.5;
    500.do{
	    p = ( a * p * (1.0-p) );
	    m = m.add( p );
    }
)
m.plot

というわけでaの値で結果が全然違う。3〜3.5あたりまでは規則的に振動していて、3.5から4に近づくとカオス度が上がっていくっぽい。

4を超すと値がinfになっちゃうので注意。

以下はlogistic mapで得た値を音階に変換してメロディーを生成するテスト。

(
var scale = Scale.romanianMinor;
var key = "C6".notemidi;
var state1 = 1.0.rand;
var state2 = 1.0.rand;
var r = 3.88;
var logisticmap, note;

//ロジスティック写像関数
logisticmap = { |previous=60| r*previous*(1.0-previous) };
			
{
    inf.do{
    //リードメロディ
    state1 = logisticmap.(state1);
    note = ( state1 * 14 ).round; 
    note = ( note.degreeToKey( scale ) + key );
    Synth(\asynth,[\midi, note]);
   //ベース
    state2 = logisticmap.(state2);
    note = ( state2 * 7 ).round; 
    note = ( note.degreeToKey( scale ) + key-24 );
    Synth(\asynth,[\midi, note]);
    0.25.wait;	
    };
}.fork;
)

鳴らしてみた

(ちなみにマルコフ連鎖の方の伴奏はニンテンドースイッチのkorgのやつで作っていて、リードにかかっているワウっぽいエフェクトが外部でかけている)

ていうか

ここまで書いてから気付いたけどSuperColliderのUGenにそもそもMarkov SynthLogisticというのがあった。

Logisticのほうは任意の周波数でロジスティックス写像を用いたノイズを信号として出力できるみたいだ。

Markov Synthのほうはinputしたシグナルを解析してマルコフ連鎖を生成してくれるっぽい?のでなんか凝ったことができそう(ただサンプル単位の値の推移を読むっぽいので音階の推移を解析するより使い方が複雑かも?)

このへんは後でまたちゃんと試してみたい。

three.jsで3Dキャラを作成:uvを貼る

シェーダーマテリアルを利用して、作成したメッシュにuvを貼って色を付ける。またその際、three.js側で設定したライティングを考慮した色にする。

ライトを設置

const light1 = new THREE.DirectionalLight( 0xffffff, 0.5 );
light1.position.set(0, 0, 10);
scene.add(light1);

メッシュに貼るためのテクスチャを読み込む

わかりやすいようにこんな感じの色分けした画像を用意。

画像を(2のべき乗)pxにしないとエラーが出るから注意。

const texLoader = new THREE.TextureLoader();
const armTex = texLoader.load( './data/tex/armTex.png' );

uvmapを作成

メッシュの座標とテクスチャ上の座標を対応(どこの色情報を参照するのか決める)させるため、マッピング用の配列を作る。uv座標は上の画像のようになっている。

前回まで作っていた筒状のメッシュに貼り付けることを考えたとき、基本的にはテクスチャの横をedge数、縦をsegment数(反対でもいいが)で割って、0~1の範囲をメッシュの座標に対応させるように考えればいいと思う。

こんな感じで貼りたい
function makeUvmap( obj ){
    const uvmap = [];
    for( let i=0; i<( obj.seg+1 ); i++ ){
        uvmap[i] = [];
        const y = i / obj.seg;
        for( let j=0; j<( obj.edge+1 ); j++ ){
              const x = j / obj.edge;
              uvmap[i][j] = [x, y];
        }
    }
    return uvmap;
}

あとは頂点座標の時と同じようにuv座標をジオメトリにsetAttributeしたいので、verticesと同じ体裁にuvmapの配列を整えたい。

注意なのは、verticesの方はedge数が8の時、頂点座標は以下のように端っこの部分で0に折り返している。

function setVertices( seg, edge, pt ){
    const vert = [];
    for( let i=0; i<seg; i++ ){
        vert[i] = [];
        for( let j=0; j<edge; j++ ){
            vert[i][j] = [];
            vert[i][j][0] = pt[i][j];
            vert[i][j][1] = pt[i][(j+1) % edge];
            vert[i][j][2] = pt[i+1][(j+1) % edge];
            vert[i][j][3] = pt[i+1][j];
        }
    }
    return new Float32Array( vert.flat(3) );
}

コードだと% edgeで剰余にしている部分。

セグメントごとに円を閉じるために最初の座標に戻ってくるようにしている。

でもuvは普通に(座標0地点に折り返さないで)端っこ(1.0)に行きたい。

makeUvmap関数でuvmap配列のedgeをひとつ増やしているのはそのため。

ジオメトリに対応させるため、setVertices関数と同じようにsetUvs関数を作成(edgeで折り返さないところだけ違う)。

function setUvs( seg, edge, pt ){
    const vert = [];
    for( let i=0; i<seg; i++ ){
        vert[i] = [];
        for( let j=0; j<edge; j++ ){
            vert[i][j] = [];
            vert[i][j][0] = pt[i][j];
            vert[i][j][1] = pt[i][j+1];
            vert[i][j][2] = pt[i+1][j+1];
            vert[i][j][3] = pt[i+1][j];
        }
    }
    return new Float32Array( vert.flat(3) );
}

makeGeometry関数は引数にuvmapを受け取るように追加し、uv情報をsetAttributeする記述を追加。

function makeGeometry( obj, pt, uv ){
    const vertices = setVertices( obj.seg, obj.edge, pt );
    const indices = setIndices( obj.seg, obj.edge );
    const uvs = setUvs( obj.seg, obj.edge, uv );  //←追加
    const geometry = new THREE.BufferGeometry();
    geometry.setAttribute('position', new THREE.BufferAttribute( vertices, 3 ));
    geometry.setAttribute('uv', new THREE.BufferAttribute( uvs, 2 ));  //←追加
    geometry.setIndex(new THREE.BufferAttribute( indices, 1 ));
    const merg = new THREE.Geometry().fromBufferGeometry( geometry );
    merg.mergeVertices();
    merg.computeVertexNormals();
    return merg;
}

armInit関数内にも、uv情報を作成する記述を追加。

function armInit(){
    //  .....  ↑省略 ..... //     
    //upper arm
    const upperArmUv = makeUvmap( upperArmObj ); //uvmapを作成
    const upperArmpt = makePipePt( upperArmObj );
    upperArmGeo = makeGeometry( upperArmObj, upperArmpt, upperArmUv ); //uvmapを追加
    const upperArmMesh = new THREE.Mesh( upperArmGeo, uvMat );

    //lower arm
    const jointArmPt = makeJointPt( upperArmObj, -1 );
    const lowerArmPt = makePipePt( lowerArmObj );
    const lowerArmPts = jointArmPt.concat( lowerArmPt );
    const jointArmUv = makeUvmap( jointArmObj ); //uvmapを作成
    lowerArmGeo = makeGeometry( jointArmObj, lowerArmPts, jointArmUv ); //uvmapを追加
    const lowerArmMesh = new THREE.Mesh( lowerArmGeo, uvMat );

    //hand
    lastValClear();
    const fingerPt = makePipePt( fingerObj );
    const fingerGeo = makeGeometry( fingerObj, fingerPt, upperArmUv ); //uvmapを追加
    //  .....  ↓省略 ..... //
}

指はupperArmとseg数、edge数が一緒なので、upperArmUvをそのままmakeGeometry関数に渡している。

シェーダーマテリアルの作成

const uniform = THREE.UniformsUtils.merge([
  //ライト情報を使う設定
    THREE.UniformsLib['lights'],{
     //シェーダー側にテクスチャを渡す
        'uTexture': { value: null },
    }
]);

const material = new THREE.ShaderMaterial({
    vertexShader: document.getElementById('vert').textContent,
    fragmentShader: document.getElementById('frag').textContent,
    uniforms: uniform,
    side:THREE.DoubleSide,
    lights: true
});

const armMat = material.clone();
armMat.uniforms.uTexture.value = armTex;

シェーダーマテリアルの基本的な設定方法は以前の記事を参照。

ライティングを正しく機能させるために、uniformにTHREE.UniformsUtils.mergeを使ってlightsを読み込んでいるのと、マテリアルの設定でlightsをtrueにするのを注意する。

armMat以外にもテクスチャ画像の違うマテリアルをいくつか用意することを考えて、基本となるマテリアルをクローンして、uniformのuTexutre変数に画像情報を個別にセットしている。

シェーダー側記述

頂点シェーダー側。

ライト情報を使うため、必要ソースをincludeしているところに注意。

<script id="vert" type="x-shader/x-vertex">
    #include <common>
    #include <lights_pars_begin>
    varying vec2 vUv;
    varying vec4 fragColor;

    void main() {
        //normalはShaderMaterialで補完されるジオメトリの法線情報
        //ワールド座標系に変換
        vec3 norm = normalMatrix * normal;
        vec3 color = vec3( 0.0, 0.0, 0.0 );

        //three.jsで設置したライトの方向を取得
        vec3 vertexToLight = normalize( directionalLights[0].direction );
        //three.jsで設置したライトの色を取得
        vec3 lightCol = vec3( directionalLights[0].color );
     //法線情報とライトの方向から反射を計算(マイナスは除去)
        //ライトの色を考慮
        color = lightCol * max( dot( vertexToLight.xyz, norm ), 0.0 );

        /*
        //ライトが複数ある場合
        for (int i = 0; i < NUM_DIR_LIGHTS; i++) {
            vec3 vertexToLight = normalize( directionalLights[i].direction );
            vec3 lightCol = vec3( directionalLights[i].color );
            color +=  lightCol * max( dot( vertexToLight.xyz, norm ), 0.0 );
        }
        */
        
        //colorをフラグメントシェーダーに渡す
        fragColor = vec4( color, 1.0 );
        //uv情報をフラグメントシェーダーに渡す
        vUv = uv;

        //positionをカメラ座標に変換
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }
</script>

フラグメントシェーダー側。

<script id="frag" type="x-shader/x-fragment">
    precision mediump float;
    varying vec2 vUv;
    varying vec4 fragColor;
    uniform sampler2D uTexture;

    void main() {
        //テクスチャ画像から色を取得
        vec3 texCol = texture2D( uTexture, vUv ).rgb;
     //vec4に変換
        vec4 color = vec4( texCol, 1.0 );
     //ライティングをかける
        gl_FragColor = fragColor * color;
    }
</script>

uniformでthreejsからテクスチャ画像を受け取り、texture2Dでuv座標での色情報を取得している。

最終的にvaryingで頂点シェーダー側から受け取ったライティングの反射色と、テクスチャ画像からの色を掛け合わせている。

参考:https://qiita.com/aa_debdeb/items/870e52499dc94a2942c3