Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / media / base / audio_fifo.cc
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 "media/base/audio_fifo.h"
6
7 #include "base/logging.h"
8
9 namespace media {
10
11 // Given current position in the FIFO, the maximum number of elements in the
12 // FIFO and the size of the input; this method provides two output results:
13 // |size| and |wrap_size|. These two results can then be utilized for memcopy
14 // operations to and from the FIFO.
15 // Under "normal" circumstances, |size| will be equal to |in_size| and
16 // |wrap_size| will be zero. This case corresponding to the non-wrapping case
17 // where we have not yet reached the "edge" of the FIFO. If |pos| + |in_size|
18 // exceeds the total size of the FIFO, we must wrap around and start reusing
19 // a part the allocated memory. The size of this part is given by |wrap_size|.
20 static void GetSizes(
21     int pos, int max_size, int in_size, int* size, int* wrap_size) {
22   if (pos + in_size > max_size) {
23     // Wrapping is required => derive size of each segment.
24     *size = max_size - pos;
25     *wrap_size = in_size - *size;
26   } else {
27     // Wrapping is not required.
28     *size = in_size;
29     *wrap_size = 0;
30   }
31 }
32
33 // Updates the read/write position with |step| modulo the maximum number of
34 // elements in the FIFO to ensure that the position counters wraps around at
35 // the endpoint.
36 static int UpdatePos(int pos, int step, int max_size) {
37   return ((pos + step) % max_size);
38 }
39
40 AudioFifo::AudioFifo(int channels, int frames)
41     : audio_bus_(AudioBus::Create(channels, frames)),
42       max_frames_(frames),
43       frames_pushed_(0),
44       frames_consumed_(0),
45       read_pos_(0),
46       write_pos_(0) {}
47
48 AudioFifo::~AudioFifo() {}
49
50 int AudioFifo::frames() const {
51   int delta = frames_pushed_ - frames_consumed_;
52   return delta;
53 }
54
55 void AudioFifo::Push(const AudioBus* source) {
56   DCHECK(source);
57   DCHECK_EQ(source->channels(), audio_bus_->channels());
58
59   // Ensure that there is space for the new data in the FIFO.
60   const int source_size = source->frames();
61   CHECK_LE(source_size + frames(), max_frames_);
62
63   // Figure out if wrapping is needed and if so what segment sizes we need
64   // when adding the new audio bus content to the FIFO.
65   int append_size = 0;
66   int wrap_size = 0;
67   GetSizes(write_pos_, max_frames(), source_size, &append_size, &wrap_size);
68
69   // Copy all channels from the source to the FIFO. Wrap around if needed.
70   for (int ch = 0; ch < source->channels(); ++ch) {
71     float* dest = audio_bus_->channel(ch);
72     const float* src = source->channel(ch);
73
74     // Append part of (or the complete) source to the FIFO.
75     memcpy(&dest[write_pos_], &src[0], append_size * sizeof(src[0]));
76     if (wrap_size > 0) {
77       // Wrapping is needed: copy remaining part from the source to the FIFO.
78       memcpy(&dest[0], &src[append_size], wrap_size * sizeof(src[0]));
79     }
80   }
81
82   frames_pushed_ += source_size;
83   DCHECK_LE(frames(), max_frames());
84   write_pos_ = UpdatePos(write_pos_, source_size, max_frames());
85 }
86
87 void AudioFifo::Consume(AudioBus* destination,
88                         int start_frame,
89                         int frames_to_consume) {
90   DCHECK(destination);
91   DCHECK_EQ(destination->channels(), audio_bus_->channels());
92
93   // It is not possible to ask for more data than what is available in the FIFO.
94   CHECK_LE(frames_to_consume, frames());
95
96   // A copy from the FIFO to |destination| will only be performed if the
97   // allocated memory in |destination| is sufficient.
98   CHECK_LE(frames_to_consume + start_frame, destination->frames());
99
100   // Figure out if wrapping is needed and if so what segment sizes we need
101   // when removing audio bus content from the FIFO.
102   int consume_size = 0;
103   int wrap_size = 0;
104   GetSizes(read_pos_, max_frames(), frames_to_consume,
105            &consume_size, &wrap_size);
106
107   // For all channels, remove the requested amount of data from the FIFO
108   // and copy the content to the destination. Wrap around if needed.
109   for (int ch = 0; ch < destination->channels(); ++ch) {
110     float* dest = destination->channel(ch);
111     const float* src = audio_bus_->channel(ch);
112
113     // Copy a selected part of the FIFO to the destination.
114     memcpy(&dest[start_frame], &src[read_pos_], consume_size * sizeof(src[0]));
115     if (wrap_size > 0) {
116       // Wrapping is needed: copy remaining part to the destination.
117       memcpy(&dest[consume_size + start_frame], &src[0],
118              wrap_size * sizeof(src[0]));
119     }
120   }
121
122   frames_consumed_ += frames_to_consume;
123   read_pos_ = UpdatePos(read_pos_, frames_to_consume, max_frames());
124 }
125
126 void AudioFifo::Clear() {
127   frames_pushed_ = 0;
128   frames_consumed_ = 0;
129   read_pos_ = 0;
130   write_pos_ = 0;
131 }
132
133 }  // namespace media