1use 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 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; 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 pub async fn write(&self, data: &[u8]) {
100 StreamState::new(self.source_voice.clone(), &data).await;
101 }
102
103 #[allow(dead_code)]
107 pub fn flush(&self) {
108 unsafe { self.source_voice.FlushSourceBuffers() }.unwrap_or(())
109 }
110
111 pub fn stop(&self) {
115 unsafe { self.source_voice.Stop(0, 0) }.expect("Can't stop the stream.");
116 }
117
118 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 {}