Fix WASAPI capture logic

The buffer size handling differs from what render streams uses. Logic is based on https://github.com/microsoft/Windows-universal-samples/blob/master/Samples/WindowsAudioSession/cpp/WASAPICapture.cpp.
This commit is contained in:
ishitatsuyuki 2019-08-12 10:56:14 +09:00
parent 36dee482bd
commit e9043c605a
1 changed files with 60 additions and 49 deletions

View File

@ -502,73 +502,84 @@ impl EventLoop {
let stream_idx = handle_idx - 1; let stream_idx = handle_idx - 1;
let stream = &mut run_context.streams[stream_idx]; let stream = &mut run_context.streams[stream_idx];
// The number of frames available for reading/writing.
let mut frames_available = match get_available_frames(stream) {
Ok(0) => continue, // TODO: Can this happen?
Ok(n) => n,
Err(err) => {
streams_to_remove.push((stream.id.clone(), err));
continue;
}
};
let sample_size = stream.sample_format.sample_size(); let sample_size = stream.sample_format.sample_size();
// Obtaining a pointer to the buffer. // Obtaining a pointer to the buffer.
match stream.client_flow { match stream.client_flow {
AudioClientFlow::Capture { capture_client } => { AudioClientFlow::Capture { capture_client } => {
let mut frames_available = 0;
// Get the available data in the shared buffer. // Get the available data in the shared buffer.
let mut buffer: *mut BYTE = mem::uninitialized(); let mut buffer: *mut BYTE = mem::uninitialized();
let mut flags = mem::uninitialized(); let mut flags = mem::uninitialized();
let hresult = (*capture_client).GetBuffer( loop {
&mut buffer, let hresult = (*capture_client).GetNextPacketSize(&mut frames_available);
&mut frames_available, if let Err(err) = stream_error_from_hresult(hresult) {
&mut flags, streams_to_remove.push((stream.id.clone(), err));
ptr::null_mut(), break; // Identical to continuing the outer loop
ptr::null_mut(), }
); if frames_available == 0 {
break;
}
let hresult = (*capture_client).GetBuffer(
&mut buffer,
&mut frames_available,
&mut flags,
ptr::null_mut(),
ptr::null_mut(),
);
// TODO: Can this happen? // TODO: Can this happen?
if hresult == AUDCLNT_S_BUFFER_EMPTY { if hresult == AUDCLNT_S_BUFFER_EMPTY {
continue; continue;
} else if let Err(err) = stream_error_from_hresult(hresult) { } else if let Err(err) = stream_error_from_hresult(hresult) {
streams_to_remove.push((stream.id.clone(), err)); streams_to_remove.push((stream.id.clone(), err));
continue; break; // Identical to continuing the outer loop
} }
debug_assert!(!buffer.is_null()); debug_assert!(!buffer.is_null());
let buffer_len = frames_available as usize let buffer_len = frames_available as usize
* stream.bytes_per_frame as usize / sample_size; * stream.bytes_per_frame as usize / sample_size;
// Simplify the capture callback sample format branches. // Simplify the capture callback sample format branches.
macro_rules! capture_callback { macro_rules! capture_callback {
($T:ty, $Variant:ident) => {{ ($T:ty, $Variant:ident) => {{
let buffer_data = buffer as *mut _ as *const $T; let buffer_data = buffer as *mut _ as *const $T;
let slice = slice::from_raw_parts(buffer_data, buffer_len); let slice = slice::from_raw_parts(buffer_data, buffer_len);
let unknown_buffer = UnknownTypeInputBuffer::$Variant(::InputBuffer { let unknown_buffer = UnknownTypeInputBuffer::$Variant(::InputBuffer {
buffer: slice, buffer: slice,
}); });
let data = StreamData::Input { buffer: unknown_buffer }; let data = StreamData::Input { buffer: unknown_buffer };
callback(stream.id.clone(), Ok(data)); callback(stream.id.clone(), Ok(data));
// Release the buffer. // Release the buffer.
let hresult = (*capture_client).ReleaseBuffer(frames_available); let hresult = (*capture_client).ReleaseBuffer(frames_available);
if let Err(err) = stream_error_from_hresult(hresult) { if let Err(err) = stream_error_from_hresult(hresult) {
streams_to_remove.push((stream.id.clone(), err)); streams_to_remove.push((stream.id.clone(), err));
continue; continue;
} }
}}; }};
} }
match stream.sample_format { match stream.sample_format {
SampleFormat::F32 => capture_callback!(f32, F32), SampleFormat::F32 => capture_callback!(f32, F32),
SampleFormat::I16 => capture_callback!(i16, I16), SampleFormat::I16 => capture_callback!(i16, I16),
SampleFormat::U16 => capture_callback!(u16, U16), SampleFormat::U16 => capture_callback!(u16, U16),
}
} }
}, },
AudioClientFlow::Render { render_client } => { AudioClientFlow::Render { render_client } => {
// The number of frames available for writing.
let frames_available = match get_available_frames(stream) {
Ok(0) => continue, // TODO: Can this happen?
Ok(n) => n,
Err(err) => {
streams_to_remove.push((stream.id.clone(), err));
continue;
}
};
let mut buffer: *mut BYTE = mem::uninitialized(); let mut buffer: *mut BYTE = mem::uninitialized();
let hresult = (*render_client).GetBuffer( let hresult = (*render_client).GetBuffer(
frames_available, frames_available,