Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Unified Diff: media/audio/win/audio_low_latency_input_win.cc

Issue 2690793002: Add basic resample support to WASAPIAudioInputStream. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « media/audio/win/audio_low_latency_input_win.h ('k') | media/audio/win/audio_low_latency_input_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698