티스토리 뷰

반응형

안녕하세요 :) Zedd입니다.

네..............리젝이 벌써 4번째인가요..?네.....다른앱을 만들어야 하는지 ㅠㅠㅠ 열심히 만든건데..

이것때문에 하루종일 메일함만 들여다보고 있네요 XD....

이제 iOS글도 좀 써야겠습니다. 화이팅!!


오늘은 간단하게 local에 있는 오디오파일을 재생하는 법을 알려드릴거에요 XD

저는 용량도 작고 아주 짧아서 (2초?) 이렇게 local에 넣었거든요..!

만약 용량도 크고 막 그러시면 이렇게 local에 넣는건 좋지 않은 것 같아요. 사용자들이 앱을 무겁다고 생각할 수 있으니까요 :)



 local에 있는 오디오 파일 재생하기



가장 먼저 해야할일은...오디오쪽을 전부 맡고 있는 아주 기특한 프레임워크...

import AVFoundation

AVFoundation을 import해주셔야 합니다 XD

그리고! 클래스 바깥에 

var soundEffect: AVAudioPlayer?

AVAudioPlayer타입의 인스턴스를 만들어주세요 :)

간단하게 AVAudioPlayer가 뭔지 설명하면...이름만봐도 "오디오 재생기?.."인 것 같죠?

네! 맞아요. 이 아이는 파일이나 메모리의 오디오 데이터를 재생하는 것을 담당해요.

Apple은 네트워크 스트림에서 캡쳐한 오디오를 재생하거나, 매우 낮은 I/O대기시간을 필요로 하지 않는 오디오를 재생하는데, 이 AVAudioPlayer을 사용하는 것을 권장(추천)하고 있어요.

AVAudioPlayer가 할 수 있는 일은

  • Play sounds of any duration

  • Play sounds from files or memory buffers

  • Loop sounds

  • Play multiple sounds simultaneously, one sound per audio player, with precise synchronization

  • Control relative playback level, stereo positioning, and playback rate for each sound you are playing

  • Seek to a particular point in a sound file, which supports such application features as fast forward and rewind

  • Obtain data you can use for playback-level metering



이만큼이나 있네요!!

자..아무튼 다음으로 넘어가볼게요. 

ViewController 안에 함수를 하나 만들거에요. 

 let url = Bundle.main.url(forResource: "athena", withExtension: "mp3")

        if let url = url{


            do {

                //code

            } catch let error {

                print(error.localizedDescription)

            }

        }

    }

자..가장 먼저 해야 할 일은 우리가 재생해야할 오디오를 "찾는 것"이에요.

저번에 우리 local에 있는 JSON을 찾을때도, Bundl.main.~을 사용했죠. 자세한건 <JSON 파싱 - iOS편>를 참고해주세요.

저는 athena라는 이름을 가지고, 그 확장자가 mp3인 것을 재생할거에요. 

이렇게 "athena.mp3"라는 파일을 앱이 찾으면, 이제 do-catch문을 수행할겁니다. 

url은 옵셔널타입을 반환하기 때문에, 해당 오디오 파일이 없으면 url에는 nil이 들어가게 됩니다.


let url = Bundle.main.url(forResource: "athena", withExtension: "mp3")!

이렇게 강제 언래핑으로 하면 if let구문이 없어도 되겠지만, 만약 해당 오디오 파일이 없다면 fetal error를 내게 됩니다. 

옵셔널 시간에 배웠었죠? 값이 반드시 있다고 확신할 수 있을때만 !을 쓰자구요! 일단 저는 if let으로 한번 바인딩을 해줬어요 :)

 

자 다음!


do {

    soundEffect = try AVAudioPlayer(contentsOf: url)

guard let sound = soundEffect else { return }

sound.prepareToPlay()

sound.play()

  }

저 do안에는 이러한 코드가 들어가게 되는데요.

위에서 선언해준 AVAudioPlayer의 인스턴스인 soundEffect가 보이네요.

soundEffect에, 우리가 local에서 찾은 오디오 파일의 url을 넘겨주는 것을 볼 수 있네요.

(여기서 url에 있는 모든 데이터는 CoreAudio에서 이해할 수있는 오디오 파일 형식이어야합니다.)


throws가 붙어있기 때문에, try로 감싸줘야 해요 :) 


그리고 sound에 soundEffect를 guard 구문을 통해 넣어준 것을 볼 수 있어요. 

그리고.. play가 두개가 나옵니다. 

sound.prepareToPlay()


sound.play()

자..위에거는 재생을 "준비"하는 것 같고, 밑에거는 비로소 "재생"을 하는 것 같네요. 

맞습니다!

prepareToPlay()는 버퍼를 미리 로드하여 재생할 오디오 플레이어를 준비합니다. 

prepareToPlay()를 호출하면, 버퍼를 미리 로드하고 재생에 필요한 오디오 하드웨어를 가져오므로, play()메소드를 호출하는 시점과 사운드 출력을 시작하는 시점사이의 지연을 최소화합니다.

stop()메소드를 호출하거나, 사운드 재생을 종료하려고 하면 설정을 취소합니다. prepareToPlay()는 성공했으면 true를, 실패했으면 false를 반환합니다. 


play()메소드에 대한 설명도 볼까요?

비동기적으로 사운드를 재생합니다. 오디오 플레이어가 아직 재생 준비가 되어있지 않으면, 이 메소드를 호출하면 암시적으로 prepareToPlay()메소드가 호출됩니다.

성공하면 true, 실패하면 false를 반환합니다.


헐 play()메소드말이죠..굉장히 흥미롭네요. 아직 재생 준비가 안되어있으면 알아서 prepareToPlay()를 호출한다니.. 

실제로 prepareToPlay()를 주석처리해도 사운드 재생이 잘 되네요..!!!


밑에 catch 구문은


soundEffect = try AVAudioPlayer(contentsOf: url)

여기서 나오는 에러를 받는 catch문이겠죠?ㅎㅎ 


AVFoundation에 있는 아이들은 참 대단한 것 같아요...!

아무튼 오늘은 이렇게 간단한? local에 있는 오디오파일 재생하는 법을 알아봤어요 :)

전체코드는 밑에 넣어둘게요 :)

도움이 되었길 바라며 ㅎㅎㅎㅎ 안녕!!

반응형