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

Side by Side Diff: webrtc/modules/audio_mixer/audio_mixer_impl.cc

Issue 2298163002: Simplifications of the mixing algorithm. (Closed)
Patch Set: Rebase. Created 4 years, 3 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 19 matching lines...) Expand all
30 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before) 30 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before)
31 : audio_source_(p), 31 : audio_source_(p),
32 audio_frame_(a), 32 audio_frame_(a),
33 muted_(m), 33 muted_(m),
34 was_mixed_before_(was_mixed_before) { 34 was_mixed_before_(was_mixed_before) {
35 if (!muted_) { 35 if (!muted_) {
36 energy_ = NewMixerCalculateEnergy(*a); 36 energy_ = NewMixerCalculateEnergy(*a);
37 } 37 }
38 } 38 }
39 39
40 SourceFrame(MixerAudioSource* p,
41 AudioFrame* a,
42 bool m,
43 bool was_mixed_before,
44 uint32_t energy)
45 : audio_source_(p),
46 audio_frame_(a),
47 muted_(m),
48 energy_(energy),
49 was_mixed_before_(was_mixed_before) {}
50
40 // a.shouldMixBefore(b) is used to select mixer participants. 51 // a.shouldMixBefore(b) is used to select mixer participants.
41 bool shouldMixBefore(const SourceFrame& other) const { 52 bool shouldMixBefore(const SourceFrame& other) const {
42 if (muted_ != other.muted_) { 53 if (muted_ != other.muted_) {
43 return other.muted_; 54 return other.muted_;
44 } 55 }
45 56
46 auto our_activity = audio_frame_->vad_activity_; 57 auto our_activity = audio_frame_->vad_activity_;
47 auto other_activity = other.audio_frame_->vad_activity_; 58 auto other_activity = other.audio_frame_->vad_activity_;
48 59
49 if (our_activity != other_activity) { 60 if (our_activity != other_activity) {
(...skipping 13 matching lines...) Expand all
63 // Remixes a frame between stereo and mono. 74 // Remixes a frame between stereo and mono.
64 void RemixFrame(AudioFrame* frame, size_t number_of_channels) { 75 void RemixFrame(AudioFrame* frame, size_t number_of_channels) {
65 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); 76 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
66 if (frame->num_channels_ == 1 && number_of_channels == 2) { 77 if (frame->num_channels_ == 1 && number_of_channels == 2) {
67 AudioFrameOperations::MonoToStereo(frame); 78 AudioFrameOperations::MonoToStereo(frame);
68 } else if (frame->num_channels_ == 2 && number_of_channels == 1) { 79 } else if (frame->num_channels_ == 2 && number_of_channels == 1) {
69 AudioFrameOperations::StereoToMono(frame); 80 AudioFrameOperations::StereoToMono(frame);
70 } 81 }
71 } 82 }
72 83
73 // Mix |frame| into |mixed_frame|, with saturation protection and upmixing. 84 void Ramp(const std::vector<SourceFrame>& mixed_sources_and_frames) {
74 // These effects are applied to |frame| itself prior to mixing. Assumes that 85 for (const auto& source_frame : mixed_sources_and_frames) {
75 // |mixed_frame| always has at least as many channels as |frame|. Supports 86 // Ramp in previously unmixed.
76 // stereo at most. 87 if (!source_frame.was_mixed_before_) {
77 // 88 NewMixerRampIn(source_frame.audio_frame_);
78 void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) { 89 }
79 RTC_DCHECK_GE(mixed_frame->num_channels_, frame->num_channels_); 90
80 if (use_limiter) { 91 const bool is_mixed = source_frame.audio_source_->_mixHistory->IsMixed();
81 // Divide by two to avoid saturation in the mixing. 92 // Ramp out currently unmixed.
82 // This is only meaningful if the limiter will be used. 93 if (source_frame.was_mixed_before_ && !is_mixed) {
83 *frame >>= 1; 94 NewMixerRampOut(source_frame.audio_frame_);
95 }
84 } 96 }
85 RTC_DCHECK_EQ(frame->num_channels_, mixed_frame->num_channels_);
86 *mixed_frame += *frame;
87 } 97 }
88 98
89 } // namespace 99 } // namespace
90 100
91 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {} 101 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {}
92 102
93 MixerAudioSource::~MixerAudioSource() { 103 MixerAudioSource::~MixerAudioSource() {
94 delete _mixHistory; 104 delete _mixHistory;
95 } 105 }
96 106
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, 191 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
182 "Invalid frequency: %d", sample_rate); 192 "Invalid frequency: %d", sample_rate);
183 RTC_NOTREACHED(); 193 RTC_NOTREACHED();
184 return; 194 return;
185 } 195 }
186 196
187 if (OutputFrequency() != sample_rate) { 197 if (OutputFrequency() != sample_rate) {
188 SetOutputFrequency(static_cast<Frequency>(sample_rate)); 198 SetOutputFrequency(static_cast<Frequency>(sample_rate));
189 } 199 }
190 200
191 AudioFrameList mixList; 201 AudioFrameList mix_list;
192 AudioFrameList additionalFramesList; 202 AudioFrameList anonymous_mix_list;
193 int num_mixed_audio_sources; 203 int num_mixed_audio_sources;
194 { 204 {
195 rtc::CritScope lock(&crit_); 205 rtc::CritScope lock(&crit_);
196 mixList = UpdateToMix(kMaximumAmountOfMixedAudioSources); 206 mix_list = GetNonAnonymousAudio();
197 GetAdditionalAudio(&additionalFramesList); 207 anonymous_mix_list = GetAnonymousAudio();
198 num_mixed_audio_sources = static_cast<int>(num_mixed_audio_sources_); 208 num_mixed_audio_sources = static_cast<int>(num_mixed_audio_sources_);
199 } 209 }
200 210
201 for (FrameAndMuteInfo& frame_and_mute : mixList) { 211 mix_list.insert(mix_list.begin(), anonymous_mix_list.begin(),
202 RemixFrame(frame_and_mute.frame, number_of_channels); 212 anonymous_mix_list.end());
203 } 213
204 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) { 214 for (const auto& frame : mix_list) {
205 RemixFrame(frame_and_mute.frame, number_of_channels); 215 RemixFrame(frame, number_of_channels);
206 } 216 }
207 217
208 audio_frame_for_mixing->UpdateFrame( 218 audio_frame_for_mixing->UpdateFrame(
209 -1, time_stamp_, NULL, 0, output_frequency_, AudioFrame::kNormalSpeech, 219 -1, time_stamp_, NULL, 0, output_frequency_, AudioFrame::kNormalSpeech,
210 AudioFrame::kVadPassive, number_of_channels); 220 AudioFrame::kVadPassive, number_of_channels);
211 221
212 time_stamp_ += static_cast<uint32_t>(sample_size_); 222 time_stamp_ += static_cast<uint32_t>(sample_size_);
213 223
214 use_limiter_ = num_mixed_audio_sources > 1; 224 use_limiter_ = num_mixed_audio_sources > 1;
215 225
216 // We only use the limiter if it supports the output sample rate and 226 // We only use the limiter if we're actually mixing multiple streams.
217 // we're actually mixing multiple streams. 227 MixFromList(audio_frame_for_mixing, mix_list, id_, use_limiter_);
218 MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_); 228
219 MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList);
220 if (audio_frame_for_mixing->samples_per_channel_ == 0) { 229 if (audio_frame_for_mixing->samples_per_channel_ == 0) {
221 // Nothing was mixed, set the audio samples to silence. 230 // Nothing was mixed, set the audio samples to silence.
222 audio_frame_for_mixing->samples_per_channel_ = sample_size_; 231 audio_frame_for_mixing->samples_per_channel_ = sample_size_;
223 audio_frame_for_mixing->Mute(); 232 audio_frame_for_mixing->Mute();
224 } else { 233 } else {
225 // Only call the limiter if we have something to mix. 234 // Only call the limiter if we have something to mix.
226 LimitMixedAudio(audio_frame_for_mixing); 235 LimitMixedAudio(audio_frame_for_mixing);
227 } 236 }
228 237
229 // Pass the final result to the level indicator. 238 // Pass the final result to the level indicator.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 ? 0 334 ? 0
326 : -1; 335 : -1;
327 } 336 }
328 337
329 bool AudioMixerImpl::AnonymousMixabilityStatus( 338 bool AudioMixerImpl::AnonymousMixabilityStatus(
330 const MixerAudioSource& audio_source) const { 339 const MixerAudioSource& audio_source) const {
331 rtc::CritScope lock(&crit_); 340 rtc::CritScope lock(&crit_);
332 return IsAudioSourceInList(audio_source, additional_audio_source_list_); 341 return IsAudioSourceInList(audio_source, additional_audio_source_list_);
333 } 342 }
334 343
335 AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const { 344 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() const {
336 RTC_DCHECK_RUN_ON(&thread_checker_); 345 RTC_DCHECK_RUN_ON(&thread_checker_);
346 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
347 "GetNonAnonymousAudio()");
337 AudioFrameList result; 348 AudioFrameList result;
338 std::vector<SourceFrame> audioSourceMixingDataList; 349 std::vector<SourceFrame> audioSourceMixingDataList;
350 std::vector<SourceFrame> ramp_list;
339 351
340 // Get audio source audio and put it in the struct vector. 352 // Get audio source audio and put it in the struct vector.
341 for (MixerAudioSource* audio_source : audio_source_list_) { 353 for (MixerAudioSource* audio_source : audio_source_list_) {
342 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( 354 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted(
343 id_, static_cast<int>(output_frequency_)); 355 id_, static_cast<int>(output_frequency_));
344 356
345 auto audio_frame_info = audio_frame_with_info.audio_frame_info; 357 auto audio_frame_info = audio_frame_with_info.audio_frame_info;
346 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; 358 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame;
347 359
348 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) { 360 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) {
349 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, 361 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
350 "failed to GetAudioFrameWithMuted() from participant"); 362 "failed to GetAudioFrameWithMuted() from participant");
351 continue; 363 continue;
352 } 364 }
353 audioSourceMixingDataList.emplace_back( 365 audioSourceMixingDataList.emplace_back(
354 audio_source, audio_source_audio_frame, 366 audio_source, audio_source_audio_frame,
355 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted, 367 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted,
356 audio_source->_mixHistory->WasMixed()); 368 audio_source->_mixHistory->WasMixed());
357 } 369 }
358 370
359 // Sort frames by sorting function. 371 // Sort frames by sorting function.
360 std::sort(audioSourceMixingDataList.begin(), audioSourceMixingDataList.end(), 372 std::sort(audioSourceMixingDataList.begin(), audioSourceMixingDataList.end(),
361 std::mem_fn(&SourceFrame::shouldMixBefore)); 373 std::mem_fn(&SourceFrame::shouldMixBefore));
362 374
375 int maxAudioFrameCounter = kMaximumAmountOfMixedAudioSources;
363 // Go through list in order and put things in mixList. 376 // Go through list in order and put things in mixList.
364 for (SourceFrame& p : audioSourceMixingDataList) { 377 for (SourceFrame& p : audioSourceMixingDataList) {
365 // Filter muted. 378 // Filter muted.
366 if (p.muted_) { 379 if (p.muted_) {
367 p.audio_source_->_mixHistory->SetIsMixed(false); 380 p.audio_source_->_mixHistory->SetIsMixed(false);
368 continue; 381 continue;
369 } 382 }
370 383
371 // Add frame to result vector for mixing. 384 // Add frame to result vector for mixing.
372 bool is_mixed = false; 385 bool is_mixed = false;
373 if (maxAudioFrameCounter > 0) { 386 if (maxAudioFrameCounter > 0) {
374 --maxAudioFrameCounter; 387 --maxAudioFrameCounter;
375 if (!p.was_mixed_before_) { 388 result.push_back(p.audio_frame_);
376 NewMixerRampIn(p.audio_frame_); 389 ramp_list.emplace_back(p.audio_source_, p.audio_frame_, false,
377 } 390 p.was_mixed_before_, -1);
378 result.emplace_back(p.audio_frame_, false);
379 is_mixed = true; 391 is_mixed = true;
380 } 392 }
381
382 // Ramp out unmuted.
383 if (p.was_mixed_before_ && !is_mixed) {
384 NewMixerRampOut(p.audio_frame_);
385 result.emplace_back(p.audio_frame_, false);
386 }
387
388 p.audio_source_->_mixHistory->SetIsMixed(is_mixed); 393 p.audio_source_->_mixHistory->SetIsMixed(is_mixed);
389 } 394 }
395 Ramp(ramp_list);
390 return result; 396 return result;
391 } 397 }
392 398
393 void AudioMixerImpl::GetAdditionalAudio( 399 AudioFrameList AudioMixerImpl::GetAnonymousAudio() const {
394 AudioFrameList* additionalFramesList) const {
395 RTC_DCHECK_RUN_ON(&thread_checker_); 400 RTC_DCHECK_RUN_ON(&thread_checker_);
396 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 401 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
397 "GetAdditionalAudio(additionalFramesList)"); 402 "GetAnonymousAudio()");
398 // The GetAudioFrameWithMuted() callback may result in the audio source being 403 // The GetAudioFrameWithMuted() callback may result in the audio source being
399 // removed from additionalAudioFramesList_. If that happens it will 404 // removed from additionalAudioFramesList_. If that happens it will
400 // invalidate any iterators. Create a copy of the audio sources list such 405 // invalidate any iterators. Create a copy of the audio sources list such
401 // that the list of participants can be traversed safely. 406 // that the list of participants can be traversed safely.
407 std::vector<SourceFrame> ramp_list;
402 MixerAudioSourceList additionalAudioSourceList; 408 MixerAudioSourceList additionalAudioSourceList;
409 AudioFrameList result;
403 additionalAudioSourceList.insert(additionalAudioSourceList.begin(), 410 additionalAudioSourceList.insert(additionalAudioSourceList.begin(),
404 additional_audio_source_list_.begin(), 411 additional_audio_source_list_.begin(),
405 additional_audio_source_list_.end()); 412 additional_audio_source_list_.end());
406 413
407 for (MixerAudioSourceList::const_iterator audio_source = 414 for (MixerAudioSourceList::const_iterator audio_source =
408 additionalAudioSourceList.begin(); 415 additionalAudioSourceList.begin();
409 audio_source != additionalAudioSourceList.end(); ++audio_source) { 416 audio_source != additionalAudioSourceList.end(); ++audio_source) {
410 auto audio_frame_with_info = 417 auto audio_frame_with_info =
411 (*audio_source)->GetAudioFrameWithMuted(id_, output_frequency_); 418 (*audio_source)->GetAudioFrameWithMuted(id_, output_frequency_);
412 auto ret = audio_frame_with_info.audio_frame_info; 419 auto ret = audio_frame_with_info.audio_frame_info;
413 AudioFrame* audio_frame = audio_frame_with_info.audio_frame; 420 AudioFrame* audio_frame = audio_frame_with_info.audio_frame;
414 if (ret == MixerAudioSource::AudioFrameInfo::kError) { 421 if (ret == MixerAudioSource::AudioFrameInfo::kError) {
415 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, 422 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
416 "failed to GetAudioFrameWithMuted() from audio_source"); 423 "failed to GetAudioFrameWithMuted() from audio_source");
417 continue; 424 continue;
418 } 425 }
419 if (audio_frame->samples_per_channel_ == 0) { 426 if (ret != MixerAudioSource::AudioFrameInfo::kMuted) {
420 // Empty frame. Don't use it. 427 result.push_back(audio_frame);
421 continue; 428 ramp_list.emplace_back(*audio_source, audio_frame, false,
429 (*audio_source)->_mixHistory->IsMixed(), -1);
430 (*audio_source)->_mixHistory->SetIsMixed(true);
422 } 431 }
423 additionalFramesList->push_back(FrameAndMuteInfo(
424 audio_frame, ret == MixerAudioSource::AudioFrameInfo::kMuted));
425 } 432 }
433 Ramp(ramp_list);
434 return result;
426 } 435 }
427 436
428 bool AudioMixerImpl::IsAudioSourceInList( 437 bool AudioMixerImpl::IsAudioSourceInList(
429 const MixerAudioSource& audio_source, 438 const MixerAudioSource& audio_source,
430 const MixerAudioSourceList& audioSourceList) const { 439 const MixerAudioSourceList& audioSourceList) const {
431 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 440 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
432 "IsAudioSourceInList(audio_source,audioSourceList)"); 441 "IsAudioSourceInList(audio_source,audioSourceList)");
433 return std::find(audioSourceList.begin(), audioSourceList.end(), 442 return std::find(audioSourceList.begin(), audioSourceList.end(),
434 &audio_source) != audioSourceList.end(); 443 &audio_source) != audioSourceList.end();
435 } 444 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 int32_t id, 476 int32_t id,
468 bool use_limiter) { 477 bool use_limiter) {
469 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id, 478 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id,
470 "MixFromList(mixedAudio, audioFrameList)"); 479 "MixFromList(mixedAudio, audioFrameList)");
471 if (audioFrameList.empty()) 480 if (audioFrameList.empty())
472 return 0; 481 return 0;
473 482
474 uint32_t position = 0; 483 uint32_t position = 0;
475 484
476 if (audioFrameList.size() == 1) { 485 if (audioFrameList.size() == 1) {
477 mixedAudio->timestamp_ = audioFrameList.front().frame->timestamp_; 486 mixedAudio->timestamp_ = audioFrameList.front()->timestamp_;
478 mixedAudio->elapsed_time_ms_ = 487 mixedAudio->elapsed_time_ms_ = audioFrameList.front()->elapsed_time_ms_;
479 audioFrameList.front().frame->elapsed_time_ms_;
480 } else { 488 } else {
481 // TODO(wu): Issue 3390. 489 // TODO(wu): Issue 3390.
482 // Audio frame timestamp is only supported in one channel case. 490 // Audio frame timestamp is only supported in one channel case.
483 mixedAudio->timestamp_ = 0; 491 mixedAudio->timestamp_ = 0;
484 mixedAudio->elapsed_time_ms_ = -1; 492 mixedAudio->elapsed_time_ms_ = -1;
485 } 493 }
486 494
487 for (AudioFrameList::const_iterator iter = audioFrameList.begin(); 495 for (const auto& frame : audioFrameList) {
488 iter != audioFrameList.end(); ++iter) { 496 RTC_DCHECK_EQ(mixedAudio->sample_rate_hz_, frame->sample_rate_hz_);
489 if (!iter->muted) { 497 RTC_DCHECK_EQ(
490 MixFrames(mixedAudio, iter->frame, use_limiter); 498 frame->samples_per_channel_,
499 static_cast<size_t>((mixedAudio->sample_rate_hz_ * kFrameDurationInMs) /
500 1000));
501
502 // Mix |f.frame| into |mixedAudio|, with saturation protection.
503 // These effect is applied to |f.frame| itself prior to mixing.
504 if (use_limiter) {
505 // Divide by two to avoid saturation in the mixing.
506 // This is only meaningful if the limiter will be used.
507 *frame >>= 1;
491 } 508 }
492 509 RTC_DCHECK_EQ(frame->num_channels_, mixedAudio->num_channels_);
510 *mixedAudio += *frame;
493 position++; 511 position++;
494 } 512 }
495
496 return 0;
497 }
498
499 // TODO(andrew): consolidate this function with MixFromList.
500 int32_t AudioMixerImpl::MixAnonomouslyFromList(
501 AudioFrame* mixedAudio,
502 const AudioFrameList& audioFrameList) const {
503 RTC_DCHECK_RUN_ON(&thread_checker_);
504 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
505 "MixAnonomouslyFromList(mixedAudio, audioFrameList)");
506
507 if (audioFrameList.empty())
508 return 0;
509
510 for (AudioFrameList::const_iterator iter = audioFrameList.begin();
511 iter != audioFrameList.end(); ++iter) {
512 if (!iter->muted) {
513 MixFrames(mixedAudio, iter->frame, use_limiter_);
514 }
515 }
516 return 0; 513 return 0;
517 } 514 }
518 515
519 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const { 516 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const {
520 RTC_DCHECK_RUN_ON(&thread_checker_); 517 RTC_DCHECK_RUN_ON(&thread_checker_);
521 if (!use_limiter_) { 518 if (!use_limiter_) {
522 return true; 519 return true;
523 } 520 }
524 521
525 // Smoothly limit the mixed frame. 522 // Smoothly limit the mixed frame.
(...skipping 29 matching lines...) Expand all
555 } 552 }
556 553
557 int AudioMixerImpl::GetOutputAudioLevelFullRange() { 554 int AudioMixerImpl::GetOutputAudioLevelFullRange() {
558 RTC_DCHECK_RUN_ON(&thread_checker_); 555 RTC_DCHECK_RUN_ON(&thread_checker_);
559 const int level = audio_level_.LevelFullRange(); 556 const int level = audio_level_.LevelFullRange();
560 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_, 557 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
561 "GetAudioOutputLevelFullRange() => level=%d", level); 558 "GetAudioOutputLevelFullRange() => level=%d", level);
562 return level; 559 return level;
563 } 560 }
564 } // namespace webrtc 561 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_mixer/audio_mixer_impl.h ('k') | webrtc/modules/audio_mixer/test/audio_mixer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698