1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/speech/audio_buffer.h"
6 
7 #include "base/check_op.h"
8 
9 namespace content {
10 
AudioChunk(int bytes_per_sample)11 AudioChunk::AudioChunk(int bytes_per_sample)
12     : bytes_per_sample_(bytes_per_sample) {
13 }
14 
AudioChunk(size_t length,int bytes_per_sample)15 AudioChunk::AudioChunk(size_t length, int bytes_per_sample)
16     : data_string_(length, '\0'), bytes_per_sample_(bytes_per_sample) {
17   DCHECK_EQ(length % bytes_per_sample, 0U);
18 }
19 
AudioChunk(const uint8_t * data,size_t length,int bytes_per_sample)20 AudioChunk::AudioChunk(const uint8_t* data, size_t length, int bytes_per_sample)
21     : data_string_(reinterpret_cast<const char*>(data), length),
22       bytes_per_sample_(bytes_per_sample) {
23   DCHECK_EQ(length % bytes_per_sample, 0U);
24 }
25 
IsEmpty() const26 bool AudioChunk::IsEmpty() const {
27   return data_string_.empty();
28 }
29 
NumSamples() const30 size_t AudioChunk::NumSamples() const {
31   return data_string_.size() / bytes_per_sample_;
32 }
33 
AsString() const34 const std::string& AudioChunk::AsString() const {
35   return data_string_;
36 }
37 
GetSample16(size_t index) const38 int16_t AudioChunk::GetSample16(size_t index) const {
39   DCHECK(index < (data_string_.size() / sizeof(int16_t)));
40   return SamplesData16()[index];
41 }
42 
SamplesData16() const43 const int16_t* AudioChunk::SamplesData16() const {
44   return reinterpret_cast<const int16_t*>(data_string_.data());
45 }
46 
AudioBuffer(int bytes_per_sample)47 AudioBuffer::AudioBuffer(int bytes_per_sample)
48     : bytes_per_sample_(bytes_per_sample) {
49   DCHECK(bytes_per_sample == 1 ||
50          bytes_per_sample == 2 ||
51          bytes_per_sample == 4);
52 }
53 
~AudioBuffer()54 AudioBuffer::~AudioBuffer() {
55   Clear();
56 }
57 
Enqueue(const uint8_t * data,size_t length)58 void AudioBuffer::Enqueue(const uint8_t* data, size_t length) {
59   chunks_.push_back(new AudioChunk(data, length, bytes_per_sample_));
60 }
61 
DequeueSingleChunk()62 scoped_refptr<AudioChunk> AudioBuffer::DequeueSingleChunk() {
63   DCHECK(!chunks_.empty());
64   scoped_refptr<AudioChunk> chunk(chunks_.front());
65   chunks_.pop_front();
66   return chunk;
67 }
68 
DequeueAll()69 scoped_refptr<AudioChunk> AudioBuffer::DequeueAll() {
70   size_t resulting_length = 0;
71   ChunksContainer::const_iterator it;
72   // In order to improve performance, calulate in advance the total length
73   // and then copy the chunks.
74   for (it = chunks_.begin(); it != chunks_.end(); ++it) {
75     resulting_length += (*it)->AsString().length();
76   }
77   scoped_refptr<AudioChunk> chunk(
78       new AudioChunk(resulting_length, bytes_per_sample_));
79   uint8_t* dest = chunk->writable_data();
80   for (it = chunks_.begin(); it != chunks_.end(); ++it) {
81     memcpy(dest, (*it)->AsString().data(), (*it)->AsString().length());
82     dest += (*it)->AsString().length();
83   }
84   Clear();
85   return chunk;
86 }
87 
Clear()88 void AudioBuffer::Clear() {
89   chunks_.clear();
90 }
91 
IsEmpty() const92 bool AudioBuffer::IsEmpty() const {
93   return chunks_.empty();
94 }
95 
96 }  // namespace content
97