2023. 6. 12. 15:30

닷넷은 사운드 처리가 개떡 같습니다.

'SoundPlayer'는 멀티플랫폼에서 동작하지 않습니다.

 

이 꼬라지인 이유를 아직도 모르겠습니다...

(최소한 기본 구현은 있어야 하는 게 아닌지....)

 

특히 크로스 플랫폼 작업 시 선택지가 애매해지는데......

그나마 쓸 수 있는 가벼운 라이브러리인 'NetCoreAudio'를 소개합니다.

 

 

1. 'NetCoreAudio' 특징

이 라이브러리는 여러 플랫폼에 사용할 수 있습니다.

단점은 기본 사운드 API인 'SoundPlayer'처럼 한 번에 하나뿐이 재생을 못 합니다.

 

자세한 분석은 '3. 분석'에서 하겠습니다.

 

 

2. 설치 및 사용

누겟(NuGet)에서 'NetCoreAudio'를 찾아 설치해 줍니다.

 

간단한 예제

기본 예제는 잘되어 있습니다.

참고 : github - NetCoreAudio/DemoHarness

 

var player = new Player();

switch (command)
{
    case "play":
        Console.WriteLine($"Playing {fileName}");
        player.Play(fileName).Wait();
        Console.WriteLine(player.Playing ? "Playback started" : "Could not start the playback");
        break;
    case "pause":
        player.Pause().Wait();
        Console.WriteLine(player.Paused ? "Playback paused" : "Could not pause playback");
        break;
    case "resume":
        player.Resume().Wait();
        Console.WriteLine(player.Playing && !player.Paused ? "Playback resumed" : "Could not resume playback");
        break;
    case "stop":
        player.Stop().Wait();
        Console.WriteLine(!player.Playing ? "Playback stopped" : "Could not stop the playback");
        break;
    case "change":
        player.Stop().Wait();
        ShowFileEntryPrompt();
        fileName = Console.ReadLine();
        ShowInstruction();
        break;
    case "volume":
        Console.WriteLine("Enter new volume in percent");
        byte volume = Convert.ToByte(Console.ReadLine());
        player.SetVolume(volume).Wait();
        ShowInstruction();
        break;
    case "exit":
        break;
    default:
        Console.WriteLine("Haven't got a clue, mate!");
        break;
}

 

사운드 라이브러리의 기능은 거기서 거기라 설명할 게 없고

'Player'개체를 생성해서 'Play' 할 때 파일 경로를 전달하여 재생합니다.

 

테스트 프로젝트 :

github - dang-gun/DotNetSamples/NetCoreAudioTest

 

 

3. 분석

다른 플랫폼은 테스트해 보지 않았지만, 재생전에 '프로세스 킬'을 하게 되어 있는 것으로 보아 동시 재생은 염두하지 않은 라이브러리로 보입니다.

 

윈도우에서는 'winmm.dll'로 구현되어 있는데 이것은 멀티 재생 지원을 합니다.

하지만 구현된 내용을 보면 한 번에 하나만 재생하도록 구현되어 있습니다.

 

'winmm.dll'로 멀티 재생을 구현해 본 입장에서 보자면 충분히 가능합니다.

(참고 : [.NET] 여러 사운드 파일 한 번에 재생하기 - mciSendString)

 

'SoundPlayer'로 구현된 것이 아닌 거로 봐서는 나중에라도 여러 파일 재생을 구현할 생각이 있었던 거 같기는 합니다.

이미 업데이트가 끊긴 프로젝트라 알 수가 없습니다.

 

다른 플랫폼도 구현된 걸 보면 윈도우만 명령어가 다른 걸 알 수 있습니다.

리눅스와 맥은 유닉스 명령어를 사용하고 있는데 마음만 먹으면 여러 파일 재생이 가능한 것으로 보입니다.

 

 

마무리

저는 결국 OpenAL을 사용하여 여러 파일 재생과 멀티플랫폼을 구현하였습니다.

OpenAL은 SDK를 설치해야 한다는 단점이 있습니다.

 

시간만 된다면 이 프로젝트 기반으로 여러 파일 재생도 해보면 좋을 텐데 말이죠....

뭐 설치할 거 없이 동작할 테니까요..

 

여러 파일 재생까지는 아니여도 이 정도 수준의 구현은 닷넷에서 해줘야 하는데.....

계획 자체가 없다고 합니다.

(github - dotnet/runtime - Cross-platform replacement for SoundPlayer for playing audio across devices/paltforms #27450)

 

표면적인 문제는 IoT 때문이라고 하는데.....

그러면 지금 'SoundPlayer'처럼 주요 플랫폼만 지원하고 예외인 플랫폼은 재생 안 되게 하면 되는 게 아닌가 싶은데 말이죠...

진짜 관심이 적어서 이러는 건가?