サウンドを再生する

iPhoneアプリ内に短い効果音のようなものを入れたい場合のサンプルコードです。

まずは、サウンドを扱うために AudioToolbox.framework をプロジェクトに追加します。
Xcode 3.x系では左ナビのFrameworksを右クリックして追加でしたが、Xcode 4.xからちょっと複雑になりました。

AudioToolbox.frameworkの追加

左ナビのプロジェクト名をクリックし、TARGETSを選択、Build Phasesのタブの中にあるLink Binary With Librariesの+ボタンをクリックしてAudioToolbox.frameworkを追加します。

続いて、音を鳴らすためのサウンドIDを定義し、音を鳴らしたい部分にサウンド再生の記述を行います。

具体的には、projectnameViewController.mに以下の記述を追加します。

SystemSoundID tapSoundID;

-(void) playSound{
#define BufferSize 1000
	int r = arc4random() % 2;
	CFStringRef str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), r);

	CFBundleRef mainBundle;
	CFURLRef soundURL;
	CFMutableStringRef cfFileName;
	UniChar *myBuffer;
	myBuffer = malloc(BufferSize * sizeof(UniChar));
	cfFileName = CFStringCreateMutableWithExternalCharactersNoCopy(NULL, myBuffer, 0, BufferSize, kCFAllocatorNull);
	CFStringAppend(cfFileName, CFSTR("sound_"));
	CFStringAppend(cfFileName, str);

	mainBundle = CFBundleGetMainBundle ();
	soundURL  = CFBundleCopyResourceURL (mainBundle,cfFileName,CFSTR ("aif"),NULL);
	AudioServicesCreateSystemSoundID (soundURL, &tapSoundID); 
	CFRelease (soundURL);
	AudioServicesPlaySystemSound (tapSoundID);

	CFRelease(cfFileName);
	CFRelease(str);
	free(myBuffer);
}

この例では、rに0か1がランダムでセットされますので、sound_0.aifまたはsound_1.aifが再生されます。
当然ですが、projectnameViewController.hには、

#import <AudioToolbox/AudioServices.h>
-(void) playSound;

を定義しておきましょう。

多くのブログなどで紹介されているコードが以下ですが、現時点の最新版であるXcode 4.2ではNSObjectとCFObjectの変換ができずエラーが発生してしまいます。
これは、iOS5から実装されるARCの関係で、NSは自動メモリ解放の対象となっているが、CF(Core Foundation)は自動メモリ管理の対象外となるためのようです。

NSURL*  url;
url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sound_0" ofType:@"aif"]];
AudioServicesCreateSystemSoundID((CFURLRef)url, &tapSoundID);

この例ですと、3行目の(CFURLRef)の部分でエラーとなります。

サンプルコード

Sound Test (Zipファイル 95,661B)
サンプルでは動作を確認しやすいようにIBActionとしてplaySoundをボタンアクションに割り当ててあります。
サウンドファイルは含まれていませんので、sound_0.aifとsound_1.aifをプロジェクトに設定の上、ご確認ください。

カテゴリー: 実例ノウハウ集   パーマリンク

サウンドを再生する への10件のコメント

  1. kiki より:

    こんにちは。

    音のランダム再生のコードを探していて辿り着きました。
    上記コードを試した所
    07の行でwarning:initialization makes pointer from integer without a castの警告が出現してしまい効果音が鳴らないです。

    よろしければ、解決方法を教えてもらえないでしょうか?
    よろしくお願いします。

    • jun より:

      手元にこれを書いたときに組んだコードが無いので、まだ再現できていませんが、型が一致しないポインタからの代入ですので、変数rの扱い方に間違いがあるのかもしれません。
      サウンドファイルのファイル名が決まっているのであれば、
      CFStringRef cfPath = “sound_1″;
      のような形では解決できないでしょうか。(上記の場合はsound_1.aif)

  2. kiki より:

    上記コードにて試してみた所、playSound内でコードを書くと音が出なく、viewDidLoad内にコードを実装すると同じ音が出るという、同じ状態でした。
    ちなみに、arc4random() % 2の場合はsound_1が再生され、arc4random() % 1の場合はsound_0が再生されるみたいです。

    なかなか難しいですね。

    • jun より:

      その現象がこちらでは再現しないんですよね。。
      didLoadに書くということは、一度鳴って終わりですよね。
      arc4random() % 2とarc4random() % 1の挙動についても不思議ですので、NSLogなどで出力結果を確認してみてください。
      念のため、こちらで動作しているサンプルコードを追加しておきました。

  3. kiki より:

    サンプルコード、ありがとうございます。
    サンプルを元になんとかランダムで再生させることができました。本当にありがとうございます!

    結果として音を出すことには成功したのですが、ダメだった過程を追記しておきます。

    私の使っていたコードも、junさんと同じようにIBでアクションのあるHELLO WORLDだったのですが、playSound内にコードを使った場合は結局再生されることがなかったです。

    そして、viewDidLoadにコードを入れたのですが、viewDidLoad内での立ち上がり時の再生でも、AudioServicesPlaySystemSound (tapSoundID);をIBAction内に入れた時両方とも、同一の音のみ再生されるという感じでした(コンソールでのログは正常に動いていました)。

    最後にサンプルコードと同じように、直接IBActionにコードを実装すると、ランダムで再生ができました。
    文字を打ち込めるだけのシンプルなコードだったので、何が原因だったのか不思議です。

    とにかく、無事にランダム再生が作れました。長々とご教授いただき本当にありがとうございました。
    ためになるブログをこれからもお願いします!

  4. mura より:

    3行目の(CFURLRef)の部分でエラー は、
    (__bridge CFURLRef) 
    で解決できませんか?

コメントを残す

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

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>