본문 바로가기

프로그래밍/libGDX

[libGDX] PCM으로 오디오 녹음/재생하기

PCM (Pulse code modulation: 펄스 부호 변조)

!! 잠깐, 잠깐!! 어려운 내용이 아닙니다. 생소한 단어가 나왔다고 해서 뒤로가지 말아주세요.

PCM은 아날로그 신호의 디지털 표현입니다. 배열을 하나 만들어서 시간에 따른 신호 데이터를 집어 넣은 것입니다. 오디오 포맷 중에서 압축 되지 않은 포맷인 Wav 포맷은 PCM 데이터에 메타 데이터만 추가된 형태입니다. 다시 말하면 PCM이 오디오 포맷의 가장 기초적인 형태라고 할 수 있습니다.


아날로그 신호를 PCM로 변환한 모습


PCM은 2가지 형태를 가지고 있습니다. 하나는 16-bit signed 형식이고, 다른 하나는 32-bit float 형식입니다. 32-bit가 용량을 많이 먹지만 그 만큼 정확도가 높습니다. 두 형식 모두 일반적으로 사용됩니다. 자바에서는 16-bit signed PCM은 short[]로 나타낼 수 있고, 32-bit float PCM은 float[]로 나타낼 수 있습니다.


LibGDX 에서 제공되는 기본적인 오디오 API

LibGDX 에서 PCM을 다룰 수 있는 기능들을 제공합니다. 가장 많이 쓰일만한 API들은 녹음과 재생입니다. 이번에는 LibGDX를 이용하여 오디오를 녹음하고 녹음이 끝난 후 녹음된 오디오를 재생해 보도록 하겠습니다.

Audio Recorder

LibGDX에서 오디오 녹음을 하기 위해서는 먼저 Audio Recorder를 만들어야 합니다. 그리고 그 device에서 readSamples만 호출하면 알아서 잘 녹음이 됩니다. 별 다른 코드를 작성하지 않아서 매우 쉽게 녹음이 됩니다. (LibGDX 버전에 따라 메쏘드 이름이 readSamples 일 수도 있고, read 일 수도 있습니다.

AudioRecorder recorder = Gdx.audio.newAudioRecorder(22050, true);
short[] shortPCM = new short[22050 * 5];
recorder.readSamples(shortPCM, 0, shortPCM.length)

여기서 device를 만들때 첫번째 인자로 22050을 넣은 것을 확인할 수 있습니다. 이 말은 1초동안 들어온 오디오 아날로그 신호는 22050개의 디지털 신호로 저장한다는 것입니다. 이 숫자가 커질수록 정교하게 소리를 녹음할 수 있지만 용량이 커집니다. 일반적으로 22050 또는 44100를 사용합니다.

readSamples 메쏘드는 3개의 인자를 받습니다.

  • 읽어온 PCM 샘플을 저장할 배열 (read Samples는 16-bit signed PCM으로 읽어오기 때문에 short[]를 넣어 주어야 합니다.)
  • 배열에서 쓰기 시작할 위치
  • 읽어올 PCM 샘플 크기

위의 예제에서는 shortPCM의 크기를 22050 * 5 으로 설정해 주었습니다. 즉, 5초동안만 녹음을 하겠다는 것입니다. 만약 shortPCM의 크기를 22050 * 10 으로하면 10초동안녹음을 하게 됩니다.


Audio Player

녹음은 했으나 제대로 녹음이 됬는지 확인해보지 않았습니다. 이번에는 PCM 데이터를 재생해보도록 하겠습니다. PCM 데이터를 재생하는 API는 MP3, OGG 파일과 같은 음악 파일을 재생하는 것과 API가 다릅니다.

먼저 녹음을 했을때와 비슷하게 Audio Device를 만들어 줍니다. (위에서는 Audio Recorder이고 여기서는 Audio Device입니다.) 그리고 나서 readSamples와 비슷하게 writeSamples 메쏘드를 호출해 주면 해당 PCM 데이터를 재생합니다. 위에서 shortPCM의 크기를 22050 * 5 으로 설정해 두었으니 5초동안 재생될겁니다.

AudioDevice device = Gdx.audio.newAudioDevice(22050, true);
device.writeSamples(shortPCM, 0, shortPCM.length);


녹음과 재생을 해 보았습니다. 어렵지 않지요? 녹음한 파일을 인코더를 이용하여 mp3나 ogg 파일로 저장할 수 도 있습니다. LibGDX를 이용해서 크로스플랫폼 녹음기를 만들 수 있는 것이지요! (이 참에 진짜 녹음 앱이나 만들어 볼까?)

완성된 자바 파일은 여기를 클릭해서 다운받을 수 있습니다.


PCM 활용

PCM 데이터를 활용할 수 있다는 것은 오디오 신호를 직접 다룰 수 있다는 것은 거의 모든 오디오 프로세싱이 가능하다는 것입니다. 이퀄라이저를 만들 수도 있고, 스펙트럼 비쥬얼라이저를 만들 수도 있습니다. 특히나 LibGDX에서 Extension 패키지 중에 Gdx-audio 라이브러리에는 FFT (Fast Fourier Transform) 관련 메쏘드들도 있어서 오디오 신호에서 특정 파장을 뽑아낼 수도 있습니다. 오디오 프로세싱에 관한 지식이 조금 필요하겠지만, 조금만 배우면 오디오와 관련된 기능들을 구현할 수 있을것 같습니다. 아래는 LibGDX에 내장된 FFT 클래스를 이용해서 오디오 파장대를 뽑아내서 Visualization으로 만든 것입니다.


LibGDX로 만든 spectrum visualizer



마치면서

이번 포스팅은 LibGDX로 할 수 있는 새로운 분야를 소개하는 것이 목적이었습니다. LibGDX는 단순한 게임 프레임워크가 아니라 내장되어 있는 라이브러리들을 잘 활용하면 퀄리티 높은 크로스플랫폼 앱을 개발할 수 있는 훌륭한 프레임워크입니다. 이번 포스팅에서 볼 수 있듯이 기본적인 오디오 프로세싱 관련 라이브러리들이 있어서 LibGDX를 이용한 오디오 관련 앱을 만들 수 있습니다. 앞으로도 LibGDX의 여러 활용 분야를 살펴볼테니 기대해주세요.