본문 바로가기

프로그래밍/cocos2d

AudioToolbox를 이용하여 효과음 내기 (Singleton 사용)

작업 할 파일은 다음과 같습니다.

(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 파일을 추가합니다.