(1) SoundManager.h
(2) SoundManager.m
(3) GameLayer.m
//
// SoundManager.h
// GameDemo
//
// Created by Chang-Min Pak on 6/12/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@interface SoundManager : NSObject {
// 만들어진 SystemSoundID를 재사용하기 위해 보관할 dictionary
NSMutableDictionary *soundIDDic;
}
@property (nonatomic, retain) NSMutableDictionary *soundIDDic;
// Singleton을 만듭니다.
+ (SoundManager *)sharedSoundManager;
- (void) playSystemSound:(NSString*)fileName fileType:(NSString*)type;
@end
(1) 시스템 사운드와 관련된 API를 사용하고자 AudioToolbox/AudioToolbox.h 파일을 임포트 했습니다.
(2) 만들어진 SystemSoundID를 보관할 NSMutableDictionary를 정의 했습니다.
(3) SoundManager 객체를 받기 위해서 sharedSoundManager 메소드를 사용합니다.
//
// SoundManager.m
// GameDemo
//
// Created by Chang-Min Pak on 6/12/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "SoundManager.h"
@implementation SoundManager
@synthesize soundIDDic;
// Singleton
static SoundManager *_sharedSoundManager = nil;
+ (SoundManager *)sharedSoundManager {
@synchronized([SoundManager class]) {
// 아직 객체가 만들어지지 않았다면 init 메소드를 호출하여
// 새로 만든다.
if (!_sharedSoundManager)
[[self alloc] init];
return _sharedSoundManager;
}
// 컴파일러 에러를 막기위해 추가
return nil;
}
+ (id) alloc {
@synchronized([SoundManager class]) {
_sharedSoundManager = [super alloc];
return _sharedSoundManager;
}
// 컴파일러 에러를 막기위해 추가
return nil;
}
- (id) init {
if( (self = [super init]) ) {
// SystemSoundID를 보관할 Dictionary를 만든다.
NSMutableDictionary *tmpDic = [[NSMutableDictionary alloc] initWithCapacity:20];
self.soundIDDic = tmpDic;
[tmpDic release];
}
return self;
}
- (void) playSystemSound:(NSString*)fileName fileType:(NSString*)type {
@try {
// 넘어온 파일 이름으로 만들어진 소리가 dictionary에 이미 들어있는지 확인한다.
NSNumber *num = (NSNumber*) [self.soundIDDic objectForKey:fileName];
SystemSoundID soundID;
// 없다면 새로 만든다.
if(num == nil) {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *path = [mainBundle pathForResource:fileName ofType:type];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
// 만들어진 SystemSoundID를 dictionary에 추가한다. 파일이름이 키(key)로 사용된다.
num = [[NSNumber alloc] initWithUnsignedLong:soundID];
[self.soundIDDic setObject:num forKey:fileName];
}else {
// 같은 파일이름이 존재한다면 사용한다.
soundID = [num unsignedLongValue];
}
// sound ID로 소리를 낸다.
AudioServicesPlaySystemSound(soundID);
}@catch(NSException* e) {
// 혹시 파일을 읽어들일 때 문제가 생길 경우를 대비하여
// exception을 적절히 처리한다.
NSLog(@"Exception from playSystemSound: %@ for '%@'", e, type);
}
}
- (void) dealloc {
// dictionary에 보관중이던 SystemSoundID를 릴리즈 한다.
if(self.soundIDDic != nil && [self.soundIDDic count] > 0) {
NSArray *IDs = [self.soundIDDic allValues];
if(IDs != nil) {
for(NSInteger i = 0; i < [IDs count]; i++) {
NSNumber *num = (NSNumber*) [IDs objectAtIndex:i];
if(num == nil)
continue;
SystemSoundID soundID = [num unsignedLongValue];
AudioServicesDisposeSystemSoundID(soundID);
}
}
}
[soundIDDic release];
[super dealloc];
}
@end
(1) 클래스 메서드인 sharedSoundManager와 같이 사용할 정적 변수로 _sharedSoundManager를 사용합니다. 이 변수가 새로 만들어질 SoundManager 객체를 보관합니다.
(2) sharedSoundManager 메서드는 클래스 메서드 이므로 SoundManager 클래스 이름만으로 호출되며, SoundManager 객체를 돌려줍니다.
(3) NSMutableDictionary 에는 NSObject 클래스 또는 NSObject를 상속받는 클래스 객체만 추가될 수 있습니다. SystemSoundID 자체를 바로 추가할 수 없기 때문에 NSNumber 형태로 변환한 후에 집어넣습니다.
//
// GameLayer.m
// GameDemo
//
// Created by cmpak on 5/10/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "SoundManager.h"
[[SoundManager sharedSoundManager] playSystemSound:@"soundKick" fileType:@"aif"];
(1) 프로젝트 내에 sound 파일을 추가합니다.