Skip to content
vwaioletPublic

About

WinUI 3 및 BASS 엔진 기반 WASAPI Exclusive / ASIO 비트퍼펙트(Bit-Perfect) 하이파이 오디오 플레이어 (Native AOT)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

StelWave (스텔웨이브)

StelWave는 Windows App SDK (WinUI 3)와 고성능 오디오 엔진 BASS를 결합하여 제작된 고음질 오디오 플레이어 데스크톱 애플리케이션입니다. 음원의 원래 음질을 그대로 출력 장치로 전달하는 비트퍼펙트(Bit-Perfect) 및 저지연(Low latency) 재생에 초점을 맞추어 설계되었습니다.


🎧 핵심 기능 (Core Features)

1. 하이파이(Hi-Fi) 재생 모드 지원

기기의 사운드 하드웨어를 한계까지 활용할 수 있도록 다양한 출력 환경을 제공합니다.

  • Shared Mode (공용 믹서): Windows 시스템 기본 믹서를 사용하는 표준 재생 모드입니다.
  • WASAPI Exclusive Mode (WASAPI 단독 모드): Windows 오디오 엔진을 거치지 않고 오디오 장치를 직접 제어합니다. 장치가 지원하면 곡의 샘플레이트 그대로 장치를 열어 리샘플링 없이 보내므로, 볼륨이 100%이면 비트퍼펙트로 재생됩니다. 장치가 그 샘플레이트를 받지 않을 때만 장치 형식으로 변환하고, 출력 경로에 리샘플링으로 표시합니다.
  • ASIO Mode (ASIO 모드): 오디오 인터페이스 및 전용 드라이버를 통해 초저지연 및 고음질 출력을 지원합니다. 드라이버가 지원하면 장치를 곡의 샘플레이트로 바꿔 리샘플링 없이 재생합니다.
  • FLAC 무손실 재생: 공식 BASS FLAC 플러그인(bassflac.dll)을 통합하여 고해상도 FLAC 파일을 기본 지원합니다.

2. 실시간 오디오 스펙 트래킹

  • 재생 중인 소스의 원본 포맷(컨테이너, 비트 깊이, 샘플링 레이트)과 실제 사운드 카드로 나가는 출력 포맷을 비교해 재생 바에 FLAC 24/96 → 배타 32/96처럼 짧은 배지로 표시합니다.
  • Windows 레지스트리를 직접 조회하여 연결된 스피커의 실제 하드웨어 비트 깊이(Bit Depth)를 자동으로 검출합니다.
  • 출력 경로를 솔직하게 표시합니다. 원본과 출력의 샘플레이트가 다르면 리샘플링으로, 배타/ASIO 모드에서 샘플레이트·비트 깊이가 맞고 볼륨이 100%일 때만 비트퍼펙트로 표시합니다.
  • 배지를 누르거나 지금 재생 패널을 열면 비트퍼펙트 조건(출력 모드, 샘플레이트, 비트 깊이, 볼륨)마다 충족·주의·참고 여부와 이유를 보여 줍니다.

3. 대용량 라이브러리 초고속 스캔 & 최적화

  • 병렬 메타데이터 처리: 다중 스레드를 사용하는 Parallel.ForEach 방식을 채택하여 라이브러리에 추가한 폴더 내 수만 곡의 태그 정보(TagLibSharp 사용)와 오디오 속성(포맷, 비트 깊이, 샘플레이트, 비트레이트, 채널)을 순식간에 추출합니다.
  • SQLite 일괄 삽입(Batch Inserter): 추출한 메타데이터를 배치 단위(500개)로 SQLite 트랜잭션을 적용해 효율적으로 디비에 동기화합니다.
  • 다시 스캔과 취소: 다시 스캔하면 새 파일은 추가하고, 수정 시각이 바뀐 파일만 같은 Id로 다시 읽습니다. 모든 스캔은 진행 표시줄의 취소로 멈출 수 있습니다.
  • 스키마 버전 관리: DB 스키마는 PRAGMA user_version으로 관리하며, 이전 버전 DB는 곡을 그대로 둔 채 새 열을 추가합니다. 이전 버전에서 스캔한 곡은 라이브러리 정보 갱신으로 오디오 속성을 채웁니다.
  • UI 데이터 가상화(Data Virtualization): 대량의 음원 목록 스크롤 시 앱이 멈추거나 끊기지 않도록 VirtualizingTrackList를 직접 구현하여 SQLite로부터 비동기 페이징(100개 단위) 방식으로 리스트를 실시간 로드합니다. 아직 불러오지 않은 행은 자리 표시 행으로 두었다가 제자리에서 채우므로 목록이 깜빡이지 않고, 곡 개수도 백그라운드에서 조회합니다.

4. 정보를 촘촘하게 보여 주는 화면

  • 컬럼형 곡 테이블: 32px 행에 재생 상태, 트랙 번호, 제목, 아티스트, 앨범, 연도, 포맷, 비트, 샘플레이트, 길이를 표시합니다. 앨범 아티스트, 장르, 디스크, 비트레이트, 추가한 날짜 열은 헤더 우클릭이나 표시할 열 버튼으로 켭니다. 헤더를 누르면 정렬하고, 다시 누르면 순서를 뒤집습니다. 기본 정렬은 앨범 아티스트 → 앨범 → 디스크 → 트랙입니다.
  • 필터 브라우저: 장르 → 앨범 아티스트 → 앨범 목록에서 고르면 오른쪽 목록과 곡 테이블이 좁혀집니다. 각 값 옆에 곡 수를 보여 줍니다.
  • 지금 재생 패널: 창 오른쪽에 커버, 곡 정보, 포맷 요약, 출력 경로 상세, 다음 곡을 보여 줍니다. 재생 바의 커버나 패널 버튼으로 열고 닫습니다.
  • 반응형 레이아웃: 창 너비가 1280px 미만이면 지금 재생 패널을 내용 위에 띄우고, 1008px 미만이면 필터 브라우저와 우선순위가 낮은 열, 재생 바의 배지를 숨깁니다. 최소 창 크기는 720×500입니다.
  • 앨범 아트 로딩: 앨범 아트를 백그라운드에서 추출해 표시 크기(재생 바 64px, 지금 재생 360px, DPI 반영)로만 디코딩하고, 앨범 단위로 캐시합니다.

5. 사용자 편의 기능

  • 재생 대기열: 곡을 재생하면 그 시점의 목록이 재생 대기열이 됩니다. 이후 검색어를 바꿔도 재생 순서는 바뀌지 않습니다. 곡을 우클릭해 다음에 재생이나 대기열에 추가를 고를 수 있고, 재생 대기열 화면에서 끌어서 순서를 바꾸거나(Alt+↑/↓도 가능) 빼고, 원하는 곡부터 재생합니다. 대기열은 다음 실행 때 그대로 복원됩니다.
  • 셔플 & 반복 모드: 끔, 전체 반복, 한 곡 반복을 지원합니다. 셔플은 현재 곡을 유지한 채 대기열 순서만 섞고, 전체 반복으로 한 바퀴를 돌면 새 순서로 다시 섞습니다.
  • 실시간 검색: 제목 표시줄의 검색창에서 제목, 아티스트, 앨범, 앨범 아티스트, 장르로 검색합니다. 여러 단어를 입력하면 모두 포함된 곡을 찾습니다(beatles abbey). 입력이 잠시 멈추면 백그라운드에서 조회하므로 입력 중에 화면이 멈추지 않습니다.
  • 여러 곡 선택: Ctrl/Shift로 여러 곡을 고른 뒤 우클릭해 선택한 곡만 재생하거나 대기열에 넣습니다.
  • 세션 복원: 볼륨·음소거, 셔플·반복, 출력 장치, 창 위치와 크기, 마지막으로 듣던 곡과 위치, 재생 대기열, 표시할 열과 정렬, 테마를 기억해 다음 실행 때 복원합니다.
  • 테마: 설정에서 Windows 설정 따르기 / 라이트 / 다크를 고릅니다.

6. Windows와 함께 쓰기

  • 미디어 키 & Windows 미디어 오버레이: 키보드의 미디어 키(재생/일시정지, 이전/다음 곡)가 다른 앱을 쓰는 중에도 동작하고, 볼륨을 바꿀 때 뜨는 Windows 미디어 오버레이에 제목, 아티스트, 앨범, 커버, 재생 위치가 표시됩니다. 오버레이에서 탐색, 셔플, 반복도 바꿀 수 있습니다.
  • 미니 플레이어: 재생 바의 미니 플레이어 버튼이나 Ctrl+Shift+M으로 커버와 재생 컨트롤만 있는 작은 창을 항상 위에 띄웁니다. 위쪽을 끌어 옮길 수 있고, 다시 누르면 원래 창 크기와 위치로 돌아갑니다.
  • 앨범아트 색: 지금 재생 패널과 미니 플레이어 뒤에 흐린 커버를, 재생 바에 커버의 대표색을 은은하게 깝니다. 글자는 테마 색 그대로라 읽기 쉽고, 설정 → 화면 → 앨범아트 색에서 끌 수 있습니다.
  • 드래그 앤 드롭: 탐색기에서 폴더를 창에 끌어 놓으면 음악 폴더로 등록해 스캔하고, 파일을 놓으면 그 파일만 라이브러리에 추가합니다. 앱을 관리자 권한으로 실행하면 Windows 보안 정책(UIPI) 때문에 일반 권한의 탐색기에서 끌어 놓을 수 없으니 일반 권한으로 실행하세요.

🛠️ 기술 스택 (Technology Stack)

  • 언어 및 플랫폼: C# 14 / .NET 10.0 / Windows Target (10.0.17763.0 이상)
  • 프레임워크: WinUI 3 (Windows App SDK 2.2)
  • 오디오 엔진: BASS Audio Library (Native wrapper: ManagedBass 4.0.2)
    • ManagedBass.Asio, ManagedBass.Wasapi, ManagedBass.Mix
  • 데이터베이스: SQLite (Microsoft.Data.Sqlite 10.0.9)
  • 메타데이터 파서: TagLibSharp 2.3.0

🚀 시작하기 (Getting Started)

1. 필수 기본 환경

  • OS: Windows 10 (버전 1809, 빌드 17763 이상) 또는 Windows 11
  • IDE: Visual Studio 2022 (또는 VS Code + C# Dev Kit)
  • SDK: .NET 10.0 SDK

2. 의존성 네이티브 DLL 다운로드 (필수)

StelWave는 강력한 오디오 제어를 위해 BASS 네이티브 C++ DLL 라이브러리를 사용합니다. 빌드 및 실행 전에 반드시 아래 스크립트를 파워쉘에서 실행하여 네이티브 종속성을 다운로드해야 합니다.

프로젝트 루트 디렉토리에서 PowerShell을 열고 다음 명령어를 실행하십시오.

Set-ExecutionPolicy Bypass -Scope Process -Force
.\download_deps.ps1

이 스크립트는 bass.dll, basswasapi.dll, bassasio.dll, bassmix.dll, bassflac.dll의 x64 아키텍처 버전을 자동으로 내려받아 lib/x64/ 폴더에 배치하고, 빌드 시 실행 디렉토리로 복사되도록 구성합니다.

3. 빌드 및 실행

Visual Studio에서 StelWave.csproj를 로드한 뒤 F5 키를 누르거나 파워쉘에서 아래 명령어로 컴파일하고 실행합니다.

dotnet restore
dotnet run

단위 테스트(재생 대기열과 그 저장, 검색·정렬 쿼리와 DB 마이그레이션, 실제 WAV 파일 스캔, 테이블 열 정의, 커버 대표색 추출, 시간 포맷, 설정 직렬화, DB 이전, LRU 캐시)는 다음 명령으로 실행합니다.

dotnet test StelWave.Tests

4. 배포용 게시 (Publish)

Release 게시는 NativeAOT(네이티브 단일 실행 파일, 빠른 시작)로 구성되어 있습니다.

dotnet publish -c Release -r win-x64

NativeAOT는 C++ 링커가 필요하므로 Visual Studio(또는 Build Tools)의 C++를 사용한 데스크톱 개발 워크로드(MSVC 빌드 도구와 Windows SDK)를 설치해야 합니다. 설치하지 않은 환경에서는 NativeAOT를 끄고 트리밍된 자체 포함(self-contained) 앱으로 게시할 수 있습니다.

dotnet publish -c Release -r win-x64 -p:PublishAot=false

게시 폴더에는 컴파일된 XAML(.xbf)과 리소스 인덱스(StelWave.pri)가 함께 들어가므로 그대로 복사해 실행하면 됩니다.

NativeAOT 빌드에서만 드러나는 문제가 있으니 코드를 바꾼 뒤에는 게시본으로도 확인하세요. 예를 들어 WinUI가 object나 기본 클래스로 돌려주는 객체(포커스된 요소, 목록의 행 컨테이너 등)는 AOT 빌드에서 is ListViewItem 같은 형식 검사가 실패할 수 있습니다. 그래서 코드에서는 형식 검사 대신 Helpers/WinRTObjects와 행 인덱스를 씁니다.

5. 데이터 저장 위치 & 포터블 모드

라이브러리 DB(library.db), 설정(settings.json), 재생 대기열(queue.json), 크래시 로그는 %LocalAppData%\StelWave 폴더에 저장됩니다. 이전 버전처럼 실행 폴더에 library.db가 있으면 처음 실행할 때 한 번 복사해 그대로 이어 사용합니다(원본 파일은 그대로 남습니다).

실행 파일(StelWave.exe)과 같은 폴더에 StelWave.portable이라는 빈 파일을 두면 포터블 모드로 동작하며, 모든 데이터를 실행 폴더에 저장합니다. USB 드라이브 등에 설치해 들고 다닐 때 사용하세요.


📂 프로젝트 구조 (Project Structure)

StelWave/
│
├── Assets/                 # 애플리케이션 아이콘 및 이미지 리소스
├── Controls/               # 재사용 UI 컨트롤
│   ├── PlayerBar               # 하단 재생 바 (곡 정보, 포맷 배지, 컨트롤, 탐색 바, 장치, 볼륨)
│   ├── NowPlayingPanel         # 오른쪽 지금 재생 패널
│   ├── MiniPlayerView          # 미니 플레이어 화면
│   ├── OutputPathView          # 출력 경로 상세 (비트퍼펙트 조건별 표시)
│   ├── TrackRow / TrackTableHeader / TrackTable.cs  # 컬럼형 곡 테이블의 행, 헤더, 공유 열 너비
├── Converters/             # XAML 값 변환기 (탐색 슬라이더 시간 표시 등)
├── Helpers/                # 시간·오디오 포맷 표기, 커버 대표색 추출, 아이콘 코드 포인트, LRU 캐시, x:Bind 함수, AOT에서도 안전한 WinRT 객체·목록 행 판별 등 공용 헬퍼
├── Styles/                 # 재생 컨트롤 버튼 스타일 (App.xaml에 병합)
├── Database/               # 데이터베이스 액세스 및 리스트 데이터 가상화 로직
│   ├── DatabaseHelper.cs        # SQLite 초기화, 스키마 마이그레이션, 쿼리
│   ├── TrackQuery.cs            # 검색·필터·정렬 조건과 SQL 변환 (정렬 열은 허용 목록으로만 매핑)
│   └── VirtualizingTrackList.cs # 라이브러리 목록 데이터 소스 (비동기 페이징, 자리 표시 행 제자리 채우기)
│
├── Models/                 # 데이터 모델 (Track, TrackColumn, FacetItem, AppSettings, QueueState, RepeatMode)
│
├── Services/               # 핵심 서비스
│   ├── AudioDevice.cs           # 오디오 하드웨어 장치 엔티티
│   ├── AudioService.cs          # BASS엔진 API 래핑, 재생/일시정지/시크 및 음질 정보 쿼리
│   ├── LibraryService.cs        # 폴더 스캔(추가·다시 읽기·취소), 정보 갱신, 누락 파일 찾기
│   ├── PlaybackQueue.cs         # 재생 대기열 (목록과 독립된 재생 순서, 셔플, 삽입·제거·이동)
│   ├── QueueStore.cs            # 재생 대기열 저장·복원 (queue.json)
│   ├── MediaControlsService.cs  # 미디어 키와 Windows 미디어 오버레이(SMTC) 연동
│   ├── AlbumArtService.cs       # 앨범아트 추출·디코딩·캐시
│   ├── SettingsService.cs       # settings.json 로드/저장
│   └── AppPaths.cs              # 데이터 폴더 위치, 포터블 모드, 기존 DB 이전
│
├── ViewModels/             # 화면이 바인딩하는 상태와 동작
│   ├── PlayerViewModel.cs       # 재생, 대기열, 출력 경로
│   ├── LibraryViewModel.cs      # 검색, 필터 브라우저, 정렬, 표시할 열
│   ├── ScanViewModel.cs         # 음악 폴더와 스캔·정리 작업 (드롭한 폴더·파일 포함)
│   ├── ArtworkViewModel.cs      # 재생 중인 곡의 커버와 대표색
│   └── ShellViewModel.cs        # 창 너비, 지금 재생 패널, 미니 플레이어, 테마, 앨범아트 색
├── Views/                  # 페이지 (LibraryPage, QueuePage, SettingsPage)
├── StelWave.Tests/         # 단위 테스트 (xUnit)
│
├── Properties/             # 앱 퍼블리시 프로필 설정
├── App.xaml / App.xaml.cs   # WinUI App 진입점
├── MainWindow.xaml / .cs   # 셸: 제목 표시줄 검색, 내비게이션, 알림, 재생 바, 단축키
├── download_deps.ps1       # BASS 라이브러리 자동 셋업 스크립트
└── StelWave.csproj         # 빌드 및 NuGet 패키지 의존성 파일

📖 사용 방법

  1. 라이브러리 빌드: 라이브러리 화면의 폴더 추가… 버튼(라이브러리가 비어 있으면 목록 영역의 음악 폴더 추가 버튼)이나 설정 → 음악 폴더에서 폴더를 추가합니다.
  2. 폴더 추가: 음악 파일(.mp3, .flac, .wav 등)이 담겨 있는 컴퓨터의 폴더를 선택합니다. 등록한 폴더는 설정에서 다시 스캔하거나 제거할 수 있습니다.
  3. 스캔 및 목록 자동화: 스캔 진행률은 상단 알림 막대에 표시되고(취소 가능), 끝나면 추가·다시 읽은 곡 수를 알려 주며 목록에 즉시 반영됩니다.
  4. 둘러보기: 필터 브라우저에서 장르 → 앨범 아티스트 → 앨범을 고르거나, 제목 표시줄 검색창(Ctrl+F)에 검색어를 입력합니다. 열 헤더를 누르면 정렬됩니다.
  5. 출력 모드 설정: 재생 바 우측의 출력 장치(헤드폰 아이콘) 메뉴나 설정 → 출력 장치에서 공유, WASAPI 배타, ASIO 장치를 고릅니다. WASAPI 배타 모드는 장치를 독점하므로 재생 중에는 다른 앱의 소리가 나지 않을 수 있습니다. 장치를 새로 연결했다면 장치 목록 새로 고침을 누르세요.
  6. 재생 제어: 곡을 더블 클릭하거나 선택 후 Enter를 누르면 그 곡부터 목록 전체를 재생합니다. 곡을 우클릭하면 재생, 다음에 재생, 대기열에 추가, 파일 위치 열기 메뉴를 쓸 수 있습니다.
  7. 출력 경로 확인: 재생 바의 배지가 원본 포맷 → 출력 포맷을 보여 줍니다. 원본이 변환 없이 전달되면 초록색 체크(비트퍼펙트), 샘플레이트가 변환되면 주의 표시(리샘플링)가 붙습니다. 배지를 누르면 조건별 상세가 열립니다.
  8. 라이브러리 정리: 설정 → 누락된 파일 정리…로 파일이 사라진 곡을 찾아 확인 후 뺍니다. 위험 구역의 라이브러리 초기화…는 목록만 비우며 음악 파일은 지워지지 않습니다.

⌨️ 키보드 단축키

동작 단축키
재생 / 일시정지 Space (텍스트 입력 중이 아닐 때)
이전 곡 / 다음 곡 Ctrl + ← / → (3초 넘게 재생 중이면 이전 곡 대신 곡 처음으로)
5초 뒤로 / 앞으로 Shift + ← / →
볼륨 올리기 / 내리기 Ctrl + ↑ / ↓ (볼륨 영역에서 마우스 휠도 가능)
음소거 F7
셔플 / 반복 모드 Ctrl + H / Ctrl + T
검색창으로 이동 / 검색어 지우기 Ctrl + F / Esc
선택한 곡 재생 Enter
우클릭 메뉴 열기 메뉴 키 또는 Shift + F10
재생 대기열에서 빼기 / 순서 옮기기 Delete / Alt + ↑ / ↓ (재생 대기열 화면)
미니 플레이어 / 기본 창으로 Ctrl + Shift + M
재생 / 일시정지, 이전 곡 / 다음 곡 키보드 미디어 키 (다른 앱을 쓰는 중에도)

About

WinUI 3 및 BASS 엔진 기반 WASAPI Exclusive / ASIO 비트퍼펙트(Bit-Perfect) 하이파이 오디오 플레이어 (Native AOT)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages