SwiftでOpenALの簡単サンプルソース

今日はiOSアプリ「決めちゃいな!」の改修中になかなか上手く行かなかった、OpenALでの音ファイルの再生について、必要最低限なサンプルソースを紹介します

ルーレットにクリック音をつけたい

今回「決めちゃいな!」のバージョンアップをするに当たって、ルーレットにクリック音(回ってる時にカチカチ鳴る奴)を付けてみようと、思ったわけです。
で、やっぱり最初に使ってみるのがAVFoundationAVAudioPlayerになるのですが、使ってみると意外とレスポンスが悪いんですね。これ。UTも鈍くなりますし、少し遅れてなってる感じですね。バックグラウンドのスレッドで再生しても駄目でしたね。

OpenALが良いらしい

そこで、いろいろググってみたのですが、「OpenAL」が良いとの事で、使ってみることにしました。Appleもゲームアプリ等のレスポンスが必要な物はこれを使う事を推奨しているらしい。
だがしかし・・・使い方をググってもわかりやすいサンプルコードが出てこないんですよね。単純に音を鳴らすだけの、とりあえず・・・最低限これだけ書けば一旦音出るよ・・・みたいなコードがパッと出てこない。結構ちゃんとクラス作ったりしてるサイトはあって・・・最終型としては良いんですけどね・・・いや、多分ググり方が悪いんです・・・英語がちゃんと読めないのも駄目んだんでしょうね。

簡単サンプルソース

最低限これだけ書けば、OpenALで音鳴らせますよってコードを以下に載せておきます。雑なサンプルです。エラーハンドリングもしてなければ、ソースを閉じることもしてません。音を鳴らすというスタートラインに立つだけのソースでございます。
サンプルソースは21行目〜23行目で音ファイルを0バイト目から音ファイルのバイトサイズ分、一気に読み込んでますが、読み込んでバッファに詰めるって所を、ループで回すのが良いんでしょうかね。
ちなみに音ファイルは「.caf」って拡張子のファイルにしてます。参考にしたサイトがそれだったので、そうしていますが、「.aiff」とかからは、コマンドで変換が出来ます。それは、また今度紹介致します。

// OpenALをインポート
import OpenAL

// デバイスを開く
let device = alcOpenDevice(nil)
// コンテキストを作成する
let context = alcCreateContext(device, nil)
alcMakeContextCurrent(context)

// 音ファイルを開く
var fileId: AudioFileID? = nil
let url = URL(fileURLWithPath: Bundle.main.path(forResource: "click", ofType: "caf")!) as CFURL
let result1: OSStatus = AudioFileOpenURL(url, .readPermission, kAudioFileCAFType, &fileId)

// 音ファイルのバイトサイズを取得する
var byteCount: UInt64 = 0
var propertySize = UInt32(MemoryLayout.size(ofValue: byteCount))
let result2: OSStatus = AudioFileGetProperty(fileId!, kAudioFilePropertyAudioDataByteCount, &propertySize, &byteCount)

// 音ファイルを読み込む
var bytesRead = UInt32(byteCount)
let audioData = malloc(Int(bytesRead))!
let result3: OSStatus = AudioFileReadBytes(fileId!, false, 0, &bytesRead, audioData)

// 音ファイルを閉じる
let result4: OSStatus = AudioFileClose(fileId!)

// バッファにデータを詰める
var buffer: ALuint = 0
alGenBuffers(1, &buffer)
alBufferData(buffer, AL_FORMAT_MONO16, audioData, ALsizei(bytesRead), 44100)

// バッファデータをソースに貼付ける
var source: ALuint = 0
alGenSources(1, &source)
alSourcei(source, AL_LOOPING, AL_FALSE) // ループしない設定
alSourcei(source, AL_BUFFER, ALint(buffer))

// ソースを再生する
alSourcePlay(source)

参考サイト

参考にしたのは以下のサイトです。Objective-Cで書かれていますが、一個一個、これするあれするって書かれているので、わかりやすいです。

関連記事

【Swift】日付(Date型)同士の差の取り方

【Swift】UIViewControllerでStatic CellsのTab...

【Swift】'applicationFrame' was deprecated...

【Mac App】Domain=NSURLErrorDomain Code=-1...

【Google Home】Google Homeにテキストを読み上げさせたい【そ...

【Xcode】制約をソースにリンク