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:
kylep@chromium.org
2009-07-10 21:04:44 +00:00
commit 8fd29c03e6
5 arquivos alterados com 59 adições e 19 exclusões
+13 -1
Ver Arquivo
@@ -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.
+23 -11
Ver Arquivo
@@ -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);
};
+15 -7
Ver Arquivo
@@ -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;