Commit ca148891 authored by kxing@chromium.org's avatar kxing@chromium.org

Added support for multiple sampling rates on Windows.


Review URL: https://chromiumcodereview.appspot.com/10818010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148766 0039d316-1c4b-4281-b951-d872f2087c98
parent 09771af1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/audio_capturer.h"
#include "remoting/proto/audio.pb.h"
namespace remoting {
bool AudioCapturer::IsValidSampleRate(int sample_rate) {
switch (sample_rate) {
case AudioPacket::SAMPLING_RATE_44100:
case AudioPacket::SAMPLING_RATE_48000:
return true;
default:
return false;
}
}
} // namespace remoting
...@@ -7,10 +7,11 @@ ...@@ -7,10 +7,11 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "remoting/proto/audio.pb.h"
namespace remoting { namespace remoting {
class AudioPacket;
class AudioCapturer { class AudioCapturer {
public: public:
typedef base::Callback<void(scoped_ptr<AudioPacket> packet)> typedef base::Callback<void(scoped_ptr<AudioPacket> packet)>
...@@ -20,8 +21,8 @@ class AudioCapturer { ...@@ -20,8 +21,8 @@ class AudioCapturer {
static scoped_ptr<AudioCapturer> Create(); static scoped_ptr<AudioCapturer> Create();
// Capturers should sample at a 44.1 kHz sampling rate, in uncompressed PCM // Capturers should sample at a 44.1 or 48 kHz sampling rate, in uncompressed
// stereo format. Capturers may choose the number of frames per packet. // PCM stereo format. Capturers may choose the number of frames per packet.
// Returns true on success. // Returns true on success.
virtual bool Start(const PacketCapturedCallback& callback) = 0; virtual bool Start(const PacketCapturedCallback& callback) = 0;
// Stops the audio capturer, and frees the OS-specific audio capture // Stops the audio capturer, and frees the OS-specific audio capture
...@@ -29,6 +30,8 @@ class AudioCapturer { ...@@ -29,6 +30,8 @@ class AudioCapturer {
virtual void Stop() = 0; virtual void Stop() = 0;
// Returns true if the audio capturer is running. // Returns true if the audio capturer is running.
virtual bool IsRunning() = 0; virtual bool IsRunning() = 0;
static bool IsValidSampleRate(int sample_rate);
}; };
} // namespace remoting } // namespace remoting
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
namespace { namespace {
const int kChannels = 2; const int kChannels = 2;
const int kBitsPerSample = 16; const int kBitsPerSample = 16;
const int kSamplesPerSecond = 44100;
const int kBitsPerByte = 8; const int kBitsPerByte = 8;
// Conversion factor from 100ns to 1ms. // Conversion factor from 100ns to 1ms.
const int kHnsToMs = 10000; const int kHnsToMs = 10000;
...@@ -48,6 +47,8 @@ class AudioCapturerWin : public AudioCapturer { ...@@ -48,6 +47,8 @@ class AudioCapturerWin : public AudioCapturer {
PacketCapturedCallback callback_; PacketCapturedCallback callback_;
AudioPacket::SamplingRate sampling_rate_;
scoped_ptr<base::RepeatingTimer<AudioCapturerWin> > capture_timer_; scoped_ptr<base::RepeatingTimer<AudioCapturerWin> > capture_timer_;
base::TimeDelta audio_device_period_; base::TimeDelta audio_device_period_;
...@@ -62,8 +63,9 @@ class AudioCapturerWin : public AudioCapturer { ...@@ -62,8 +63,9 @@ class AudioCapturerWin : public AudioCapturer {
DISALLOW_COPY_AND_ASSIGN(AudioCapturerWin); DISALLOW_COPY_AND_ASSIGN(AudioCapturerWin);
}; };
AudioCapturerWin::AudioCapturerWin() { AudioCapturerWin::AudioCapturerWin()
thread_checker_.DetachFromThread(); : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID) {
thread_checker_.DetachFromThread();
} }
AudioCapturerWin::~AudioCapturerWin() { AudioCapturerWin::~AudioCapturerWin() {
...@@ -131,13 +133,19 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) { ...@@ -131,13 +133,19 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) {
case WAVE_FORMAT_IEEE_FLOAT: case WAVE_FORMAT_IEEE_FLOAT:
// Intentional fall-through. // Intentional fall-through.
case WAVE_FORMAT_PCM: case WAVE_FORMAT_PCM:
if (!AudioCapturer::IsValidSampleRate(wave_format_ex_->nSamplesPerSec)) {
LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz.";
return false;
}
sampling_rate_ = static_cast<AudioPacket::SamplingRate>(
wave_format_ex_->nSamplesPerSec);
wave_format_ex_->wFormatTag = WAVE_FORMAT_PCM; wave_format_ex_->wFormatTag = WAVE_FORMAT_PCM;
wave_format_ex_->nChannels = kChannels; wave_format_ex_->nChannels = kChannels;
wave_format_ex_->nSamplesPerSec = kSamplesPerSecond;
wave_format_ex_->wBitsPerSample = kBitsPerSample; wave_format_ex_->wBitsPerSample = kBitsPerSample;
wave_format_ex_->nBlockAlign = kChannels * kBitsPerSample / kBitsPerByte; wave_format_ex_->nBlockAlign = kChannels * kBitsPerSample / kBitsPerByte;
wave_format_ex_->nAvgBytesPerSec = wave_format_ex_->nAvgBytesPerSec =
kSamplesPerSecond * kChannels * kBitsPerSample / kBitsPerByte; sampling_rate_ * kChannels * kBitsPerSample / kBitsPerByte;
break; break;
case WAVE_FORMAT_EXTENSIBLE: { case WAVE_FORMAT_EXTENSIBLE: {
PWAVEFORMATEXTENSIBLE wave_format_extensible = PWAVEFORMATEXTENSIBLE wave_format_extensible =
...@@ -145,16 +153,24 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) { ...@@ -145,16 +153,24 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) {
static_cast<WAVEFORMATEX*>(wave_format_ex_)); static_cast<WAVEFORMATEX*>(wave_format_ex_));
if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
wave_format_extensible->SubFormat)) { wave_format_extensible->SubFormat)) {
if (!AudioCapturer::IsValidSampleRate(
wave_format_extensible->Format.nSamplesPerSec)) {
LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz.";
return false;
}
sampling_rate_ = static_cast<AudioPacket::SamplingRate>(
wave_format_extensible->Format.nSamplesPerSec);
wave_format_extensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wave_format_extensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
wave_format_extensible->Samples.wValidBitsPerSample = kBitsPerSample; wave_format_extensible->Samples.wValidBitsPerSample = kBitsPerSample;
wave_format_extensible->Format.nChannels = kChannels; wave_format_extensible->Format.nChannels = kChannels;
wave_format_extensible->Format.nSamplesPerSec = kSamplesPerSecond; wave_format_extensible->Format.nSamplesPerSec = sampling_rate_;
wave_format_extensible->Format.wBitsPerSample = kBitsPerSample; wave_format_extensible->Format.wBitsPerSample = kBitsPerSample;
wave_format_extensible->Format.nBlockAlign = wave_format_extensible->Format.nBlockAlign =
kChannels * kBitsPerSample / kBitsPerByte; kChannels * kBitsPerSample / kBitsPerByte;
wave_format_extensible->Format.nAvgBytesPerSec = wave_format_extensible->Format.nAvgBytesPerSec =
kSamplesPerSecond * kChannels * kBitsPerSample / kBitsPerByte; sampling_rate_ * kChannels * kBitsPerSample / kBitsPerByte;
} else { } else {
LOG(ERROR) << "Failed to force 16-bit samples"; LOG(ERROR) << "Failed to force 16-bit samples";
return false; return false;
...@@ -162,7 +178,7 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) { ...@@ -162,7 +178,7 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) {
break; break;
} }
default: default:
LOG(ERROR) << "Failed to force 16-bit samples"; LOG(ERROR) << "Failed to force 16-bit PCM";
return false; return false;
} }
...@@ -221,6 +237,7 @@ bool AudioCapturerWin::IsRunning() { ...@@ -221,6 +237,7 @@ bool AudioCapturerWin::IsRunning() {
} }
void AudioCapturerWin::DoCapture() { void AudioCapturerWin::DoCapture() {
DCHECK(AudioCapturer::IsValidSampleRate(sampling_rate_));
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(IsRunning()); DCHECK(IsRunning());
...@@ -249,6 +266,7 @@ void AudioCapturerWin::DoCapture() { ...@@ -249,6 +266,7 @@ void AudioCapturerWin::DoCapture() {
scoped_ptr<AudioPacket> packet = scoped_ptr<AudioPacket>(new AudioPacket()); scoped_ptr<AudioPacket> packet = scoped_ptr<AudioPacket>(new AudioPacket());
packet->set_data(data, frames * wave_format_ex_->nBlockAlign); packet->set_data(data, frames * wave_format_ex_->nBlockAlign);
packet->set_sampling_rate(sampling_rate_);
callback_.Run(packet.Pass()); callback_.Run(packet.Pass());
......
...@@ -1130,6 +1130,7 @@ ...@@ -1130,6 +1130,7 @@
'../crypto/crypto.gyp:crypto', '../crypto/crypto.gyp:crypto',
], ],
'sources': [ 'sources': [
'host/audio_capturer.cc',
'host/audio_capturer.h', 'host/audio_capturer.h',
'host/audio_capturer_linux.cc', 'host/audio_capturer_linux.cc',
'host/audio_capturer_mac.cc', 'host/audio_capturer_mac.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment