歌詞の翻訳によって邦楽と洋楽の違いはどうなるか?

YouTube のトップページで日本と西洋の音楽の違いを話す動画が上がってきたんですよね。


www.youtube.com

自分はこういうのとても大好きです。作曲者の人そこまで考えてないと思うよってやつなんですが、ジョハリの窓にプロットされるような作者の内面の一部を解き明かしている感覚がします。また、直感的に行っているであろう作者の才能を解き明かすことで、少し自分がその作者の才能に近づいた気になります。ゲームで強い装備を入手するタイミングが意図的に設計されていたりしますが、それと同じように自分のスキルを解放したと錯覚できるんだと思います。

邦楽と洋楽の違いをはじめとして、音楽を論理的に分解していく記事はたびたび浮上しているのを目にします。

また、ボカロの音楽を論理的に分析した記事も探すといろいろとありますね。

realsound.jp

上記以外にも、 「音楽理論」ではてなブックマークを検索してみると 、数年に 1 回程度上位に上がっているようです。冒頭の動画を始めとして邦楽と洋楽に関する記事をなんとなく読み漁りながら、 YouTube でそれらの再現性を「そうだね」と確かめつつ、スキル解放の感覚に浸る遊びをしていたわけです。

そこで右の列のおすすめ動画を見ていたら、記事タイトルの疑問が浮かぶ動画が出てきたんですよね。


www.youtube.com

ホロライブに所属している英語圏向け VTuber の方がボカロ曲をカバーしたというものです。 先に挙げた音楽を頭で理解する記事をふまえながら、原曲と聞き比べてみるとどうなるでしょう?気になりますね。


www.youtube.com

まずは、音節の話。 冒頭の動画の 2:14 あたりで、日本の音楽に慣れるまでに感じた違いを話しています。

西洋の音楽は、比較的に音符の数が少ないです。理由は、言葉の違いですね。つまり、日本語の方が音節が多いです。

日本と西洋の音楽の違い PART 1:音符の数、メロディーのリズムと英語が使われる理由!Japan and Western music differences(音楽 ミスチル 米津玄師 j-pop) - YouTube

どうやら英語圏の人は、音節の違いから違和感を感じてしまうようです。 全ての英語圏の人がそうでないとしても、その後に続く例には説得力があります。

そこで注目したのは、翻訳語の動画タイトルに Rap とつけられている点です。

[MV] ロキ / Roki (English Rap Cover) - Calliope Mori

確かに。専門家ではないので意識せずに聞いていたら、楽器とサビに惑わされそうになりますが、サビ以外のボーカルははラップ成分濃厚です。 思うに、音節の違いからくる慣れの問題は、アップテンポな英語のラップとして考えると違和感無く翻訳可能なのではないでしょうか? 日本語の音節の感覚だと「言われてみればラップか」が、英語の音節の感覚だとはっきりと「いや、これラップじゃん」となるみたいな閾値のズレはありそうです。

あるいは逆に日本語側の長音を多くしてみたり。 別の曲でスローテンポだとこちらでしょうか?

音節の切り方に自信は無いですが、翻訳して同じメロディに乗せるためには、音節の数は大きくは変えようが無さそうに思います。

ロキの話に戻って、もう一つは表・裏拍の話。

英単語には先頭シラブルにアクセントがくる単語はあまり多くない。多くの単語は2つめのシラブルにアクセントがくる。1つ目のシラブルは、ごく短く弱くしか発音しない。

何故、日本人は縦乗りなのか ─── 縦乗りを克服しようシリーズその1 (oka01-qioaafwfeykuqiuj) - 言語と音楽(オカアツシ公式ブログ)

個人的には、「おちゃん おじょうちゃん おねもさのうも なじっかるだけやっんす」 の部分。日本語は 1, 2 拍目に単語の 2 音目が集中して、 3, 4 拍目が比較的弱めに感じます。おそらく半分は鏡音リンの音声で Velocity 値的な差はほとんど無いと思いますが、「おぼっちゃん」の「ん」を強調するのは自然ではないので、勝手にそう解釈しているように思えます。一方で英語側は、「guys and gals, money, fame, fortune, talent, ya can't dance around it, they'll just tie you down!」とどの拍でも比較的均等に聞こえました。 聴いているときは日本語でも裏拍に合わせて体を動かすことができるのですが、口ずさみそうとしながら同時に体を動かそうとすると 1, 2 拍目に集中した方が楽にできます。

翻訳側は並記される要素として平坦でストレートに感じますし、日本語側はまさにやっかいな感じがして好みとしては甲乙つけがたいですが、ちょっと不思議な感じがします。 日本語の要素を抜いたらラップとしての平坦な四つ打ち的な要素が前面に出てくるからでしょうか?専門家の見解を聞いてみたいところです。 表拍のノリの曲が歌詞を翻訳するだけで裏拍になるとは思えませんが、四つ打ちの曲で拍手のタイミングの統計取ると、おそらく歌詞の言語次第で変わったりするんじゃないかな?

あと、日本語の 2 番のサビで「ロキロキのロックンロックンロール」のリズムが変化するタイミング(原曲も翻訳版も 2:05 あたり)がありますが、翻訳版はそのような変化の代わりに「Break it down!!」が入ります。この違いは、作曲者と編曲者のバックグラウンドの違いが反映されたのではないでしょうか。本家版のリズムを裏のリズムで横にノッていると強いインパクトを受けますが、表の拍で縦にノッている場合は比較的自然にエネルギッシュな変化として入ってくると感じました。

まとめると

  • 翻訳して同じメロディに乗せるためには、元の音節から大きく動かすことは難しい
    • この制約を具体的に認識するだけで、複数の言語になっている音楽のすごさの解像度が上がった気がします
    • 日本語ベースで英語をラップ側に寄せるか、英語ベースで日本語をゆったりさせるか
  • メロディで表・裏がはっきりしない場合は、言語の特性でどちらに寄るかが変化するかも
    • 自分だけの N=1 で科学的にどうとかは無いんですが、 50:50 の曲に歌詞を加えると 45:55 とかになる可能性は無くはないんじゃないかと
  • 表でも裏でもノれる曲にどちらか寄りの変化を加えると、聞き手のノリ方によって印象が変わる
    • ターゲットとする言語のアクセントが表か裏かでアレンジを変えたりとかしたら面白いんですかね?なんかすでにありそうな気もする。

じゃぁ自分がそれで音楽活動をするとかそういうことはまぁ無いし、特にスキル解放演出みたいなのが出るわけでも無いんですけどね。

先輩は大きなディスプレイを使う

大学に入りたての頃、サークルの先輩は部屋に唯一あったものすごく大きなディスプレイを使っていた。しばらくいろんな人たちと働いたあとだと、あれは良かったなと思う。

 

というのも、なんといっても先輩が何をしているかがよく見える。巨大なディスプレイに投影されているおかげで、先輩がどんな操作をどんなペースで(当時の自分から見たらすごく早い)行っているのかがわかる。Gnome2から3のAlt+F2の違いや、可変の仮想デスクトップに落ち着かない日々が数年続いたのも、このおかげなのかもしれない。

 

普通のオフィスにある肩幅でほとんど隠れてしまうようなサイズでは、こんなことは発生しない。結果的に、隣の後輩がすごく非効率な操作をしていたり、まわりが何をしているのかわからないという話になったりする。プロジェクトをリードするエンジニアには、周囲のメンバーに見えるようなサイズのディスプレイがあっても良いのかもなと思ったりした。

人工知能と貧困と覇権

最近の人工知能を "人工知能" として抽象化して語られることに違和感がある。 人工知能が脅威か?みたいな議論はそれが流行るたびにあった。 少なくとも僕の生きている間ではこれが2回目で、1回目は "探索" が人工知能の正体だったとき。 将棋でボナンザが台頭して一般人を軽く超えてきたと同時に、ターミネーターが人間の脅威になるという議論はいくつかあった覚えがある。

今回も "ニューラルネットワーク" が人工知能の正体で、それをブラックボックス化された状態で議論が巻き起こる。 正体を知っているひとからすると、「人工知能が怖いか?」みたいな質問はあるいみ滑稽で、 ソートのアルゴリズムは怖いか?とか、2次方程式は怖いか?とかという質問と同様にとらえることができる。 きっといつか専門外の人たちが、将棋の AI は想像を超えた量の手を読んでいると理解するように、 想像を超えた量の分類で日本語と英語を翻訳しているとなんとなくその存在を認められるようになる。 このあたりが、きっとマルチラリティの一つずつなのではないだろうか?

普通の人間にできることはそこまで多くなくて、将棋が趣味の翻訳家の友人ぐらいなら近いうちに作れてしまうかもしれない。 そしていつのまにか周りがそんな人達に囲まれた将来は、きっとシンギュラリティと言えるだろう。 たぶん人間が一日に会ったと認識する人数もそれほど多くないので、囲まれるという状況もきっとスマホで作れる。

これを思ったのは、正月の帰省で ニッポンのジレンマ を見たから。 Twitter の反応を見ると、議論そのものに文句を言っている人がいる。 横文字ばっかりとか、具体的に語れよとか。生放送ではないのだけれど。

同時に思い出されたのが年末に マンガワン の配信で見たオメガトライブ。 この中で、梶秋一という人物が自身の従える暴走族の前で総理大臣になると宣言する。 このシーンは、主人公の吾妻晴が種の入れ替わりとかの抽象的な話で解いた後に、 梶くんが「こいつらバカだから具体的なことしかわかんねーよ」という流れから続く。 「つまり俺が総理大臣になる」というのは、バカの象徴の暴走族でも具体的にイメージできる事象なのだ。 きっと梶くんならあの番組を見た後に、バカでも心が動くまとめをしてくれる。

年末に帰省して小中学校の頃の人間と会うと、相対的な貧困とはこういうことかとよく理解できる。 彼らは衣食住に不安は無いだろうし、携帯も持っている。結婚もしていてある意味自分よりも幸せそうだ。 ただ、僕の仕事については「なんか難しいこと」らしい(わかった気にさせるのは得意だと自負していたのだが…)。 タバコと酒と昔話で共通のものを見つける会話と、大学時代の研究や仕事で違う世界を共有する会話は、貧困に対して十分に相関があるように思える。 一応断っておくと、仲が悪いとか見下しているとかそういう話ではない。「幸せそうだ」と書いたのは皮肉でもなく単純に羨ましい。

「政治的な判断は Truth に従うか、 Post Truth に従うか」みたいな質問は、たぶん日本のほとんどの人間が理解できない。 理性と感情と言っても、むず痒い気分の人のほうが大多数で、共通のものを見つける会話ではまぁ全く通じないだろう。 抽象的な言葉はそれだけで分断を引き起こす。 大学入試の人工知能で人間の国語の能力の低さがわかったというのは、そのあたりの感覚値と合っている。 識字率が高いというのは字が読めるというだけで、抽象度の高い文章を理解できるのはそこからさらに絞られる。 バカ競争が原因というのは一理あるが、単に発見されただけという仮説も十分ありうる。 どちらにしろ、人間は思ったほど知的な生き物ではないらしい。

トランプというのは、そのような現実の多数に支持されたのだと思う。ヒラリーの方が正しいとかそんな話ではない。 抽象的な議論に触れる機会がある人たちは、どちらが多数なのかを勘違いしやすい状況にあるのだと思う。 ヒラリーの話す言葉は聞き取れはするが、暴走族の前の吾妻晴のように意味不明な宇宙語を話しているように聞こえる。 一方で、トランプは具体的にメキシコとの国境に壁を立てると言って、つまりはかつての偉大なアメリカにする。わかりやすい。 「偉大なアメリカ」というのは、理解できて心が動くギリギリの抽象度で、なおかつ昔話なのである。 どちらの思想が正しいとかの対立ではなくて、理解できたかできないかの違い。 我々と近い言葉を話すトランプは同じ族の仲間であり、理解不能な宇宙人は別の種族。 どちらに投票するかと言われれば、共通のものを持つ同族に投票するだろう。

戦争に関して言うと、もうドンパチやるような戦争は、覇権を争う上では主ではなくなると思っている。 今は Google や MS, Amazon がアメリカにあるが、情報を握り合ってうまく活用した方が覇権を取ると、 いつのまにか別の国の似たような企業が圧倒的なシェアを持つようになる。 それ以外の国々はきっといつのまにか丸裸にされ、やりたい放題に送り込まれて、気づいたら時代が変わっている。 覇権の圏内に入れない国々は、生産性でまともに太刀打ちできず、ストレスによって種として自ら衰退する。 去勢薬のバイオテロなど行わなくとも、人口減少はすでに起こっている。

世界で1人ぐらいは、人道的な非難を避けつつ他の種族を滅ぼす方法を考えているだろう。 覇権国家がシンギュラリティのメリットを享受する一方、 抽象論で時間を潰している国は、社会学的な戦争で意外とあっさり淘汰されるのかもしれない。

文章として吐き出したら、こんな2017年もポジティブに生きられそう。

最近欲しいと感じたもの

最近の(少なくとも僕の知っている)Webフレームワークというか Web アプリケーションを作るためのエコシステム全体のバランスが崩れてあまり調和が取れていない気がする。FaaSとかを使うととっても安く全世界に公開できるシステムを作れるというのに、僕がそれをビビって本気で勉強する気が起きないのは、標準が無いからな気がするけど、それにしても面倒なことが多い。それぞれの単発の技術としては納得感があるのだけど、僕が Django とかで始めたときのような、ORM で M 書いて、テンプレートエンジンで V 書いて、正規表現とタプルで C 書いて、 mod_wsgi の設定書いて終わり!みたいな感じじゃないあたりが辛い。

URL とロジックの結びつけは、 zip アップロードして画面でポチポチ設定する気にならない。そこまで手間は変わってないからたぶん気分の問題なんだけど、なんとか統合なんちゃらとか、必要なステップのような気もするし、設定より規約に従ったら省けるステップのような気もする。 Swagger と zip をアップロードした後にあのあたりいじってるとうーんってなる。実はもっと簡単な方法があって僕がそれを知らないだけの話かもしれない。ちょっと気をつけて書いた Flask あたりを放り投げたら勝手に FaaS で実行してくれないかな。というかあのあたりは MVC それぞれの代替というよりも、これまでの Webサーバとかリバースプロキシ+C を 1 レイヤにした感じがする。そうなってくると、うまく開発スタイルを作るのが難しい。開発者がリバースプロキシを使うのもちょっとうーんってなる。エコシステムのバランスが取れていないような気もする。毎月無料分用意しとるやろって言われても、なんか開発が1台で完結できないのはモヤモヤする。クラウド上で動くアプリ作ってるんだからしゃーないやろって言われても、新幹線の中でノートパソコンを開いて遊んでいた時間は今後別なことに使わないといけなくなってしまう。そこまで困らないんだけどなんかモヤモヤする。

アカウント管理まわりはもう変わりきった感じする。数年前はクライアントサイドに保存してHMACで署名とかちょっと怖いなとか思ってたけど、最近はもう違和感ない。逆にスケールの観点からリクエストごとに同じ場所に問い合わせるとかやばいって気がする。保存先をクラスタにするってのもあるけど、 HMAC の良さには敵わない気がする。それで思ったのは HttpServletRequest のあたりとかもう不要だよなぁと。 Spark Java は最近触ってて好きなんだけど、やっぱり裏側に Servlet がチラチラと顔を出してくる。あぁやっぱり普遍的な抽象化って難しいなぁ。頼むからそんなに高く積み上げないでくれ。コントロールしたいのは些細なことなのに何層も掘り下げるのは残念な感じがする。

FaaS と Java は相性悪いって話もわかるんだど、 JavaScript でサーバサイド書くのはなかなか辛いものがある。最近の KVS だけならまぁいいんだけど、node.js + RDB で Promise まで含めたときの混沌とした感じはなんというかこれこそジャヴァスクリプトって感じがする。その点まぁPythonはいいぞ。でもやっぱりサーバサイドは Java バイトコードぐらいで動いて欲しいのと型はしっかりして欲しい。

検索エンジンミドルウェアも皆あれで満足しているんだろうか?ログ解析ツールとしてはよく聞くけど、プロダクトの部品として普通に検索エンジンとして使っている情報はあんまり見ない気がする。僕が知らないだけかもしれない。あのアップデートの辛さは聞く限りではそうとう辛い。検索と権限の組み合わせも考えるととても既存の何かではスマートに対処できる気がしない。権限は将来変わる可能性があるのでインデックスするときに用意できない。汎用的な検索サービスが欲しいけど、そのあたりを考えるとなかなかに難しい。

クライアントサイド周りも職場の席近い先輩が、サーバがどんどん状態放棄して複雑さが押し付けられてるって叫んでる。SPA の画期的なフレームワークもまだ無くて、 Angular2 には少し期待しているんだけど、大半の開発者が欲しいのは DI とかの裏方ではなくて、ヒストリ管理とかショートカットキーとかユーザに直接影響する部分ではないだろうか。近い気もするけどなんかここももやもやする。レスポンシブデザインも結構前から言われているけど、完璧に洗練される前に若干盛り下がった気がする。そしてなによりこうしていろいろ考えるとなんとかスクリプトコンパイルしてなんとかスクリプトとかなんとかシートにした後になんとかファイしてなんとかマップつくってってのがなんとかパックでできるらしいけど、俺はただそのコマンドにこのオプション付けて欲しいんだけどってのをなんとかプラグインのソースを探してなんとか修正して半日ぐらい終わるともう何かやり遂げた感じがする。ただコマンドのオプション1個足しただけなのに。このあたりはなんか太古の呪文があったような…、acとかinとかamとか、なんだ、うっ…頭が…。

あーなんかのうみそすきゃんしてぽんっとしてくれるそうちがほしい。

GNOME3用アプリケーション開発に入門してみる その3

GIO編。リファレンスをざっと見せよとのこと。

GIO Reference Manual: GIO Reference Manual

ファイルシステムにかかわるのは以下の6つ

  • GFile
  • GFileInfo
  • GFileEnumerator
  • GDrive
  • GVolume
  • GMount

GFileEnumerator はいわゆるイテレータ。 GDriveがGVolumeのリストを持っていて、マウントしていればGMountが使える。

読み書きのストリーム系はJavaと似ている。 確かにあのデコレータの設計は良いと思う。

あとシステムにインストールされているアプリケーションについては特別なクラスがある。 他にもソケット通信系、GSettings、D-Busなんかが用意してある。

なるほど。アプリケーションの裏側を作るには十分ってかんじだ。

_async が付いているメソッドは非同期で処理される。 終わったかどうかは _finish

GNOME3用アプリケーション開発に入門してみる その2

GObject

GObject Reference Manual: GObject Reference Manual

C言語オブジェクト指向を実現する仕組み。 他言語用にAPIを提供する仕組みも備えているので、 Cで書けばC++はもちろんPythonPHPとかからも使えるようになる。 たぶん逆もしかり。

ざっと見ではC++のvtableとかマングル名とかをCの構造体や命名規則、 マクロで実装している感じで合っていると思う。 加えて参照カウンタやObserverパターンのためのsignalの規則もあるっぽい。

チュートリアルから開始。

ヘッダファイルはハイフンかアンダースコアで区切るのが一般的っぽい。 privateを末尾につけた場合はインストールしない。

とりあえず maman-bar.h をコピペして、Object Construction, Object Destruction あたりまで進めてみる。

/*
 * Copyright/Licensing information.
 */

/* inclusion guard */
#ifndef __MAMAN_BAR_H__
#define __MAMAN_BAR_H__

#include <glib-object.h>
/*
 * Potentially, include other headers on which this header depends.
 */

/*
 * Type macros.
 */
#define MAMAN_TYPE_BAR                  (maman_bar_get_type ())
#define MAMAN_BAR(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
#define MAMAN_IS_BAR(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
#define MAMAN_BAR_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
#define MAMAN_IS_BAR_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
#define MAMAN_BAR_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))

typedef struct _MamanBar        MamanBar;
typedef struct _MamanBarClass   MamanBarClass;
typedef struct _MamanBarPrivate MamanBarPrivate;

struct _MamanBar
{
  /* Parent instance structure */
  GObject parent_instance;

  /** Private data pointer */
  MamanBarPrivate* priv;

  /* instance members */
};

struct _MamanBarClass
{
  /* Parent class structure */
  GObjectClass parent_class;

  /* class members */
};

/* used by MAMAN_TYPE_BAR */
GType maman_bar_get_type (void);

/*
 * Method definitions.
 */

#endif /* __MAMAN_BAR_H__ */
/*
 * Copyright information
 */

#include "maman-bar.h"
#include <glib.h>
#include <glib/gprintf.h>

/* If you use Pimpls, include the private structure 
 * definition here. Some people create a maman-bar-private.h header
 * which is included by the maman-bar.c file and which contains the
 * definition for this private structure.
 */
struct _MamanBarPrivate
{
  GObject *an_object;

  gchar *a_string;
};

G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)

static void
maman_bar_dispose (GObject *gobject)
{
  MamanBar *self = MAMAN_BAR (gobject);
  g_printf("maman_bar_dispose\n");

  /* In dispose(), you are supposed to free all types referenced from this
   * object which might themselves hold a reference to self. Generally,
   * the most simple solution is to unref all members on which you own a 
   * reference.
   */

  /* dispose() might be called multiple times, so we must guard against
   * calling g_object_unref() on an invalid GObject by setting the member
   * NULL; g_clear_object() does this for us.
   */
  // g_clear_object (&self->priv->an_object);

  /* Always chain up to the parent class; there is no need to check if
   * the parent class implements the dispose() virtual function: it is
   * always guaranteed to do so
   */
  G_OBJECT_CLASS (maman_bar_parent_class)->dispose (gobject);
}

static void
maman_bar_finalize (GObject *gobject)
{
  MamanBar *self = MAMAN_BAR (gobject);
  g_printf("maman_bar_finalize\n");

  g_free (self->priv->a_string);

  /* Always chain up to the parent class; as with dispose(), finalize()
   * is guaranteed to exist on the parent's class virtual function table
   */
  G_OBJECT_CLASS (maman_bar_parent_class)->finalize (gobject);
}

static void
maman_bar_class_init (MamanBarClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  g_printf("maman_bar_class_init\n");

  gobject_class->dispose = maman_bar_dispose;
  gobject_class->finalize = maman_bar_finalize;
}

static void
maman_bar_init (MamanBar *self)
{
  self->priv = maman_bar_get_instance_private (self); 
  g_printf("maman_bar_init\n");

  self->priv->an_object = NULL; // g_object_new (MAMAN_TYPE_BAZ, NULL);
  self->priv->a_string = g_strdup ("Maman");
}

生成と破棄はたぶんこんな感じ。

#include "maman-bar.h"

int main(int argc, char const* argv[]) {
    GObject* bar = g_object_new (MAMAN_TYPE_BAR, NULL);
    g_object_unref(bar);
    return 0;
}

破棄がdisposeとfinalizeで分かれているのは参照カウンタがループしている時のためっぽい。