Modify OLA to use window size in seconds instead of bytes.
BUG=16011 TEST=none Review URL: http://codereview.chromium.org/157001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20416 0039d316-1c4b-4281-b951-d872f2087c98
Esse commit está contido em:
@@ -15,6 +15,7 @@ const size_t kDefaultMaxQueueSizeInBytes = 65536;
|
||||
|
||||
AudioRendererAlgorithmBase::AudioRendererAlgorithmBase()
|
||||
: channels_(0),
|
||||
sample_rate_(0),
|
||||
sample_bytes_(0),
|
||||
playback_rate_(0.0f) {
|
||||
}
|
||||
@@ -22,15 +23,22 @@ AudioRendererAlgorithmBase::AudioRendererAlgorithmBase()
|
||||
AudioRendererAlgorithmBase::~AudioRendererAlgorithmBase() {}
|
||||
|
||||
void AudioRendererAlgorithmBase::Initialize(int channels,
|
||||
int sample_rate,
|
||||
int sample_bits,
|
||||
float initial_playback_rate,
|
||||
RequestReadCallback* callback) {
|
||||
DCHECK_GT(channels, 0);
|
||||
DCHECK_LE(channels, 6) << "We only support <=6 channel audio.";
|
||||
DCHECK_GT(sample_rate, 0);
|
||||
DCHECK_LE(sample_rate, 256000)
|
||||
<< "We only support sample rates at or below 256000Hz.";
|
||||
DCHECK_GT(sample_bits, 0);
|
||||
DCHECK(callback);
|
||||
DCHECK_LE(sample_bits, 32) << "We only support 8, 16, 32 bit audio.";
|
||||
DCHECK_EQ(sample_bits % 8, 0) << "We only support 8, 16, 32 bit audio.";
|
||||
DCHECK(callback);
|
||||
|
||||
channels_ = channels;
|
||||
sample_rate_ = sample_rate;
|
||||
sample_bytes_ = sample_bits / 8;
|
||||
request_read_callback_.reset(callback);
|
||||
|
||||
@@ -88,6 +96,10 @@ int AudioRendererAlgorithmBase::channels() {
|
||||
return channels_;
|
||||
}
|
||||
|
||||
int AudioRendererAlgorithmBase::sample_rate() {
|
||||
return sample_rate_;
|
||||
}
|
||||
|
||||
int AudioRendererAlgorithmBase::sample_bytes() {
|
||||
return sample_bytes_;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ class AudioRendererAlgorithmBase {
|
||||
|
||||
// Checks validity of audio parameters and takes ownership of |callback|.
|
||||
virtual void Initialize(int channels,
|
||||
int sample_rate,
|
||||
int sample_bits,
|
||||
float initial_playback_rate,
|
||||
RequestReadCallback* callback);
|
||||
@@ -82,12 +83,16 @@ class AudioRendererAlgorithmBase {
|
||||
// Number of audio channels.
|
||||
virtual int channels();
|
||||
|
||||
// Sample rate in hertz.
|
||||
virtual int sample_rate();
|
||||
|
||||
// Number of bytes per sample per channel.
|
||||
virtual int sample_bytes();
|
||||
|
||||
private:
|
||||
// Audio properties.
|
||||
int channels_;
|
||||
int sample_rate_;
|
||||
int sample_bytes_;
|
||||
|
||||
// Used by algorithm to scale output.
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
|
||||
namespace media {
|
||||
|
||||
// Default window size in bytes.
|
||||
// TODO(kylep): base the window size in seconds, not bytes.
|
||||
const size_t kDefaultWindowSize = 4096;
|
||||
// Default window and crossfade lengths in seconds.
|
||||
const double kDefaultWindowLength = 0.08;
|
||||
const double kDefaultCrossfadeLength = 0.008;
|
||||
|
||||
AudioRendererAlgorithmOLA::AudioRendererAlgorithmOLA()
|
||||
: input_step_(0),
|
||||
output_step_(0) {
|
||||
output_step_(0),
|
||||
window_size_(0) {
|
||||
}
|
||||
|
||||
AudioRendererAlgorithmOLA::~AudioRendererAlgorithmOLA() {
|
||||
@@ -47,7 +48,7 @@ size_t AudioRendererAlgorithmOLA::FillBuffer(DataBuffer* buffer_out) {
|
||||
// on the UI side or in set_playback_rate().
|
||||
while (dest_remaining >= output_step_ + crossfade_size_) {
|
||||
// If we don't have enough data to completely finish this loop, quit.
|
||||
if (QueueSize() < kDefaultWindowSize)
|
||||
if (QueueSize() < window_size_)
|
||||
break;
|
||||
|
||||
// Copy bulk of data to output (including some to crossfade to the next
|
||||
@@ -89,7 +90,7 @@ size_t AudioRendererAlgorithmOLA::FillBuffer(DataBuffer* buffer_out) {
|
||||
|
||||
// Advance pointers again.
|
||||
AdvanceInputPosition(crossfade_size);
|
||||
dest += crossfade_size;
|
||||
dest += crossfade_size_;
|
||||
}
|
||||
return dest_written;
|
||||
}
|
||||
@@ -97,21 +98,32 @@ size_t AudioRendererAlgorithmOLA::FillBuffer(DataBuffer* buffer_out) {
|
||||
void AudioRendererAlgorithmOLA::set_playback_rate(float new_rate) {
|
||||
AudioRendererAlgorithmBase::set_playback_rate(new_rate);
|
||||
|
||||
// Calculate the window size from our default length and our audio properties.
|
||||
// Precision is not an issue because we will round this to a sample boundary.
|
||||
// This will not overflow because each parameter is checked in Initialize().
|
||||
window_size_ = static_cast<size_t>(sample_rate()
|
||||
* sample_bytes()
|
||||
* channels()
|
||||
* kDefaultWindowLength);
|
||||
|
||||
// Adjusting step sizes to accomodate requested playback rate.
|
||||
if (playback_rate() > 1.0f) {
|
||||
input_step_ = kDefaultWindowSize;
|
||||
input_step_ = window_size_;
|
||||
output_step_ = static_cast<size_t>(ceil(
|
||||
static_cast<float>(kDefaultWindowSize / playback_rate())));
|
||||
static_cast<float>(window_size_ / playback_rate())));
|
||||
} else {
|
||||
input_step_ = static_cast<size_t>(ceil(
|
||||
static_cast<float>(kDefaultWindowSize * playback_rate())));
|
||||
output_step_ = kDefaultWindowSize;
|
||||
static_cast<float>(window_size_ * playback_rate())));
|
||||
output_step_ = window_size_;
|
||||
}
|
||||
AlignToSampleBoundary(&input_step_);
|
||||
AlignToSampleBoundary(&output_step_);
|
||||
|
||||
// Calculate length for crossfading.
|
||||
crossfade_size_ = kDefaultWindowSize / 10;
|
||||
crossfade_size_ = static_cast<size_t>(sample_rate()
|
||||
* sample_bytes()
|
||||
* channels()
|
||||
* kDefaultCrossfadeLength);
|
||||
AlignToSampleBoundary(&crossfade_size_);
|
||||
|
||||
// To keep true to playback rate, modify the steps.
|
||||
|
||||
@@ -48,6 +48,9 @@ class AudioRendererAlgorithmOLA : public AudioRendererAlgorithmBase {
|
||||
// Length for crossfade in bytes.
|
||||
size_t crossfade_size_;
|
||||
|
||||
// Window size, in bytes (calculated from audio properties).
|
||||
size_t window_size_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmOLA);
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ using file_util::ScopedFILE;
|
||||
using media::AudioRendererAlgorithmOLA;
|
||||
using media::DataBuffer;
|
||||
|
||||
const size_t kDefaultWindowSize = 4096;
|
||||
const double kDefaultWindowLength = 0.08;
|
||||
|
||||
struct WavHeader {
|
||||
int32 riff;
|
||||
@@ -42,15 +42,16 @@ struct WavHeader {
|
||||
// Dummy class to feed data to OLA algorithm. Necessary to create callback.
|
||||
class Dummy {
|
||||
public:
|
||||
Dummy(FILE* in, AudioRendererAlgorithmOLA* ola)
|
||||
Dummy(FILE* in, AudioRendererAlgorithmOLA* ola, size_t window_size)
|
||||
: input_(in),
|
||||
ola_(ola) {
|
||||
ola_(ola),
|
||||
window_size_(window_size) {
|
||||
}
|
||||
|
||||
void ReadDataForAlg() {
|
||||
scoped_refptr<DataBuffer> b(new DataBuffer());
|
||||
uint8* buf = b->GetWritableData(kDefaultWindowSize);
|
||||
if (fread(buf, 1, kDefaultWindowSize, input_) > 0) {
|
||||
uint8* buf = b->GetWritableData(window_size_);
|
||||
if (fread(buf, 1, window_size_, input_) > 0) {
|
||||
ola_->EnqueueBuffer(b.get());
|
||||
}
|
||||
}
|
||||
@@ -58,6 +59,7 @@ class Dummy {
|
||||
private:
|
||||
FILE* input_;
|
||||
AudioRendererAlgorithmOLA* ola_;
|
||||
size_t window_size_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Dummy);
|
||||
};
|
||||
@@ -104,11 +106,17 @@ int main(int argc, const char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t window_size = static_cast<size_t>(wav.sample_rate
|
||||
* (wav.bit_rate / 8)
|
||||
* wav.channels
|
||||
* kDefaultWindowLength);
|
||||
|
||||
// Instantiate dummy class and callback to feed data to |ola|.
|
||||
Dummy guy(input.get(), &ola);
|
||||
Dummy guy(input.get(), &ola, window_size);
|
||||
AudioRendererAlgorithmOLA::RequestReadCallback* cb =
|
||||
NewCallback(&guy, &Dummy::ReadDataForAlg);
|
||||
ola.Initialize(wav.channels,
|
||||
wav.sample_rate,
|
||||
wav.bit_rate,
|
||||
static_cast<float>(playback_rate),
|
||||
cb);
|
||||
@@ -129,7 +137,7 @@ int main(int argc, const char** argv) {
|
||||
|
||||
// Create buffer to be filled by |ola|.
|
||||
scoped_refptr<DataBuffer> buffer(new DataBuffer());
|
||||
uint8* buf = buffer->GetWritableData(kDefaultWindowSize);
|
||||
uint8* buf = buffer->GetWritableData(window_size);
|
||||
|
||||
// Keep track of bytes written to disk and bytes copied to |b|.
|
||||
size_t bytes_written = 0;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário