2012年5月3日木曜日

ヴィータのアプリに効果音やBGMを付けてみる & アプリのメモリ使用量制限について

今回の記事では、PSVITA(プレイステーションヴィータ)+PlayStation Suite(Pss)による自作アプリに、効果音とBGMを付けてみる、という内容について書かせて頂きたく思います。

アプリのメモリ使用量制限については、後述させて頂きます。

ちなみに、モチーフとしたのは、この前作ったヴィータ電卓(リンクはこちらになります)ですが、細かい改良を加えているので、合わせてそれについても触れさせて頂きたくよろしくお願いいたします。

■アプリに効果音と音楽をつけてみる■

ヴィータは、さすが天下のゲーム機だけあって、効果音やBGMを面倒なく実装する事が出来ます。
これをヴィータ電卓に追加してみようと思います。
起動すると音楽(BGM)が演奏されて、電卓のキーをタッチすると「チャカッ」と打鍵音がする(このブログでは画像だけで音をお聴きいただく事が出来ずに申し訳ありません)ように作ってみました。

効果音は、wavファイル、音楽はMP3を使います(現在はこのフォーマットしか許可されていません)。
これらを用意したら、PssStudioのソリューションの中にファイル追加します。
そして、追加したファイル名の「ビルドアクション」から「Content」を選択してプログラムをコンパイル(ビルド)した時にサウンドファイルとして認識してもらうように設定しておきます。
これ、私だけかも知れませんが、何か忘れそうですね・・・気をつけよっと。

■画面部分に実装するプログラムコード(抜粋)■

//(1)名前空間指定部分
using Sce.Pss.Core.Audio;

//(2)変数定義部分
public Bgm          oBGM;
public BgmPlayer   oBGMP;

   
//(3)効果音のインスタンス化 ※ファイル名は適宜読み替えます
oSD = new Sound("/Application/sound/clicksound1.wav");
oSDP = oSD.CreatePlayer();
   
//(4)BGMのインスタンス化 ※ファイル名は適宜読み替えます
oBGM = new Bgm("/Application/sound/vitaBGM.mp3");
oBGMP = oBGM.CreatePlayer();
oBGMP.Loop=true; //BGM 繰り返し
//(コメントアウト中)oBGMP.Volume = -1; //ボリューム設定

//(5)実際に音楽の演奏を行うメソッド実行部分
oBGMP.Play();

//(6)効果音の鳴動を行うメソッド実行部分
oSDP.Play();


■実際の起動と、改良点■

ヴィータ電卓が起動すると同時に、指定したBGMがループして演奏されます。
実際には、音楽というより、昔のSF映画であった「ピコピコー」とかいうコンピュータの動作音がたまに鳴ったり、スターウォーズのR2-D2の声がたまーに流れたりするファイルを演奏させる感じかな。
個人的な遊びでなら色々とやれそう。

キーをタッチすると、効果音が鳴ります。
今回の効果音ファイル容量は11KB程度で「チャカッ」と。
言ったら当たり前かも知れませんが、タイムラグも感じません。
タッチパネルは、残念ながら、つるっつるっの平面で硬くて、触れてあまり気持ちが良いデバイスではないと思うので、打鍵感を効果音でフォローというのは結構重要かも知れませんね。

効果音は複数同時再生可能ですが、音楽は同時には一曲のみ演奏という仕様になっています。

改良点は、ヴィータ電卓を実際に身近な方々に使って頂いて・・・以下の(1)から(4)について行いました。

サウンドからは離れてしまいますが・・・。
(1)文字を白から黒に変更
(2)表示される数字をカンマで区切る
(3)クリップエリア(メモリーエリア)に格納する数字は、 計算の結果ではなくて現在表示中の値にする
(4)ハードウェアキーのスタートボタンにアプリ終了機能を実装する。
ハードウェアキーに終了機能を実装する話は、以前の記事の手法(リンクはこちらですと同じ(コードの書き方は少し違いますが)です。



■制御(メイン)部分のコードです■

using System;
using System.Collections.Generic;

using Sce.Pss.Core;
using Sce.Pss.Core.Environment;
using Sce.Pss.Core.Graphics;
using Sce.Pss.Core.Input;
using Sce.Pss.HighLevel.UI;

namespace mmmKantanDentaku
{
    public class AppMain
    {
        private static  GraphicsContext graphics;
  private static  bool            bRES;
  private static  bool            bKEYSTS;

        public static void Main (string[] args)
        {
            Initialize ();
   
   //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
            while (bRES) 
   {
                SystemEvents.CheckEvents ();
                Update ();
                Render ();
            }
   //@@@@@@@@@@[LOOP-END  ]@@@@@@@@@@
        }

        public static void Initialize ()
        {
            // Set up the graphics system
            graphics = new GraphicsContext ();

            // Initialize UI Toolkit
            UISystem.Initialize(graphics);

   // Create scene
   var MyScene = new mmmKantanDentaku.Cls_Scene();
   // Set scene
   UISystem.SetScene(MyScene, null);
   
   bRES = true;
   bKEYSTS = false;
   
        }

        public static void Update ()
        {
            // Query gamepad for current state
            var gamePadData = GamePad.GetData (0);
   //Cls_Scene oScene;
   
   //oScene = new Cls_Scene();

            // Query touch for current state
            List touchDataList = Touch.GetData (0);

            // Update UI Toolkit
            UISystem.Update(touchDataList);
   
   if(!bKEYSTS)
   {
    //ボタンが押された、かつ、それがスタートボタンか?を一挙に判定してます
    if((gamePadData.Buttons & GamePadButtons.Start)!=0)
    {
     MessageDialog.CreateAndShow(MessageDialogStyle.OkCancel,
                                 "ヴィータよりの確認",
                                 "終了してよろしいですか?"
     ).ButtonPressed+= HandleButtonPressed;
     bKEYSTS=true;//終了確認ダイアログ重複表示不可能
    }
   }
        }

        static void HandleButtonPressed (object sender, MessageDialogButtonEventArgs e)
        {
   if(e.Result.Equals(MessageDialogResult.Ok))    
   {
          bRES=false;//メインループ終了 
   }
   else
   {
    bKEYSTS=false;//また終了確認ダイアログ表示可能
   }
   
        }

        public static void Render ()
        {
            // Clear the screen
            graphics.SetClearColor (1.0f, 1.0f, 1.0f, 1.0f);
            graphics.Clear ();

            // Render UI Toolkit
            UISystem.Render ();

            // Present the screen
            graphics.SwapBuffers ();
   
 
   
        }
    }
}


■アプリのメモリ使用量制限について■

ちなみに、冒頭のスクリーンショット内部に既に書かせて頂きましたけれど、ヴィータのPlayStation Suiteアプリケーションは、 メモリ使用量が96MBまでに制限されています(仕様上)。
アプリが使うメインメモリと、画像やサウンドなどに割り当てるヒープ用メモリの2種類があって、これらを別々に設定ファイル(app.cfg)にKB単位で記述する事によって、個別に容量指定が可能です。
この両者の合計が96MBまでという仕様になっています。

おおーー96MBってかなり多くないですか?

実は、自作のプログラムを許可するのだから、その代償としてメモリはもっと壮絶に規制されているのだろうなぁと想像していました。
初期のi-modeのiアプリの10KB制限みたいなものではないにしろ、数メガバイト程度になったりして・・・とか思っていました。
96MBというのは、PSP-1000が搭載している全メインメモリ量(32MB)の3倍もの容量で、むしろ大盤振る舞いの数字だなぁと。

それにつけても、本当にゲーム機の時代が変わりましたねー。
音楽や効果音は、極めて高音質なものが、個人でも自由自在に自分のプログラムに組み込んでヴィータの音源からバリバリ流せてしまう。
ポケコン、テレビゲーム機、携帯ゲーム機、そしてPC・・・全てのジャンルが分担して実現して来た夢が、ついに一つに結実した感じがして目頭が熱いわい。
ヴィータは色々な意味で、私が想像するよりもずっとずっと強いのかも知れない。