C#でマルチプラットフォームに音声を再生するライブラリとしてSharpAudioというものがあります。
今回はこのライブラリをMacOSで動かそうとしてとても苦労したので、解決法を備忘録として雑に書きます。
環境
CPU Apple M3
MacOS 14.4.1
SharpAudio 1.0.65-beta
SharpAudio.ALBinding 1.0.65-beta
バグ発生!
using SharpAudio;
var engine = AudioEngine.CreateDefault();
var buffer = engine.CreateBuffer();
var source = engine.CreateSource();
// Play a 1s long sound at 440hz
AudioFormat format;
format.BitsPerSample = 16;
format.Channels = 1;
format.SampleRate = 44100;
float freq = 440.0f;
var size = format.SampleRate;
var samples = new short[size];
for (int i = 0; i < size; i++)
{
samples[i] = (short)(32760 * Math.Sin((2 * Math.PI * freq) / size * i));
}
buffer.BufferData(samples, format);
source.QueueBuffer(buffer);
source.Play();
GitHubのreadmeにある例を動かそうとすると、4行目で
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
というようなエラーが出ます。
var engine = AudioEngine.CreateDefault();
のところでAudioEngineのインスタンス生成がうまくいかず、次の行でNull~という状態です。
原因
OpenALのライブラリをSharpAudio.ALBindingが読み込むときにOpenALライブラリが見つからなかった場合、例外が出ずにそのまま進んでしまうようです。
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
names = new[]
{
"/usr/local/opt/openal-soft/lib/libopenal.dylib",
"libopenal.dylib",
"soft_oal.so"
};
}
SharpAudio.ALBindingは、MacにOpenALがインストールされていればそれを、無ければ実行ファイルと同じ階層にあるダイナミックライブラリを参照するようです(最後の一個はよくわからない)。
解決?方法
おそらくOpenALをインストールすれば治りそうですが、私の環境ではどうしてもOpenALをインストールできなかったので、実行ファイルと同じフォルダにlibopenal.dylibを配置する作戦でいくことにしました。
libopenal.dylibは結構使われているようなのでそこからコピーしてきます。Minecraftとかに入ってるみたいですね。
私は以下リンクのファイルを改名して使いました。
https://github.com/MonoGame/MonoGame.Dependencies/blob/master/openal-soft/MacOS/Universal/libopenal.1.dylib
ただこれだとアプリを配布する際に同梱するわけにもいかないので、また考えないといけませんね。
ライセンスが許すならば自前でビルドして同梱したり、インストール時にビルドスクリプトを走らせるとかになるのでしょうか。
これでエラーが出ず、正常に再生されるようになりました。