으으, 왜 앞의 디지털 오디오 강의는 꽤나 흥미로웠는데 왜 이렇게 의욕이 안 나는지...
어제(12시가 지났으니 정확히는 그제) 하려던 걸 하루 밀려서 오늘에야 다 봤다.
열심히 필기하면서 듣다가, 설치법이 나오는데 이걸 내가 굳이 필기하고 블로그에 정리할 필요가 있나 싶어서 순간 현자타임이.
내가 뭐, 필요해서 다음에 잊어먹을까봐 만드는 거지 떠먹여주려고 만드는 건 아니니까.
어디까지나 내가 다음에 필요할 것 같은 내용만 정리하면 되는거다.
여러번 느꼈지만 설치법은 단순한 거라도 사진찍고 뭐하고 해야하는게 많아서 더럽게 귀찮단 말이지... 뭣보다 이미 올려놨다. ㅎ.
https://blog.naver.com/luku756/221829247921
[NAudio] 외부 라이브러리 사용
음, 솔직히, 됐는데 어떻게 됐는지를 모르겠다... 그래도 약간 아는 거라도 리뷰를 남겨 보도록 하자. 일단...
blog.naver.com
1강이니 만큼, 여기서는 NAduio란 라이브러리가 어떤 라이브러리인지를 알려준다.
약력이라던가, 코드 공개 장소라던가(오픈소스니까) 버전이라던가 등등을 알려주는 것이다. 그리고 뭘 지원하는지를 간략하게 설명한다.
나한테 중요한 건 물론 마지막이다.
(필기하면서 들었는데, 방을 비운 사이에 필기 종이가 바닥에 한장 떨어졌는지 누가 버렸다...ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 아이고...) 다시 쓸 엄두도 안나니까 그냥 대충 넘기자)
API Wrapper
먼저, NAudio 는 기존의 windows가 제공하는 audio api들에 대한 wrapper class를 제공한다고 한다.
위가 옛 버전의 api이다. (필기한 걸 잃어버린 부분ㅠ)
wave로 시작하는 api들이 있다. waveOutPlay, waveOutOpen, waveOutClose. waveIn 등. 오디오를 녹음하고 재생하기 위한 클래스이다. NAudio에서는 이들을 지원하기 위해서 WaveOut 클래스와 WaveIn 클래스를 제공한다.
적어놓은게 없으니 acm이 audio codec manager 였다는 것 외에는 기억이 안나네.... 아무튼 기존의 클래스들이 쓰기 어려워서 래퍼를 제공한다고 한다.
다음은 vista 부터 지원되는 modern API 이다.
WASAPI는 다양한 방식으로 오디오를 캡처하거나 녹음하도록 지원한다. 기존의 WaveIn, WaveOut을 대체하지만 보다 쓰기 어렵다고 한다.
DirectX Media Objects
오디오 코덱을 사용할 수 있는 또 다른 방법이라고 한다. 리샘플링 기능을 지원한다.
위의 WASAPI는 자동 리샘플링 기능을 지원하지 않아, 사운드카드가 44.1khz로 재생중이라면 8khz는 재생할 수 없다. 이럴 때는 DirectX Media Objects를 사용하여 리샘플링을 거친 후에 WASAPI에 보내야 한다.
Media Foundation API
오디오와 비디오 코덱을 쓰는 api들이다.
reader는 media foundation이 제공하는 모든 파일을 읽을 수 있다.
Steinberg ASIO
얘는 윈도우 API 래퍼가 아니다. ASIO 드라이버가 있는 사운드카드에서만 수행 가능하니 확인해보고 써야 한다.
Supported File Format
당연한 소리지만, NAudio는 몇 가지의 audio format을 지원한다. 이 지원한다는 건 읽을 수 있고, 쓸 수 있다는 뜻이다.
MP3 등의 compressed 포맷일 경우 reader는 PCM을 만들어낸다.
보다시피 꽤 여러 포맷을 지원하지만, MediaFoundationReader 덕에 간접적으로 AAC등 여러 포맷을 더 지원하게 되었다.
mp3 writer가 없는 이유는 뒤에 나온다고 한다. (저작권 문제가 아닐까)
Supported Platform
당연하지만 얘는 윈도우에서만 돌아간다. 뭐 잘 뜯어보면 다른 데서도 될 지 모르지만, 나는 거기까지 손댈 생각은 별로 없다.
기본적으로 (1.7 버전 기준) .net 3.5 이상이면 충분하다고 한다.(그런데 최신은 4.5에서만 돌아가는 것 같다. 사실 정확히는 옵션이 있는 것 같은데 못 찾겠네...)
윈도우 8 미만의 버전에는 완벽한 실행을 보장하지 않는다. 이 말은 8 이상의 버전에서는 실행을 보장한다는 뜻으로 보인다.
window store을 지원한다고 한다.
64bit에서도 실행에는 문제가 없으나, 64bit에서 실행되지 않는 코덱을 사용할 경우 원활한 동작을 보장할 수 없다고 한다. 외부 프로그램인 만큼 어쩔수 없는듯.
필요한 배경지식
위와 같은 배경지식이 NAudio를 원활하게 사용하기 위해서 필요하다고 한다. 그러니까 앞의 강의를 보고 시작하면 된다는 소리다.
사실 signal chain이 왜 필요할지 의문이 남았었는데 강의 보다보니까 NAudio는 signal chain을 염두에 두고 만들긴 했더라.
NAudio Signal Chain
이전의 디지털 오디오 강의에서도 설명했지만, 얘는 audio pipeline 이라고도 부르는 일련의 흐름이다.
오디오가 들어와서 각종 과정을 거쳐 변환되어 출력되는 것이다.
signal chain 에는 위와 같은 일련의 목록들이 들어갈 수 있다.
reader 클래스로 파일로부터(꼭 파일일 필요는 없지만, 나는 파일일 확률이 99%니까) PCM을 읽어들이고, 해당 PCM에 각종 처리를 가한 뒤 다른 포맷으로 압축하고서 실제 파일로 출력하는 것이다.
이건 reader 클래스 등 뒤의 ISampleProvider 인터페이스를 상속하는 클래스들을 보다 보면 이해가 될 것이다.
WaveStream
가장 기본적인 클래스는 WaveStream 이다.
stream.system 에서 상속(derived)되며, 읽기 전용이다(편집 불가). 시스템에서 가져왔기 때문.
위와 같은 class 이다.
Length는 당연히 전체 길이를 말한다. position은 어디까지 읽었는지를 바이트 단위로 알려주고, 현재 위치를 조정할 수 있다.
주의할 점은 set을 할 때 WaveFormat에서 가져올 수 있는 blockAlign의 배수로만 지정해야 한다는 거다. 안 그러면 오디오 파일이 손상될 수 있다.
read는 일반적인 그 read로 offset에서 count만큼 읽어서 buffer에 저장하는 거다.
WaveFormat 은 WaveFormat 클래스를 리턴하는 건데, 이 클래스는 다음에 바로 나오겠지만 지금 지닌 오디오 정보를 알려주는 것이다.
파일이 아니라 현재 지닌 오디오 정보다. PCM인지 압축포맷인지, 용량은 어떤지 등등.
CurrentTime은 바이트가 아닌 시간 단위로 현재 위치를 알려주고 세팅할 수 있게 한다. TotalTime은 length의 time 버전이다.
그리고 위 두 함수는 WaveFormat에 있는 averageByteForSecond를 써서 계산한다고 한다.
WaveFormat
포맷에 대한 정보를 지니는 클래스로, WindowsWaveFormatEX 구조를 지녔다.
다른 건 크게 유의할 건 없다. 당연하지만 읽기 전용이다.
IWaveProvider
WaveStream은 꽤나 내용이 많은데, 이 대부분은 특정 상황에서만 쓰일 수 있으므로 간략화된 인터페이스를 제작한 게 이것이다.
장점과 단점은 위와 같다.
ISampleProvider
설명을 보면 가장 노말하게 사용되는 인터페이스는 얘인 모양이다.
일단 float 32bit PCM이 가장 처리하기에 알맞다고들 하니까. 위의 일반 signal chain을 봐도 명확하지 않은가.
중간에 들어가는 여러 이펙트 등을 구현하기에도 좋다. 실제로 예시를 봤는데 참 쉽다.
이런 다양한 것들도 있는 모양이다.
직관적으로 봐서 각 파일을 읽고, 반복재생하고(LoopStream) 포맷 바꾸고 하는 stream들이 있다.
아예 16bit 오디오를 읽을 수 있는 provider도 있고.
볼륨을 조정하거나, 여러 소리를 합치거나 할 수 있는것도 보인다.
ISampleProvider 예제
정확히 말하면 signal chain 예제가 아닐까 싶긴 하다. 역시 설명 100번 하는 것보다 코드 한번 보는게 이해가 빠르지.
직접 코드를 쳐넣은 뒤 코드로 넣을까, 하다가 역시 그건 귀찮아졌다...
처음 인터페이스를 상속하면 아래와 같이 나온다.
그리고 클리핑 기능을 구현한 게 아래다.
위와 같은 느낌이다.
read 에서 파일을 읽어들여 수정, 저장하는 과정을 하는 거다. 이 경우 waveformat의 변경이 없으니 그대로 내주는 거고, 입력은 처음에 생성자에서 인자로 넘겨준다.
대충 signal chain이 상상이 간다.
하나를 만든 뒤 걔를 여러 클래스에서 read, read, read 하면서 한단계씩 변경해나가는 느낌 되겠다.
1강 끝.
'개발언어 > NAudio' 카테고리의 다른 글
[NAudio] 6. Recording Audio (0) | 2021.07.08 |
---|---|
[NAudio] 5. Working With Codecs (0) | 2021.07.08 |
[NAuidio] 4. Changing Wave Formats (0) | 2021.07.08 |
[NAuido] 3. Working With Files (0) | 2021.07.08 |
[NAudio] 2. Audio Playback (0) | 2021.07.08 |