Cocos2d-x v3にCriket Audioを導入するまで

Pocket

criket

掲題の通りです。
cocos2d-xにはAudioEngineとSimpleAudioEngineという二つのオーディオ制御モジュールが存在しますが、いずれもそれぞれ機能として不十分に感じたため、軽い制約で無料で使用できるCriket Audioを導入することにしてみたので、導入までの備忘としてメモしておきます。

なお、この記事は以下のサイトを参考にしてます。とても詳しく解説してくれてますし、この記事はそれをただぼくの環境用に(本当に備忘として)書き換えてるだけなので、こちらを参考にする方がいいかもです。
Cocos2dxで Cricket Audio を使ってみる

とりあえずぼくの環境とか

環境によってビルド方法とか変わるとも思うんで、先に載せておきます。

  • OS:Mac OS X
  • PC:MacBook Pro (13-inch, Mid 2012)
  • 前提:cocos2d-x v3のプロジェクトが既に作成済

また、フォルダ構成は以下のようにします。

/Users/[アカウント名]
└-> dist
└-> cocos2dprojects
  |  -> 3.10
  |  └-> 今回のプロジェクト
  |     └-> cocos2d-xのプロジェクト
  |        | -> proj.ios_mac
  |        | -> proj.android-studio
  |        └> 以下省略
  └-> tools
     └> Criket Audioを解凍したフォルダ

Criketのアカウント作成&ダウンロード

以下からダウンロードできます。
http://www.crickettechnology.com/free_license

使用する際の規約が載ってますが、ざっくり言うと(きっと)以下のことが書かれてます。

  • (アプリのクレジット画面なんかに) このエンジン使ってること書いてよね!
    • べっ別にこのsvg画像やpng画像使ってくれてもいいんだからね///
  • 他の人に無断配布しちゃダメなんだからね!
  • 他のSDKとかに無断で入れちゃダメだよ!そういうライセンスじゃないんだからね! (もし追加のライセンスオプションがほしいなら…問い合わせしてよね!)
  • アプリリリースする時はここに載せたいからちゃんと報告してよね!
  • もっもしクレジット出したくないならちゃんとお金払ってよね!

この2番目、3番目の理由でcocos2d-xには入ってないんでしょうね。

で、ダウンロードページは一番下のリンクにあります。
アカウント登録も必要なので、登録してダウンロードします。

ZIPファイルを解凍

ダウンロードしたZIPファイルを解凍すると、以下のようなフォルダ構成になってます。

  • binフォルダーーcktoolという専用オーディオファイルを作成するツールを格納
  • buildフォルダーーなんだろね(きっとbuildするフォルダだろうね)
  • docフォルダーードキュメントが入ってます
  • incフォルダーーSDKのヘッダファイルが入ってます
  • libフォルダーー実際に使用するプログラムが入ってます
  • srcフォルダーーサンプルプログラムが入ってます

主に使うのは「bin」「inc」「lib」フォルダです。
とりあえず上記に書いたように配置し、binフォルダにはパスを通しておきます。

// .bash_profile
export CRIKET_ROOT=/Users/[アカウント]/dist/cocos2dprojects/tools/criket-1.6.1/bin/macosx
export PATH=$CRIKET_ROOT:$PATH

iOS側の設定

Frameworkの追加

General -> 「Linked Frameworks and Libraries」から追加します。add_framework

追加するものは以下の通りです。

  • CoreMedia.framework
  • AVFoundation.framework
  • MediaPlayer.framework

Header Search Pathsを追加

Build Settings -> Header Search Pathsに、解凍したファイルの「inc」フォルダまでのパスを追加します。

add_header

Library Search Paths内にモジュールを追加

同様に、Build Settings -> Library Search Paths 内に、以下のパスを追加します。

【Debug】「Clicket Audioフォルダ/lib/ios/Debug」
【Release】「Clicket Audioフォルダ/lib/ios/Release」

Other Linker Flagsの設定

Build Settings -> Linking -> Other Linker Flags内に以下を追加します。

「-lck」

とりあえずこの時点でビルドしてみて、特にエラーにならなければ(たぶん)大丈夫です。

Android側の設定(Android Studio)

こういう類の設定でいつもめんどっちいのがAndroid側ですね。
今回もその例に漏れずにめんどくさいのですが、サンプルもあるのでそれを見ながらだとたぶんできると思います。

JNIファイルの作成

以下のようなファイルを作成します。

#include <jni.h>

#ifndef __ANDROID_JNI__
#define __ANDROID_JNI__
#ifdef __cplusplus
extern "C" {
#endif
        
        JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_initCricket(JNIEnv *, jobject obj, jobject thiz);
            
#ifdef __cplusplus
}
#endif
#endif //__ANDROID_JNI__
#include "CriketJni.h"
#include "ck/ck.h"
#include "ck/config.h"

JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_initCricket(JNIEnv *env, jobject obj, jobject thiz) {
        CkConfig config(env, thiz);
        CkInit(&config);
}

Java側との連携

proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java内に以下のように記述します。

package org.cocos2dx.cpp;

import android.os.Bundle;
import android.content.Context;
import org.cocos2dx.lib.Cocos2dxActivity;

public class AppActivity extends Cocos2dxActivity {
    private static native void initCricket(Context context);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AppActivity.initCricket(this.getApplicationContext());
    }
}

Android.mkの修正

続いて、android-studio側のAndroid.mkも同様に修正します。

LOCAL_PATH := $(call my-dir)

#-------------------------------------------------------------
# specify libck as a "prebuilt" static library

include $(CLEAR_VARS)
LOCAL_MODULE := ck

ifeq ($(NDK_DEBUG),1)
LOCAL_SRC_FILES := ../../../../../../tools/cricket-1.6.1/lib/android/ndk/$(TARGET_ARCH_ABI)/debug/libck.a
else
LOCAL_SRC_FILES := ../../../../../../tools/cricket-1.6.1/lib/android/ndk/$(TARGET_ARCH_ABI)/release/libck.a
endif

include $(PREBUILT_STATIC_LIBRARY)
    
#-------------------------------------------------------------

include $(CLEAR_VARS)

$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos)
$(call import-add-path,$(LOCAL_PATH)/../../../Classes)
$(call import-add-path,$(LOCAL_PATH)/../../../Classes/common/libs)
$(call import-add-path,$(LOCAL_PATH)/../../../../../../tools)

LOCAL_MODULE := cocos2dcpp_shared

LOCAL_MODULE_FILENAME := libcocos2dcpp

CPP_FILES := $(shell find $(LOCAL_PATH)/../../../Classes -name *.cpp)
CPP_FILES += $(shell find $(LOCAL_PATH)/../../../Classes -name *.c)
LOCAL_SRC_FILES := hellocpp/main.cpp
LOCAL_SRC_FILES += $(CPP_FILES:$(LOCAL_PATH)/%=%)

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../Classes
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../Classes/common/libs
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../../../../tools/cricket-1.6.1/inc 

# _COCOS_HEADER_ANDROID_BEGIN
# _COCOS_HEADER_ANDROID_END


LOCAL_STATIC_LIBRARIES := cocos2dx_static
LOCAL_STATIC_LIBRARIES += crypto ssl
LOCAL_STATIC_LIBRARIES += ck cpufeatures


# _COCOS_LIB_ANDROID_BEGIN
# _COCOS_LIB_ANDROID_END

include $(BUILD_SHARED_LIBRARY)

$(call import-module,.)
$(call import-module,openssl/Android)
$(call import-module,android/cpufeatures)

# _COCOS_LIB_IMPORT_ANDROID_BEGIN
# _COCOS_LIB_IMPORT_ANDROID_END

ハイライト部分がCriketとの連携用の記述です。
やたらと「../」が多いですが、それは上に書いたようなフォルダ構成にしてるからです。
はっきり言ってわかりづらいのでこんなフォルダ構成にはしないほうがよさげですね。バージョン管理もしづらそうだし。

あとは、ビルドしてみてエラーにならなければたぶんうまくいってます。

cktoolでcriket用の音楽ファイルを作成してみる。

とりあえず、環境ができたら次はリソースを作ってみます。
基本的にはwavファイルしか対応してないみたいですので、以下のソフトを使ってmp3などは先にwavファイルに変換します。
http://www.audacityteam.org/
(素材を使う場合は加工OKかどうか確かめてからね)

効果音の作成

複数の音楽ファイルを一つにして使うみたいです。
音楽ファイルと同様の部分に、XMLファイル(拡張子:ckbx)を作成します。

<?xml vertion="1.0" encoding="utf-8" ?>
<bank name="soundEffect">
    <sound name="shot" source="ファイル名.wav"/>
</bank>

あとは、ビルドします。

$ cktool buildbank soundeffects.ckbx

すると、soundeffects.ckbというファイルが出来上がります。これが利用するリソースになります。

BGM用ファイルの作成

こちらはひとつずつやるみたいです。
こちらもwabに変換してから行います。

$ cktool buildstream -format adpcm bgm1.wav bgm1.cks

ただ、BGM(ストリーム再生)用のは、そのままmp3などの状態でも使用できるみたいです。

使ってみる

さて、ここまできたら後は使うだけですね。

初期化とか

AppDelegate等に以下のように入れます。

#include "ck/bank.h"
#include "ck/ck.h"
#include "ck/config.h"
#include "ck/sound.h"
// その他は省略

bool AppDelegate::applicationDidFinishLaunching() {
   // (省略)
#if CK_PLATFORM_ANDROID
   // Androig側はAppActivityにて実施
#else
   // 
   CkConfig config;
   CkInit(&config);
#endif
   // (省略)
   // 毎回Updateを呼び出す
   // これを呼び出さないと再生とかされません。
   auto schedule = Director::getInstance()->getScheduler();
   schedule->schedule([](float f) { 
          CkUpdate(); 
    }, this, 0.016, CC_REPEAT_FOREVER, 0.0, false, "sounds");
}

void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();
    // 全てのサウンドを止める
    CkSuspend();
}

void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();
    // 全てのサウンドを再開
    CkResume();
}

AppDelegate::~AppDelegate() {
    // シャットダウン。
    // 実際はここではなくアプリ終了するメソッドなどを作成してやる方がいいと思ふ。
    CkShutdown();
}

実際に使う

こんな感じに使います。

// 効果音の初期化
CKBank* bank = CkBank::newBank("soundeffects.ckb");

// 効果音を出す
CKSound* sound = CkSound::newBankSound(m_bank, "shot");
sound->play();

// BGMを流す
CKSound* bgm = CkSound::newStreamSound("bgm.cks");
bgm->play();
bgm->setLoopCount(-1);

なお、使い終わったらそれぞれ自分で解放する必要があります。

// 解放する
bgm->destroy();
sound->destroy();
bank->destroy();

このようにメモリ管理も自分でしないといけないので、
AudioManagerクラスみたいにそれぞれのインスタンスを管理するクラスを作成したほうがいいですね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です