• 【アイマス】新世代の音楽プレイヤーソフトを作る#6

    2015-12-17 21:006


    まず最初にプログラミング経験とアイマスに関するアンケートを実施しております。
    ぜひご協力お願いいたします。

    アンケート回答はこちら


    紹介が遅くなりました、はやなりと申します。ニコニコに作ってみた動画などあげてます。
    新世代の音楽プレイヤーを作る第6回です。今回はプレイヤーの重要なカギとなる音源を準備します。




    とは言いつつ説明はほとんど動画内でしてしまいましたので、今回は録音のコツと原理をお教えしたいと思います。



    ①キャプチャソフトは音源非圧縮のものを
    私の使うキャブチャーボードに付属していたソフトは音を圧縮してしまい、アカペラ・オフボーカルを作れませんでした。おそらくmp4ファイルにしていましたので、AAC圧縮をかけていたんだと思います。そこでアマレコTVの出番です。アマレコTVは音源を圧縮せずに録画ができます。



    ②動画ファイルのサイズがとてつもなく大きい!!
    動画内でもちらっと出ていましたが、アマレコTVでの録画は高画質の代わりにとてつもなくデータサイズが大きいです。2分の動画で4GBはやばいですね。
    HDDの空き容量がない!という方はコーデックを変えてみてください。h.264はコマ落ちがひどくなりますが、音源はしっかり取れて50MBに収まるので、おすすめです。x264をインストールすれば、
    アマレコTVの録画設定>>ビデオ圧縮>>コーデック(いろいろ)の更新を押して一覧に出てくるかと。



    ③ワンフォーオールの設定変更が面倒
    毎回S4Uと設定を行ったり来たりするのは面倒です。そういう時はまずはボーカル最大のものを3人分録って、設定に戻りボーカル最小にして3人分とるというのが効率が良いです。
    さらに最初の録画の時にステージを保存しておくとアルバムからも録画できますので、もっと効率が良くなります。
    これはm@sterplayerをつくった時にしてましたね。13人分は結構時間に差がでました。今回は3人分ですのであっという間です(笑)

    コツはこんな感じです。




    では
    なぜアカペラとオフボーカルに分けれるのか
    をお教えします。

    簡単に言うと
    音の引き算をしています。

    ボーカルをアイドルのアカペラの音、オフボーカルをカラオケとしましょう。
    まず最初にボーカル最大音量のものをとりました。
    その音を数値で表すと

    100ボーカル+70オフボーカル
    になります。(数値は適当)




    次にボーカル最小音量をとりました。
    その音を数値で表すと

    10ボーカル+70オフボーカル

    このボーカル最小音量をaudacityで上下反転すると、波を打ち消す効果がでます。
    数値で表すと

    -10ボーカル-70オフボーカル

    です。

    これをズレなく同時に再生すると

    100ボーカル
    +70オフボーカル-10ボーカル-70オフボーカル

    という式が成り立ちます。
    音は

    90ボーカル
    が残りました。これでアカペラになったんですね。

    オフボーカルの取得についてはボーカル最大音量のデータをAudacityで小さくして取得しました。この時ボーカルの音量を最小のものと等しくしたんですね。

    なのでボーカル最大音量のものは
    (100ボーカル+70オフボーカル)/10という処理をします。
    これで
    10ボーカル+7オフボーカルになりました。

    これを足すと

    10ボーカル+7オフボーカル-10ボーカル-70オフボーカル

    という式が成り立ちました。
    残った音は

    -63オフボーカルです。
    負の音(波形を上下反転した音)でも音はおなじように聞こえますのでオフボーカルができたわけです。

    こんな感じで引き算をしたイメージです。この処理は音源を圧縮してしまうとノイズのためかできなくなるor効果が薄くなるので、録音に非圧縮を推奨したんです。

    この手法はボーカルの音データとオフボーカルを分けているアイマスだからこそできる技です。
    ちなみにアイマス2や無印、L4Uもできたとおもいます。



    質問などあれば下部のコメント欄にて...


    繰り返しになりますが

    アンケート回答はこちら

    次回にて集計結果をおしらせします。




  • 広告
  • 【アイマス】新世代の音楽プレイヤーソフトを作る#5

    2015-12-06 20:232

    ども、はやなりと申します。ニコニコに作ってみた動画などあげてます。

    新世代の音楽プレイヤーを作る第5回です。Processingを使い、新しい音楽プレイヤーを作る動画の詳細な解説になります。





    以下ソースコード
    追加・変更した部分には色を付けてあります。



    triangles_5.pde



    color mio = color(244, 194, 67);
    color rin = color(79, 106, 175);
    color uzuki = color(216, 47, 120);

    color rinmio = blendColor(rin, mio, SCREEN);
    color uzurin = blendColor(uzuki, rin, SCREEN);
    color uzumio = blendColor(uzuki, mio, SCREEN);
    color UMR = blendColor(rinmio, uzuki, SCREEN);

    color pick;

    int mioX=320, mioY=10;
    int rinX=605, rinY=90;
    int uzuX=30, uzuY=90;
    int lX=152, lY=360;
    int rX=482, rY=360;



    boolean transMio, transMioX, transMioY;
    boolean transRin, transRinX, transRinY;
    boolean transUzu, transUzuX, transUzuY;




    void setup() {
    size(640, 360);
    background(255);
    noStroke();
    }


    void draw() {
    fill(255);
    rect(0, 0, width, height);
    moveVertex();
    triangles(mioX, mioY, uzuX, uzuY, rinX, rinY, lX, lY, rX, rY);
    pick=get(mouseX, mouseY);
    }

    int intersectionX(int p1x, int p1y, int p2x, int p2y, int p3x, int p3y, int p4x, int p4y) {
    int s1, s2, ansx;
    s1 =((p4x-p2x)*(p1y-p2y)-(p4y-p2y)*(p1x-p2x))/2;
    s2 =((p4x-p2x)*(p2y-p3y)-(p4y-p2y)*(p2x-p3x))/2;
    ansx = p1x+(p3x-p1x)*s1/(s1+s2);
    return ansx;
    }

    int intersectionY(int p1x, int p1y, int p2x, int p2y, int p3x, int p3y, int p4x, int p4y) {
    int s1, s2, ansy;
    s1 =((p4x-p2x)*(p1y-p2y)-(p4y-p2y)*(p1x-p2x))/2;
    s2 =((p4x-p2x)*(p2y-p3y)-(p4y-p2y)*(p2x-p3x))/2;
    ansy = p1y+(p3y-p1y)*s1/(s1+s2);
    return ansy;
    }

    void triangles(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy, int ex, int ey) {
    fill(mio);
    triangle(ax, ay, dx, dy, ex, ey);
    fill(uzuki);
    triangle(bx, by, dx, dy, ex, ey);
    fill(rin);
    triangle(cx, cy, dx, dy, ex, ey);
    int rinmioX=intersectionX(ax, ay, dx, dy, ex, ey, cx, cy);
    int rinmioY=intersectionY(ax, ay, dx, dy, ex, ey, cx, cy);
    int uzurinX=intersectionX(bx, by, dx, dy, ex, ey, cx, cy);
    int uzurinY=intersectionY(bx, by, dx, dy, ex, ey, cx, cy);
    int uzumioX=intersectionX(bx, by, dx, dy, ex, ey, ax, ay);
    int uzumioY=intersectionY(bx, by, dx, dy, ex, ey, ax, ay);
    fill(uzumio);
    triangle(uzumioX, uzumioY, dx, dy, uzurinX, uzurinY);
    fill(rinmio);
    triangle(rinmioX, rinmioY, uzurinX, uzurinY, ex, ey);
    fill(UMR);
    triangle(uzurinX, uzurinY-2, dx, dy, ex, ey);
    }

    int transX(int a) {
    a+=mouseX-pmouseX;
    return a;
    }

    int transY(int a) {
    a+=mouseY-pmouseY;
    return a;
    }



    void moveVertex() {
    if (transMioX) {
    mioX=transX(mioX);
    } else if (transRinX) {
    rinX=transX(rinX);
    } else if (transUzuX) {
    uzuX=transX(uzuX);
    }
    if (transMioY) {
    mioY=transY(mioY);
    } else if (transRinY) {
    rinY=transY(rinY);
    } else if (transUzuY) {
    uzuY=transY(uzuY);
    }

    }

    void mousePressed() {
    if (pick==color(mio)) {
    transMio=true;
    transMioX=true;
    transMioY=true;
    } else if (pick==color(rin)) {
    transRin=true;
    transRinX=true;
    transRinY=true;
    } else if (pick==color(uzuki)) {
    transUzu=true;
    transUzuX=true;
    transUzuY=true;
    }
    }
    void mouseDragged() {
    if(transX(0)<0){
    if(mioX<lX+100)transMioX=false;
    if(rinX<rX)transRinX=false;
    if(uzuX<20)transUzuX=false;
    } else if(transX(0)>0){
    if(mioX>rX-100)transMioX=false;
    if(rinX>width-20)transRinX=false;
    if(uzuX>lX)transUzuX=false;
    } else {
    if(transMio)transMioX=true;
    else if(transRin)transRinX=true;
    else if(transUzu)transUzuX=true;
    }
    if(transY(0)<0){
    if(mioY<20)transMioY=false;
    if(rinY<100)transRinY=false;
    if(uzuY<100)transUzuY=false;
    }else if (transY(0)>0){
    if(mioY>120)transMioY=false;
    if(rinY>200)transRinY=false;
    if(uzuY>200)transUzuY=false;
    }else{
    if (transMio)transMioY=true;
    else if (transRin)transRinY=true;
    else if (transUzu)transUzuY=true;
    }

    }
    void mouseReleased() {
    transMio=false;
    transMioX=false;
    transMioY=false;

    transRin=false;
    transRinX=false;
    transRinY=false;

    transUzu=false;
    transUzuX=false;
    transUzuY=false;
    }
    void mouseClicked() {
    }




    解説は今回はナシでいきます。(前回あまり質問や反響がなかったため)
    まあ、言いたいことは前回ほとんど言ってしまったこともありますので。


    かわりに次回への導入として、音源を取るのにどういった機器が必要かピックアップしておきます。

    ちなみに音源はCDなどから用意してできないこともないですが、この音楽プレイヤーの場合は特殊な機能をつけますので、より楽しむにはCD音源は向いていません。

    ではどこから音源を取るのか。察しの良い方は気づいていると思いますが、ゲームから取ります。

    必要なものは

    ①PS3

    ②アイドルマスター ワンフォーオール



    PS3のアイマスのゲームはアイドルマスター2やアイドルマスターワンフォーオールなどがありますが、私のやり方ではそのどちらからも音源は取れます。今回はNGを使っていますのでワンフォーオールを使います。

    ③DLC第13弾
    Star!!が収録されているDLCをお買い求めください。「お願いシンデレラ」がしたければそちらでもかまいません。

    ④ビデオキャプチャーボード

    これがネックです。高価なものですし、基本的にデスクトップパソコンにしか取り付けられません。できるだけ綺麗な音を取る必要があるため、デジタル信号からの音が必要になります。かわりになる録音機器を買うくらいなら、キャプチャーボードを買う方が早いかもしれません。用意できなければ諦めましょう。かわりにCD音源を使うしかないです。または新しい方法を思いつけば別ですが...。もしかするとイヤホンジャックなどから音を持ってきてやれるかもしれないです。(うp主はその方法でやって頓挫しました)

    私はHDMVC4UCというものを使っていますが、今では値段も上がっており、販売しているところも少ないようです。買おうと考えている方はまだ様子見で良いんではないでしょうか。これだけのために買うのはもったいない気もします。私もできるだけ持っていない人向けのものも考えてみるつもりです。

    より安く、簡単にできる方法を知っている方は教えていただけると幸いです。

    ⑤デスクトップPC
    キャプチャーボードがつけれて、編集するソフトを入れられるパソコンが必要です。私はPCI Express x1で接続するキャプチャボードですのでデスクトップPCが必須でした。
    ちなみに編集ソフトは無料のものでAudacityを使います。



    今回は以上です。次回はプログラミングというより、音の準備になりそうです。











  • 【アイマス】新世代の音楽プレイヤーソフトを作る#4

    2015-11-21 20:001

    ども、はやなりと申します。ニコニコに作ってみた動画などあげてます。

    新世代の音楽プレイヤーを作る第4回です。Processingを使い、新しい音楽プレイヤーを作る動画の詳細な解説になります。



    今回はマウスの動きとリンクさせるプログラムを作ります。条件分岐が入ります。

    以下ソースコード
    追加した部分には色を付けてあります。それ以外は文字サイズを小さくしました。

    triangles_4.pde




    color mio = color(244, 194, 67);
    color rin = color(79, 106, 175);
    color uzuki = color(216, 47, 120);

    color rinmio = blendColor(rin, mio, SCREEN);
    color uzurin = blendColor(uzuki, rin, SCREEN);
    color uzumio = blendColor(uzuki, mio, SCREEN);
    color UMR = blendColor(rinmio, uzuki, SCREEN);



    color pick;

    int mioX=320, mioY=10;
    int rinX=605, rinY=90;
    int uzuX=30, uzuY=90;
    int lX=152, lY=360;
    int rX=482, rY=360;

    boolean transMio, transRin, transUzu;


    void setup() {
    size(640, 360);
    background(255);
    noStroke();
    }


    void draw() {
    fill(255);
    rect(0,0,width,height);
    moveVertex();
    triangles(mioX, mioY, uzuX, uzuY, rinX, rinY, lX, lY, rX, rY);
    pick=get(mouseX,mouseY);
    }

    int intersectionX(int p1x, int p1y, int p2x, int p2y, int p3x, int p3y, int p4x, int p4y) {
    int s1, s2, ansx;
    s1 =((p4x-p2x)*(p1y-p2y)-(p4y-p2y)*(p1x-p2x))/2;
    s2 =((p4x-p2x)*(p2y-p3y)-(p4y-p2y)*(p2x-p3x))/2;
    ansx = p1x+(p3x-p1x)*s1/(s1+s2);
    return ansx;
    }

    int intersectionY(int p1x, int p1y, int p2x, int p2y, int p3x, int p3y, int p4x, int p4y) {
    int s1, s2, ansy;
    s1 =((p4x-p2x)*(p1y-p2y)-(p4y-p2y)*(p1x-p2x))/2;
    s2 =((p4x-p2x)*(p2y-p3y)-(p4y-p2y)*(p2x-p3x))/2;
    ansy = p1y+(p3y-p1y)*s1/(s1+s2);
    return ansy;
    }

    void triangles(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy, int ex, int ey) {
    fill(mio);
    triangle(ax, ay, dx, dy, ex, ey);
    fill(uzuki);
    triangle(bx, by, dx, dy, ex, ey);
    fill(rin);
    triangle(cx, cy, dx, dy, ex, ey);
    int rinmioX=intersectionX(ax, ay, dx, dy, ex, ey, cx, cy);
    int rinmioY=intersectionY(ax, ay, dx, dy, ex, ey, cx, cy);
    int uzurinX=intersectionX(bx, by, dx, dy, ex, ey, cx, cy);
    int uzurinY=intersectionY(bx, by, dx, dy, ex, ey, cx, cy);
    int uzumioX=intersectionX(bx, by, dx, dy, ex, ey, ax, ay);
    int uzumioY=intersectionY(bx, by, dx, dy, ex, ey, ax, ay);
    fill(uzumio);
    triangle(uzumioX, uzumioY, dx, dy, uzurinX, uzurinY);
    fill(rinmio);
    triangle(rinmioX, rinmioY, uzurinX, uzurinY, ex, ey);
    fill(UMR);
    triangle(uzurinX, uzurinY-2, dx, dy, ex, ey);
    }

    int transX(int a){
    a+=mouseX-pmouseX;
    return a;
    }

    int transY(int a){
    a+=mouseY-pmouseY;
    return a;
    }

    void moveVertex(){
    if(transMio){
    mioX=transX(mioX);
    mioY=transY(mioY);
    }else if(transRin){
    rinX=transX(rinX);
    rinY=transY(rinY);
    }else if(transUzu){
    uzuX=transX(uzuX);
    uzuY=transY(uzuY);
    }
    }

    void mousePressed(){
    if(pick==color(mio)){
    transMio=true;
    }else{
    transMio=false;
    }

    if(pick==color(rin)){
    transRin=true;
    }else{
    transRin=false;
    }

    if(pick==color(uzuki)){
    transUzu=true;
    }else{
    transUzu=false;
    }
    }
    void mouseDragged(){
    }
    void mouseReleased(){
    transMio=false;
    transRin=false;
    transUzu=false;
    }
    void mouseClicked(){
    }




    解説1 アニメーションの設定

    第二回でsetup関数とdraw関数に分け、アニメーションの表現を可能にしたと言いましたが、それだけではアニメーションの表現は不十分です。今までの状態で実行すると三角形は止まって見えていますよね。もし、それが動くとしたら前のフレームの画面が残ったままなので、三角形が連続して見えてしまいます。

    void draw() {
    fill(255);
    rect(0,0,width,height);
    triangles(mioX, mioY, uzuX, uzuY, rinX, rinY, lX, lY, rX, rY);
    }

    そこで画面のリセットを行います。draw関数の一番上にfill関数とrect関数を置き白の四角形を描きます。こうすることで次のフレームの描写に移ったとき、最初に画面を真っ白にさせるので、前のフレームの描写は隠されるということです。試しに、この2行のコードを消してみれば必要性がわかるはずです。
    ちなみにbackground(255);としても同様になります。




    解説2 色データの取得

    変数pickをカラー型で宣言し、get関数で今あるマウスの位置の色を取得します。

    color pick=get(mouseX,mouseY);

    get関数
    get(x,y);で座標(x,y)にあるピクセルのカラーデータを返します。

    mouseX,mouseY
    デフォルトで設定されているシステム変数の一つです。マウスの位置をX,Y座標で返します。

    よってpickはつねにマウスのある場所の色を参照してるわけです。




    解説3 マウスの関数と変数

    マウスはいろんな操作ができますね。ポインタの移動、クリック、スクロール...
    それらの動作に応じるプログラムを作るのはProcessingでは難しいことではありません。

    マウスに関する関数

    mousePressed関数
    マウスのボタンのどれかが押されたときに

    mouseDragged関数
    ドラッグしたときに

    mouseReleased関数
    ボタンから離したときに

    mouseClicked関数
    クリックしたときに

    関数の中身が実行されます

    これらとmouseX,mouseYを組み合わせば、いろんなことがマウスでできます。これらはdraw関数の中に置く必要はなく、デフォルトである関数なのでsetup関数やdraw関数と同じ部類のものだと思ってください。

    マウスに関する変数

    mouseX
    現在のマウスのX方向の座標を返す
    mouseY
    現在のマウスのY方向の座標を返す

    pmouseX
    1フレーム前のマウスのX方向の座標を返す

    pmouseY
    1フレーム前のマウスのY方向の座標を返す


    既出ですが、mouseX,mouseYはマウスの位置を返してくれます。
    似たものにpmouseXとpmouseYがあります。これは1フレーム前のマウスの位置を記憶しておいて、教えてくれる変数です。

    int transX(int a){
    a+=mouseX-pmouseX;
    return a;
    }
    こんな感じでマウスをどのくらい動かしたかわかるわけです。





    解説4 ブーリアン型

    データ型はint型、float型、color型などいろんなものがありますが、他にも種類があります。その一つがブーリアン型です。

    boolean transMio, transRin, transUzu;

    ブーリアン型とは日本語で言えば「はい/いいえ」または「真/偽」、英語で言えば「Yes/No」数字で言えば「0/1」のデータを入れたいときに使うデータ型です。状態がはっきりわかるので使い易いデータ型かもしれません。

    true(真)かfalse(偽)しか代入できず、他のものを入れようとするとエラーになります。

    trueが「はい」にあたり、falseが「いいえ」に当たります。ボタンを押している間はtrue、離している間はfalseにする用途に今回は使います。

    代入は

    boolean a = true;
    boolean b = false;

    というように数字ではないのが特徴です。





    解説5 条件分岐

    条件分岐とは、ある条件ではこれをして、この条件のときはこっちをしてと、命令することです。これが多いほどいろんな機能をつけれるんではないでしょうか。

    if文
    if(条件A)~;

    で条件Aをみたすとき~を実行します。

    )
    int age;
    int time=20151121;
    if(time==20151121) age=18;

    ageには18が入ります。武内Pは18歳なんですよね?


    ここで注目は条件の==です。これは数学でいうイコールなんですが、プログラミングでは代入に=を使う為、==が等号になります。一方が数値などなら左辺に変数をおいたほうが良いですね。

    else if文
    if(条件A)~;
    else if(条件B)~~;

    if文の後に続けることで、ifの条件以外の他の条件(条件B)を満たすときに~~を実行します。else ifは何個でも続けることができます。

    命令を2つ以上するときは{}でくくれば、条件があったときに{}内が実行されます。

    )
    int age;
    int Production=346;
    if(Production==765) age=31;

    else if(Production==346) age=18;

    赤羽根Pは31らしいですね。変数ageには18が代入されます。

    else 
    if(条件A)~;
    else if(条件B)~~;
    else if(条件C)~~;

    .
    .
    .
    else ~;


    )

    int Production=961;
    boolean Jupiter;

    if(production==961) Jupiter=true;
    else jupiter=false;

    良い例が浮かばなかった。なんかあればコメントで教えて!




    総括

    今回は要点をつまんで解説しました。ここがよく分からないと下のコメントなどで教えてくれれば追記します。