Chromium Code Reviews| Index: media/audio/win/audio_low_latency_input_win.cc |
| diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc |
| index 22355580aac45b2c656ae6066bd25fd1b72f1a3f..cfecc91cc41ddbbcca6d5c8d652684b8a31dca6a 100644 |
| --- a/media/audio/win/audio_low_latency_input_win.cc |
| +++ b/media/audio/win/audio_low_latency_input_win.cc |
| @@ -15,6 +15,7 @@ |
| #include "media/audio/win/avrt_wrapper_win.h" |
| #include "media/audio/win/core_audio_util_win.h" |
| #include "media/base/audio_bus.h" |
| +#include "media/base/multi_channel_resampler.h" |
| using base::win::ScopedComPtr; |
| using base::win::ScopedCOMInitializer; |
| @@ -123,9 +124,10 @@ bool WASAPIAudioInputStream::Open() { |
| // Initialize the audio stream between the client and the device using |
| // shared mode and a lowest possible glitch-free latency. |
| hr = InitializeAudioEngine(); |
| + if (SUCCEEDED(hr) && resampler_.get() != nullptr) |
|
DaleCurtis
2017/02/13 19:40:42
just "&& resampler_" it has safe-bool conversion b
tommi (sloooow) - chröme
2017/02/16 17:08:46
Done.
|
| + open_result_ = OPEN_RESULT_OK_WITH_RESAMPLING; |
| ReportOpenResult(); // Report before we assign a value to |opened_|. |
| opened_ = SUCCEEDED(hr); |
| - DCHECK(open_result_ == OPEN_RESULT_OK || !opened_); |
| return opened_; |
| } |
| @@ -424,8 +426,15 @@ void WASAPIAudioInputStream::Run() { |
| // Copy data to audio bus to match the OnData interface. |
| uint8_t* audio_data = |
| reinterpret_cast<uint8_t*>(capture_buffer.get()); |
| - audio_bus_->FromInterleaved(audio_data, audio_bus_->frames(), |
| - format_.wBitsPerSample / 8); |
| + |
| + if (resampler_.get()) { |
|
DaleCurtis
2017/02/13 19:40:42
Ditto.
tommi (sloooow) - chröme
2017/02/16 17:08:46
Done.
|
| + resample_bus_->FromInterleaved(audio_data, resample_bus_->frames(), |
| + format_.wBitsPerSample / 8); |
| + resampler_->Resample(audio_bus_->frames(), audio_bus_.get()); |
| + } else { |
| + audio_bus_->FromInterleaved(audio_data, audio_bus_->frames(), |
| + format_.wBitsPerSample / 8); |
| + } |
| // Deliver data packet, delay estimation and volume level to |
| // the user. |
| @@ -595,6 +604,44 @@ bool WASAPIAudioInputStream::DesiredFormatIsSupported() { |
| &format_, &closest_match); |
| DLOG_IF(ERROR, hr == S_FALSE) << "Format is not supported " |
| << "but a closest match exists."; |
| + if (hr == S_FALSE && closest_match->nChannels == format_.nChannels) { |
|
DaleCurtis
2017/02/13 19:40:42
If you use a AudioConverter it'll handle mismatche
DaleCurtis
2017/02/13 23:59:00
You should also sanity check the closest match sam
tommi (sloooow) - chröme
2017/02/16 17:08:46
Done. Also switched to AudioConverter.
|
| + // We want a 1:1 ratio between the buffers we get and the buffers we |
| + // give to OnData so that each buffer we receive from the OS can be directly |
| + // resampled to a buffer that matches with what the client asked for. |
| + const double buffer_ratio = |
| + format_.nSamplesPerSec / static_cast<double>(audio_bus_->frames()); |
| + const size_t new_frames_per_buffer = |
| + static_cast<size_t>(closest_match->nSamplesPerSec / buffer_ratio); |
| + |
| + const double sample_rate_ratio = |
| + static_cast<double>(closest_match->nSamplesPerSec) / |
| + static_cast<double>(format_.nSamplesPerSec); |
| + resampler_.reset(new MultiChannelResampler( |
|
DaleCurtis
2017/02/13 19:40:42
I think this works, though not how we've done it i
DaleCurtis
2017/02/13 23:59:00
Over a long enough time frame I think this might l
tommi (sloooow) - chröme
2017/02/16 17:08:47
I tried several ways of reproducing that, includin
tommi (sloooow) - chröme
2017/02/16 17:09:49
Oh please ignore this, I did more testing and figu
|
| + format_.nChannels, sample_rate_ratio, new_frames_per_buffer, |
| + base::Bind(&WASAPIAudioInputStream::ProvideInput, |
| + base::Unretained(this)))); |
| + resampler_->PrimeWithSilence(); |
| + resample_bus_ = AudioBus::Create(format_.nChannels, new_frames_per_buffer); |
| + |
| + // Now change the format we're going to ask for to better match with what |
| + // the OS can provide. If we succeed in opening the stream with these |
| + // params, we can take care of the required resampling. |
| + format_.nSamplesPerSec = closest_match->nSamplesPerSec; |
| + format_.nAvgBytesPerSec = format_.nSamplesPerSec * format_.nBlockAlign; |
| + |
| + // Update our packet size assumptions based on the new format. |
| + const auto new_bytes_per_buffer = resample_bus_->frames() * |
| + closest_match->nChannels * |
| + (format_.wBitsPerSample / 8); |
| + packet_size_frames_ = new_bytes_per_buffer / format_.nBlockAlign; |
| + packet_size_bytes_ = new_bytes_per_buffer; |
| + ms_to_frame_count_ = |
| + static_cast<double>(closest_match->nSamplesPerSec) / 1000.0; |
| + |
| + // Indicate that we're good to go with a close match. |
| + hr = S_OK; |
| + } |
| + |
| return (hr == S_OK); |
| } |
| @@ -738,4 +785,9 @@ void WASAPIAudioInputStream::ReportOpenResult() const { |
| OPEN_RESULT_MAX + 1); |
| } |
| +void WASAPIAudioInputStream::ProvideInput(int resampler_frame_delay, |
| + AudioBus* audio_bus) { |
| + resample_bus_->CopyTo(audio_bus); |
|
DaleCurtis
2017/02/13 19:40:42
Probably want a DCHECK this isn't called twice wit
tommi (sloooow) - chröme
2017/02/16 17:08:47
Done.
|
| +} |
| + |
| } // namespace media |