win_wrap/
audio.rs

1/*
2 * Copyright (c) 2024. The RigelA open source project team and
3 * its contributors reserve all rights.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and limitations under the License.
12 */
13
14use std::{
15    fmt::{Debug, Formatter},
16    future::Future,
17    mem::size_of,
18    pin::Pin,
19    sync::Arc,
20    task::{Context, Poll},
21};
22use windows::Win32::Media::Audio::{
23    AudioCategory_SoundEffects,
24    XAudio2::XAUDIO2_VOICE_STATE,
25    XAudio2::{
26        IXAudio2, IXAudio2MasteringVoice, IXAudio2SourceVoice, XAudio2CreateWithVersionInfo,
27        XAUDIO2_BUFFER, XAUDIO2_COMMIT_NOW, XAUDIO2_MAX_FREQ_RATIO, XAUDIO2_USE_DEFAULT_PROCESSOR,
28        XAUDIO2_VOICE_NOSRC,
29    },
30    WAVEFORMATEX, WAVE_FORMAT_PCM,
31};
32
33#[allow(dead_code)]
34pub struct XAudio2OutputStream {
35    engine: Arc<IXAudio2>,
36    mastering_voice: Arc<IXAudio2MasteringVoice>,
37    source_voice: Arc<IXAudio2SourceVoice>,
38}
39
40impl XAudio2OutputStream {
41    /**
42    创建一个音频输出流。
43    `sample_rate` 采样率。
44    `num_channels` 通道数。
45    */
46    pub fn new(sample_rate: u32, num_channels: u32) -> Self {
47        let mut engine: Option<IXAudio2> = None;
48        let mut mastering_voice: Option<IXAudio2MasteringVoice> = None;
49        let mut source_voice: Option<IXAudio2SourceVoice> = None;
50        unsafe { XAudio2CreateWithVersionInfo(&mut engine, 0, XAUDIO2_USE_DEFAULT_PROCESSOR, 2) }
51            .expect("Can't create the XAudio engine.");
52        if let Some(x) = engine.as_ref() {
53            unsafe {
54                x.CreateMasteringVoice(
55                    &mut mastering_voice,
56                    num_channels,
57                    sample_rate,
58                    0,
59                    None,
60                    None,
61                    AudioCategory_SoundEffects,
62                )
63            }
64            .expect("Can't create the mastering voice.");
65            let block_align = num_channels * 2; // 每个样本的字节数
66            let format = WAVEFORMATEX {
67                cbSize: size_of::<WAVEFORMATEX>() as u16,
68                nChannels: num_channels as u16,
69                nSamplesPerSec: sample_rate,
70                nBlockAlign: block_align as u16,
71                nAvgBytesPerSec: sample_rate * block_align,
72                wBitsPerSample: (block_align * 8) as u16,
73                wFormatTag: WAVE_FORMAT_PCM as u16,
74            };
75            unsafe {
76                x.CreateSourceVoice(
77                    &mut source_voice,
78                    &format,
79                    XAUDIO2_VOICE_NOSRC,
80                    XAUDIO2_MAX_FREQ_RATIO,
81                    None,
82                    None,
83                    None,
84                )
85            }
86            .expect("Can't create the source voice.");
87        }
88        Self {
89            engine: engine.unwrap().into(),
90            mastering_voice: mastering_voice.unwrap().into(),
91            source_voice: source_voice.unwrap().into(),
92        }
93    }
94
95    /**
96    写入音频数据,并等待播放完毕。
97    `data` 音频数据。
98    */
99    pub async fn write(&self, data: &[u8]) {
100        StreamState::new(self.source_voice.clone(), &data).await;
101    }
102
103    /**
104    从语音队列中删除所有挂起的音频缓冲区。
105    */
106    #[allow(dead_code)]
107    pub fn flush(&self) {
108        unsafe { self.source_voice.FlushSourceBuffers() }.unwrap_or(())
109    }
110
111    /**
112    停止播放。
113    */
114    pub fn stop(&self) {
115        unsafe { self.source_voice.Stop(0, 0) }.expect("Can't stop the stream.");
116    }
117
118    /**
119    开始播放。
120    */
121    pub fn start(&self) {
122        unsafe { self.source_voice.Start(0, XAUDIO2_COMMIT_NOW) }.expect("Can't start.");
123    }
124}
125impl Debug for XAudio2OutputStream {
126    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
127        write!(f, "AudioOutputStream")
128    }
129}
130unsafe impl Send for XAudio2OutputStream {}
131unsafe impl Sync for XAudio2OutputStream {}
132pub struct StreamState(Arc<IXAudio2SourceVoice>);
133impl StreamState {
134    fn new(source_voice: Arc<IXAudio2SourceVoice>, data: &[u8]) -> Self {
135        let mut buf = XAUDIO2_BUFFER::default();
136        buf.pAudioData = data.as_ptr();
137        buf.AudioBytes = data.len() as u32;
138        unsafe { source_voice.SubmitSourceBuffer(&buf, None) }.unwrap_or(());
139        Self(source_voice)
140    }
141}
142impl Future for StreamState {
143    type Output = ();
144    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
145        let mut state = XAUDIO2_VOICE_STATE::default();
146        unsafe {
147            self.0.GetState(&mut state, 0);
148        }
149        let p = state.BuffersQueued;
150        if p < 1 {
151            Poll::Ready(())
152        } else {
153            cx.waker().wake_by_ref();
154            Poll::Pending
155        }
156    }
157}
158unsafe impl Send for StreamState {}
159unsafe impl Sync for StreamState {}