Flat Leon Works

アプリやゲームを作ってます。

ALURE(OpenALユーティリティ)をiOSで使う

クロスプラットフォームなゲーム開発で音を鳴らすにはOpenALが定番っぽいです。MacWindowsiOSAndroidで利用可能だそうで。しかしOpenALだけではwavファイルなどの音声ファイルを扱うことができません。そこで良さげなのがOpenALのユーティリティライブラリであるALUREです。wavファイルはもちろん、Ogg VorbisFLACなどにも対応しています。

しかし、このALUREをiOSで使うための情報が見つからなかったので結構苦労しました。なので記事にまとめておこうと思います。

記事執筆時の環境

iOSOpenAL+ALUREを使う

OpenALの準備

iOSでは最初からOpenALが利用可能なので、XcodeのプロジェクトのLinked Frameworks and LibrariesOpenAL.frameworkを追加するだけで良いです。

ALUREの準備

いろいろ模索した結果、以下の手順になりました。ただし、ビルド周りは詳しくないので不正確な可能性があります。ご注意を。

  • ALURE公式サイト」からソースコード一式を入手
  • ALUREのビルドにはCMakeが必要なので、まだCMakeを入れていない場合は「CMake公式サイト」からバイナリを入手。dmgを展開してアプリをアプリケーションフォルダなどへ置く。ちなみにCMakeはMakefileを生成するためのツールです。
  • https://github.com/cristeab/ios-cmake」からCMakeのiOSツールチェインファイルを入手します。
  • この中のiOS.cmakeの一部を修正します。(私の環境では修正しないとCMakeの実行に失敗しました)

修正前

include (CMakeForceCompiler)
CMAKE_FORCE_C_COMPILER (/usr/bin/gcc Apple)
CMAKE_FORCE_CXX_COMPILER (/usr/bin/g++ Apple)

修正後

set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang")
set(CMAKE_CXX_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++")
  • ターミナルでALUREソースコード一式内のbuildディレクトリに移動して、以下を実行。「iOS.cmakeのファイルパス」は各々で書き換えてください。実行に成功するとMakefileが作られます。
/Applications/CMake.app/Contents/bin/cmake .. -DCMAKE_TOOLCHAIN_FILE=iOS.cmakeのファイルパス
  • makeを実行。libalure-static.aなどが生成されます。
  • このlibalure-static.aを以下のコマンドで中身を展開。(libalure-static.aファイルを直接リンクさせてもリンクエラーになりました)
ar -x libalure-static.a
  • 展開すると以下のような複数.oファイルが生成されます。
    • alure.o
    • buffer.o
    • codec_aiff.o
    • codec_wav.o
    • istream.o
    • stream.o
    • streamdec.o
    • streamplay.o
  • これらをXcodeのプロジェクトのLinked Frameworks and Librariesに追加します。
  • Xcodeのプロジェクト設定でBitcodeを無効にしておく( ライブラリのビルド時にBitcodeを含めていないのでエラーになる )
    • Build Settings > Build Options > Enable BitcodeNo にする
  • alure.hのパスをプロジェクト設定の Build Settings > Search Paths > User Header Search Pathsなどで設定しておく
  • 生成したALUREライブラリのパスをプロジェクト設定のBuild Settings > Search Paths > Library Search Pathsで設定しておく
  • Xcodeでビルドします。ビルドが成功したら成功です。
  • 実機(iPhoneなど)でちゃんと音が鳴るか確認してみる。

(おまけ)手順を見つけるまでの流れ

上記のような手順になった経緯を参考として残しておきます。

Mac用に生成したALUREライブラリをそのままiOSのプロジェクトに持って行っても当然動きません。まず考えたのがALUREのビルドはCMakeを使っているので、CMakeにiOS用の設定があるんじゃないかということです。探してみたところCMake自体はiOSのビルドに対応していませんでしたが、GithubiOS用にビルドするためのCMakeファイルがあるのを見つけました。これhttps://github.com/cristeab/ios-cmake です。

このファイルを使えばCMake時に以下のようにオプションとして指定することでiOS用ビルドが可能になるとのこと。

cmake .. -DCMAKE_TOOLCHAIN_FILE=../../../toolchain/iOS.cmake -DIOS_PLATFORM=SIMULATOR

試してみたところ、私の環境ではALUREのCMakeを実行するとエラーが発生しました。

CMake Error at CMakeLists.txt:131 (MESSAGE):
  PThreads is required for non-Windows builds!

エラーログ(CMakeError.log)の中身を見ると、ライブラリの存在チェック時になぜかiPhoneSDKではなくMacOSX10.11.sdkなどが使われているようす。ぐぬぬ

いろいろ試してみた結果、iOS.cmakeの以下の場所を修正することでCMakeが成功することがわかりました。

修正前

include (CMakeForceCompiler)
CMAKE_FORCE_C_COMPILER (/usr/bin/gcc Apple)
CMAKE_FORCE_CXX_COMPILER (/usr/bin/g++ Apple)

修正後

set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang")
set(CMAKE_CXX_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++")

この違いがどう違うのかわかりませんが、とにかくこうすることでCMakeが成功するようになりました。ちなみに、CMAKE_FORCE_C_COMPILERからCMAKE_C_COMPILERに変えたのは、CMAKE_FORCE_C_COMPILERが最新のドキュメントで非推奨になっていたからです。https://cmake.org/cmake/help/latest/module/CMakeForceCompiler.html

続いてmakeでビルドします。これは普通に成功し、libalure-static.aが生成されました。

このlibalure-static.aXcodeiOSのプロジェクトのLinked Frameworks and Librariesに追加してビルドします。すると以下のような警告とともにリンクエラーが。

ld: warning: ignoring file ***/Lib/libalure-static.a, file was built for archive which is not the architecture being linked (armv7):

Undefined symbols for architecture armv7:
  "_alureGetErrorString", referenced from:

armv7用のシンボルが見つからないと言われているような。

このリンクエラーの対処法の前に、生成されたlibalure-static.aについて状況を確認したいと思います。

このlibalure-static.aは、内部的には以下のオブジェクトファイルから構成されています。

  • alure.o
  • buffer.o
  • codec_aiff.o
  • codec_wav.o
  • istream.o
  • stream.o
  • streamdec.o
  • streamplay.o

これはarコマンドを使って確認することができます。例:ar -t libalure-static.a

そしてこれらのそれぞれの.oファイルは、armv7armv7sarm64の3つのアーキテクチャのバイナリを合体させたFATバイナリ(universal binary)と呼ばれるものになっています。これはfileコマンドで確認することができます。

$ file alure.o
alure.o: Mach-O universal binary with 3 architectures
alure.o (for architecture armv7):   Mach-O object arm
alure.o (for architecture armv7s):  Mach-O object arm
alure.o (for architecture arm64):   Mach-O 64-bit object

このようにちゃんとarmv7用のバイナリが含まれているのにリンクエラーになってしまっています。

ちなみに、FATバイナリを作るにはlipoコマンドが必要との情報をみかけましたが、ビルドオプションで-arch armv7 -arch armv7s -arch arm64のように-archオプションを複数設定すれば勝手にFATバイナリにしてくれるようです。CMakeではCMAKE_OSX_ARCHITECTURESコマンドで設定したアーキテクチャがビルド時に-archオプションとして渡されるようです。そしてCMAKE_OSX_ARCHITECTURESコマンドはiOS.cmakeによって自動で設定されます。

さて、このリンクエラーを解決するために試しにarコマンドでlibalure-static.aの中身を展開して、それらをLinked Frameworks and Librariesに追加してビルドしてみると…ビルドに成功しました。FATバイナリをアーカイブ化したものはダメなのか、それともアーカイブ化の方法が間違っていたのかよくわかりませんが、とにかくリンクエラーを解決する方法が見つかりました。(解決まで丸2日かかりました)

(おまけ)MacOpenAL+ALUREを使う

ついでにMacでのOpenAL+ALUREの利用方法も紹介しておきます。先にMacでALUREの動作確認をしておくのもいいかもしれません。

OpenALの準備

MacOpenALを使う場合、OpenALは最初から入っているのでビルドオプションで-framework OpenALとするだけで良いです。(もしくはXcodeのプロジェクトのLinked Frameworks and LibrariesOpenAL.frameworkを追加する)

ALUREの準備

ALUREを利用するには以下の手順が必要になります。

  • ALURE公式サイトからソースコード一式を入手
  • ALUREのビルドにはCMakeが必要なので、まだCMakeを入れていない場合はCMake公式サイトからバイナリを入手。dmgを展開してアプリをアプリケーションフォルダなどへ置く。ちなみにCMakeはMakefileを生成するためのツールです。
  • ターミナルでALUREソースコード一式内のbuildディレクトリに移動し、/Applications/CMake.app/Contents/bin/cmake ..を実行。(Makefileが作られる)
  • そのままmakeを実行。(ビルドが走りライブラリファイルが生成される)
  • そのままmake installを実行。(ライブラリファイルなどが/usr/local/libなどに配置される)
  • ビルドオプションで-lalureなどしてリンクする。(もしくはXcodeのプロジェクトのLinked Frameworks and Librariesに追加する)

雑に説明しましたがMacでの利用手順はこんな感じです。