LoginSignup
2
1

More than 5 years have passed since last update.

ADX2LEとWebプレーヤー(#SoundGameJam LudumDare35 Voipadius)

Last updated at Posted at 2016-04-24

Ludumdare 35に第5回サウンドゲームジャムで作ったVoipadiusで参加したのですが、
やっぱりWebプレーヤーで遊べると気軽に遊んでもらえそうなので対応してみた。

Webプレーヤー版Voipadius(ボイパディウス)
ボイスパーカッションバトルを味わえるような2人以上で遊ぶ楽器(?)です。
出てくるキャラに合わせてボタンを押す。人数が多い場合は適当に交代する。
音が鳴る。すべての音は声の録音素材です。(ドラムとかトランペットとか動物とかすべてボイパ。すごい。)

image

ダウンロード

AtomCraftプロジェクトファイル(Voipadius_AtomProject.zip)
Unityプロジェクト(Voipadius.unitypackage)

波形素材とAtomCraftプロジェクトの変更や再利用は自由にどうぞ。
音を差し替えてみたりして遊んでみてね。
(Unity5.3.4f1,ADX2LEv202)

scenesのgameSceneとVirtualNanoPadSceneを使ってます。
追加しておいてください。
MidiJackのアクセスで止まってしまう場合はコメントアウトしてみて。

やることは

  • ADX2LEのキューの名前、IDを修正
  • ADX2LEの音をwav化(バウンス)する
  • ADX2LEの警告を無効化する
  • AtomSourceのキュー再生をAudioSourceの再生にする

の4ステップ。

ADX2LEのキューの名前、IDを修正

Unityの標準再生は波形ファイルをAudioClipにするので、対応するAudioClipを作るための波形を用意する。
image

キュー名とキューIDで再生していたのだが、

IDはやめて名前を番号にすることで、すべて名前で呼べるようにした。

MIDIデバイスからの入力Note番号をそのままキューIDにするような形で作っている。
(60から始まるように少しずらしているけど)
0は無音用として、
キューIDがMIDINoteNoとして動作するようにしている。

元々あった名前はコメントに退避

image
流し込みペーストを使って名前とIDを入れ替え。

ADX2LEの音をwav化(バウンス)する

image

バウンス設定を修正して、一つずつバウンス。

image

マテリアルの「bounce」フォルダにキュー名で波形が作成される

あらかじめ名前を修正していたのでいい感じに。

image

マテリアルのフォルダに波形が出来る

たまに再生位置がずれたりして失敗している場合があるので再生してチェックし、失敗した波形はバウンスをやり直す。
あと、ランダムなども気に入らない場合はバウンスをやり直す。

image

あと、波形エディタで若干トリミングしています。

ADX2LEの警告を無効化する

Webプレーヤーでビルドするといくつか警告でビルドを中断されるので
以下の修正

CriAtom(24-30).cs
    #endif
#elif UNITY_WIIU || UNITY_PSP2 || UNITY_PS3 || UNITY_PS4 || UNITY_WEBGL
    #define CRIWARE_UNSUPPORT_SEQUENCE_CALLBACK
#elif UNITY_WEBPLAYER
#else
    #error undefined platform if supporting sequence callback
#endif

CriAtomExVoicePool(48-54).cs
#elif UNITY_PSP2
        StandardMemory          = StandardMemoryNsrVoicePoolId,     /**< 機種標準のメモリ再生ボイスプールID */
        StandardStreaming       = StandardStreamingNsrVoicePoolId,  /**< 機種標準のストリーミング再生ボイスプールID */
            #elif UNITY_WEBPLAYER
#else
        #error unsupported platform
#endif

CriAtomExVoicePool(70-76).cs
#elif UNITY_PS4
        Atrac9Memory            = 6,                                /**< [PS4] ATRAC9メモリ再生ボイスプールID */ 
        Atrac9Streaming         = 7,                                /**< [PS4] ATRAC9ストリーミング再生ボイスプールID */
            #elif UNITY_WEBPLAYER
#else
        #error unsupported platform
#endif

UNITY_WEBPLAYERの#ifをつけただけ。

AtomSourceのキュー再生をAudioSourceの再生にする

ファイル名でサクッとやりたかったのですが、
ここから少し面倒なことに、Unity5.3.4f1のWebプレーヤーだとResources.Loadがうまくいかない。
(あ、Resourcesに入れてなかったからか...とこれ書いてる時に気がついたがまぁいいや)

ので、[Resources.Loadを使わない方法でのシーンでのclip管理]的なTipsということで・・・

名前リスト用意して、clipを名前で指定できるようにしている。

image

シーンをキューシートみたいに見せかける話

シーンに無理やりすべてのAudioClipをシーンに追加。

bounceフォルダをUnityプロジェクトに入れて、
空のGameObject作って、その下に配置。

この時、名前の後ろに「 (1)」が勝手につく。
このAudioClipをclipArrayに入れて呼び出せるようにした。(ちと回りくどいかもね・・・)
でも、シーン単位で複数AudioClipを管理しているみたいにできるね。きっと。

image

PlayADX2.cs
public class PlayADX2 : SingletonMonoBehaviourFast<PlayADX2>
{
    public Text beatCountText;

    #if UNITY_WEBPLAYER
    AudioSource[] source = new AudioSource[2];
    int souceCount = 0;
    Dictionary<string,AudioClip> clipArray = new Dictionary<string,AudioClip>();
    string[] clipNameList = {
        "60",
        "61",
        "62",
        "63",
        "64",
        "65",
        "66",
        "67",
        "68",
        "69",
        "70",
        "71",
        "72",
        "73",
        "74",
        "75",
        "76",
        "BD",
        "blulu",
        "HH",
        "hituzi_0",
        "hituzi_1",
        "hituzi_2",
        "hituzi",
        "neco_0",
        "neco_1",
        "neco_2",
        "neco",
        "rest",
        "SD",
        "SD2",
        "TPLow",
        "TPLow2",
        "TPLow3"
    };

    AudioClip NameToClip(string name)
    {
        return clipArray[name];
    }
    AudioClip IdToClip(int id)
    {
        if(id < 60){

            AudioClip clip = null;
            switch(id)
            {
                case 0:clip = clipArray["rest"];break;
                case 1:clip = clipArray["BD"];break;
                case 2:clip = clipArray["blulu"];break;
                case 3:clip = clipArray["SD"];break;
                case 4:clip = clipArray["TPLow"];break;
                case 5:clip = clipArray["SD2"];break;
                case 6:clip = clipArray["TPLow2"];break;
                case 7:clip = clipArray["HH"];break;
                case 8:clip = clipArray["TPLow3"];break;
                case 9:clip = clipArray["hituzi"];break;
                case 10:clip = clipArray["neco"];break;
                case 11:clip = clipArray["hituzi_0"];break;
                case 12:clip = clipArray["neco_0"];break;
                case 13:clip = clipArray["hituzi_1"];break;
                case 14:clip = clipArray["neco_1"];break;
                case 15:clip = clipArray["hituzi_2"];break;
                case 16:clip = clipArray["neco_2"];break;

            }
            return clip;
        }

        return clipArray[id.ToString()];
    }

#else
    CriAtomSource source;
    #endif

    public GameManager2 gm;

    void Start()
    {
        #if UNITY_WEBPLAYER
        for(int i = 0;i<2;i++){
            source[i] = this.gameObject.AddComponent<AudioSource>();
            source[i].volume = 0.71f;
        }

        foreach(string name in clipNameList)
        {
            //AudioClip newClip = Resources.Load("bounce/"+name,typeof(AudioClip)) as AudioClip;
            GameObject obj = GameObject.Find(name + " (1)");

            if(obj == null)
            {
                Debug.LogWarning("obj null " + "name");
            }

            AudioSource newClip = obj.gameObject.GetComponent<AudioSource>();

            if(newClip == null)
            {
                Debug.LogWarning("null " + "bounce/"+name);
            } else {

                //Debug.Log(name);
                clipArray.Add(name,newClip.clip);
            }
        }

        #else
        source = this.gameObject.AddComponent<CriAtomSource>();
        #endif

再生部分

AudioSourceは2つくらいにした。(同時に2つしか鳴らないけどまぁいいか)
IDでも名前に変換して呼び出すようにした。

PlayADX2.cs
    /// <summary>
    /// キュー名で再生
    /// </summary>
    /// <param name="name">Name.</param>
    public void Play(string name)
    {
        if (isSequencePlaying)
        {
            quantizePlayCueName = name;
        } else
        {
            #if UNITY_WEBPLAYER
            source[souceCount%2].clip = NameToClip(name);
            source[souceCount%2].Play();
            souceCount++;
            #else
            source.Play(name);
            #endif

        }
    }

    public void PlayId(int id)
    {

        //Debug.Log("PlayId" + id.ToString());
        if (isSequencePlaying)
        {
            quantizePlayCueId = id;
        } else
        {
            #if UNITY_WEBPLAYER
            source[souceCount%2].clip = IdToClip(id);
            source[souceCount%2].Play();
            souceCount++;
            #else
            source.Play(id);
            #endif
        }
    }


AISACとかも呼べないので、

if UNITY_WEBPLAYERで呼ばないようにした

PlayADX2.cs
                    if (ccNumber == 1)
                    {
                        #if UNITY_WEBPLAYER
                        #else
                        source.SetAisac(2, ccValue);    //  filter
                        #endif
                    }
                    if (ccNumber == 2)
                    {
                        #if UNITY_WEBPLAYER
                        #else
                        source.SetAisac(3, ccValue);    //  fx1
                        #endif

#おまけ

おまけ1.実は簡易MMLとして、32分音符固定MMLになってます。

オクターブもないですけど・・・

image

おまけ2.MusicEngineぽいもののの簡易的なものとしてクオンタイズプレイをつけてあります。

シーケンス再生中は16分音符でクオンタイズ再生されます。

ADX2Play.cs
               if ((beatCount32 % 2) == 0)
                {
                    if (quantizePlayCueName != "")
                    {
                        #if UNITY_WEBPLAYER
                        source[souceCount%2].clip = NameToClip(quantizePlayCueName);
                        source[souceCount%2].Play();
                        souceCount++;
                        #else
                        source.Play(quantizePlayCueName);
                        #endif
                        quantizePlayCueName = "";
                    }
                    if (quantizePlayCueId != 999)
                    {
                        #if UNITY_WEBPLAYER
                        source[souceCount%2].clip = IdToClip(quantizePlayCueId);
                        source[souceCount%2].Play();
                        souceCount++;
                        #else
                        source.Play(quantizePlayCueId);
                        #endif
                        quantizePlayCueId = 999;
                    }
                }

おまけ3.MidiJackをデバイスごとに受け取れるように変更

ただ、iOSとかWEBPLAYERだと読んだ時に止まってしまうようなので回避もしてる。

ADX2Play.cs
   void Update()
    {
        uint playerDeviceId = 0;
        #if UNITY_WEBPLAYER || UNITY_IOS
        #else
        switch (gm.turn)
        {

            case 1:
                playerDeviceId = MidiDriver.Instance.connectedSourceArray [MidiDriver.Instance.connectedSourceArray.Count - 1];
                break;
            case 2:
                playerDeviceId = MidiDriver.Instance.connectedSourceArray [MidiDriver.Instance.connectedSourceArray.Count - 2];
                break;

        }
        #endif

        #region padInput
        for (int noteNumber = 0; noteNumber < 128; noteNumber++)
        {
            if (playerDeviceId > 0)
            {

                if (MidiMaster.GetKeyDown(playerDeviceId, noteNumber))
                {
                    //Debug.Log("noteNo" + noteNumber.ToString());

                    if (noteNumber >= 36 && noteNumber < 36 + 16)
                    {
                        // Scene1
                        this.PlayId(noteNumber - 35);
                    }
                }
            }
        }
        #endregion

終わりに

ADX2LEをプロトタイプとして使っていて、
今回みたいに未対応プラットフォーム(Webプレーヤーとか)だった場合に、
ADX2LEを複数波形の管理ツールとして使うのもありかもと思った。
(ボリューム調整やコメントつけたり、名前変更とかも楽だし。)
Unityのマルチシーンロード機能を使えば、
「シーン=キューシート」と見たてて、複数オーディオのパッケージとして、シーンを作成していくとかできそう。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1