OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // AudioRendererAlgorithm buffers and transforms audio data. The owner of | 5 // AudioRendererAlgorithm buffers and transforms audio data. The owner of |
6 // this object provides audio data to the object through EnqueueBuffer() and | 6 // this object provides audio data to the object through EnqueueBuffer() and |
7 // requests data from the buffer via FillBuffer(). The owner also sets the | 7 // requests data from the buffer via FillBuffer(). |
8 // playback rate, and the AudioRendererAlgorithm will stretch or compress the | |
9 // buffered audio as necessary to match the playback rate when fulfilling | |
10 // FillBuffer() requests. | |
11 // | 8 // |
12 // This class is *not* thread-safe. Calls to enqueue and retrieve data must be | 9 // This class is *not* thread-safe. Calls to enqueue and retrieve data must be |
13 // locked if called from multiple threads. | 10 // locked if called from multiple threads. |
14 // | 11 // |
15 // AudioRendererAlgorithm uses the Waveform Similarity Overlap and Add (WSOLA) | 12 // AudioRendererAlgorithm uses the Waveform Similarity Overlap and Add (WSOLA) |
16 // algorithm to stretch or compress audio data to meet playback speeds less than | 13 // algorithm to stretch or compress audio data to meet playback speeds less than |
17 // or greater than the natural playback of the audio stream. The algorithm | 14 // or greater than the natural playback of the audio stream. The algorithm |
18 // preserves local properties of the audio, therefore, pitch and harmonics are | 15 // preserves local properties of the audio, therefore, pitch and harmonics are |
19 // are preserved. See audio_renderer_algorith.cc for a more elaborate | 16 // are preserved. See audio_renderer_algorith.cc for a more elaborate |
20 // description of the algorithm. | 17 // description of the algorithm. |
21 // | 18 // |
22 // Audio at very low or very high playback rates are muted to preserve quality. | 19 // Audio at very low or very high playback rates are muted to preserve quality. |
23 // | |
24 | 20 |
25 #ifndef MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ | 21 #ifndef MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ |
26 #define MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ | 22 #define MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ |
27 | 23 |
28 #include "base/memory/ref_counted.h" | 24 #include "base/memory/ref_counted.h" |
29 #include "base/memory/scoped_ptr.h" | 25 #include "base/memory/scoped_ptr.h" |
30 #include "media/audio/audio_parameters.h" | 26 #include "media/audio/audio_parameters.h" |
31 #include "media/base/audio_buffer.h" | 27 #include "media/base/audio_buffer.h" |
32 #include "media/base/audio_buffer_queue.h" | 28 #include "media/base/audio_buffer_queue.h" |
33 | 29 |
34 namespace media { | 30 namespace media { |
35 | 31 |
36 class AudioBus; | 32 class AudioBus; |
37 | 33 |
38 class MEDIA_EXPORT AudioRendererAlgorithm { | 34 class MEDIA_EXPORT AudioRendererAlgorithm { |
39 public: | 35 public: |
40 AudioRendererAlgorithm(); | 36 AudioRendererAlgorithm(); |
41 ~AudioRendererAlgorithm(); | 37 ~AudioRendererAlgorithm(); |
42 | 38 |
43 // Initializes this object with information about the audio stream. | 39 // Initializes this object with information about the audio stream. |
44 void Initialize(float initial_playback_rate, const AudioParameters& params); | 40 void Initialize(const AudioParameters& params); |
45 | 41 |
46 // Tries to fill |requested_frames| frames into |dest| with possibly scaled | 42 // Tries to fill |requested_frames| frames into |dest| with possibly scaled |
47 // data from our |audio_buffer_|. Data is scaled based on the playback rate, | 43 // data from our |audio_buffer_|. Data is scaled based on |playback_rate|, |
48 // using a variation of the Overlap-Add method to combine sample windows. | 44 // using a variation of the Overlap-Add method to combine sample windows. |
49 // | 45 // |
50 // Data from |audio_buffer_| is consumed in proportion to the playback rate. | 46 // Data from |audio_buffer_| is consumed in proportion to the playback rate. |
51 // | 47 // |
52 // Returns the number of frames copied into |dest|. May request more reads via | 48 // Returns the number of frames copied into |dest|. |
53 // |request_read_cb_| before returning. | 49 int FillBuffer(AudioBus* dest, int requested_frames, float playback_rate); |
54 int FillBuffer(AudioBus* dest, int requested_frames); | |
55 | 50 |
56 // Clears |audio_buffer_|. | 51 // Clears |audio_buffer_|. |
57 void FlushBuffers(); | 52 void FlushBuffers(); |
58 | 53 |
59 // Returns the time of the next byte in our data or kNoTimestamp() if current | 54 // Returns the time of the next byte in our data or kNoTimestamp() if current |
60 // time is unknown. | 55 // time is unknown. |
61 base::TimeDelta GetTime(); | 56 base::TimeDelta GetTime(); |
62 | 57 |
63 // Enqueues a buffer. It is called from the owner of the algorithm after a | 58 // Enqueues a buffer. It is called from the owner of the algorithm after a |
64 // read completes. | 59 // read completes. |
65 void EnqueueBuffer(const scoped_refptr<AudioBuffer>& buffer_in); | 60 void EnqueueBuffer(const scoped_refptr<AudioBuffer>& buffer_in); |
66 | 61 |
67 float playback_rate() const { return playback_rate_; } | |
68 void SetPlaybackRate(float new_rate); | |
69 | |
70 // Returns true if |audio_buffer_| is at or exceeds capacity. | 62 // Returns true if |audio_buffer_| is at or exceeds capacity. |
71 bool IsQueueFull(); | 63 bool IsQueueFull(); |
72 | 64 |
73 // Returns the capacity of |audio_buffer_| in frames. | 65 // Returns the capacity of |audio_buffer_| in frames. |
74 int QueueCapacity() const { return capacity_; } | 66 int QueueCapacity() const { return capacity_; } |
75 | 67 |
76 // Increase the capacity of |audio_buffer_| if possible. | 68 // Increase the capacity of |audio_buffer_| if possible. |
77 void IncreaseQueueCapacity(); | 69 void IncreaseQueueCapacity(); |
78 | 70 |
79 // Returns the number of frames left in |audio_buffer_|, which may be larger | 71 // Returns the number of frames left in |audio_buffer_|, which may be larger |
80 // than QueueCapacity() in the event that EnqueueBuffer() delivered more data | 72 // than QueueCapacity() in the event that EnqueueBuffer() delivered more data |
81 // than |audio_buffer_| was intending to hold. | 73 // than |audio_buffer_| was intending to hold. |
82 int frames_buffered() { return audio_buffer_.frames(); } | 74 int frames_buffered() { return audio_buffer_.frames(); } |
83 | 75 |
84 // Returns the samples per second for this audio stream. | 76 // Returns the samples per second for this audio stream. |
85 int samples_per_second() { return samples_per_second_; } | 77 int samples_per_second() { return samples_per_second_; } |
86 | 78 |
87 // Is the sound currently muted? | |
88 bool is_muted() { return muted_; } | |
89 | |
90 private: | 79 private: |
91 // Within |search_block_|, find the block of data that is most similar to | 80 // Within |search_block_|, find the block of data that is most similar to |
92 // |target_block_|, and write it in |optimal_block_|. This method assumes that | 81 // |target_block_|, and write it in |optimal_block_|. This method assumes that |
93 // there is enough data to perform a search, i.e. |search_block_| and | 82 // there is enough data to perform a search, i.e. |search_block_| and |
94 // |target_block_| can be extracted from the available frames. | 83 // |target_block_| can be extracted from the available frames. |
95 void GetOptimalBlock(); | 84 void GetOptimalBlock(); |
96 | 85 |
97 // Read a maximum of |requested_frames| frames from |wsola_output_|. Returns | 86 // Read a maximum of |requested_frames| frames from |wsola_output_|. Returns |
98 // number of frames actually read. | 87 // number of frames actually read. |
99 int WriteCompletedFramesTo( | 88 int WriteCompletedFramesTo( |
100 int requested_frames, int output_offset, AudioBus* dest); | 89 int requested_frames, int output_offset, AudioBus* dest); |
101 | 90 |
102 // Fill |dest| with frames from |audio_buffer_| starting from frame | 91 // Fill |dest| with frames from |audio_buffer_| starting from frame |
103 // |read_offset_frames|. |dest| is expected to have the same number of | 92 // |read_offset_frames|. |dest| is expected to have the same number of |
104 // channels as |audio_buffer_|. A negative offset, i.e. | 93 // channels as |audio_buffer_|. A negative offset, i.e. |
105 // |read_offset_frames| < 0, is accepted assuming that |audio_buffer| is zero | 94 // |read_offset_frames| < 0, is accepted assuming that |audio_buffer| is zero |
106 // for negative indices. This might happen for few first frames. This method | 95 // for negative indices. This might happen for few first frames. This method |
107 // assumes there is enough frames to fill |dest|, i.e. |read_offset_frames| + | 96 // assumes there is enough frames to fill |dest|, i.e. |read_offset_frames| + |
108 // |dest->frames()| does not extend to future. | 97 // |dest->frames()| does not extend to future. |
109 void PeekAudioWithZeroPrepend(int read_offset_frames, AudioBus* dest); | 98 void PeekAudioWithZeroPrepend(int read_offset_frames, AudioBus* dest); |
110 | 99 |
111 // Run one iteration of WSOLA, if there are sufficient frames. This will | 100 // Run one iteration of WSOLA, if there are sufficient frames. This will |
112 // overlap-and-add one block to |wsola_output_|, hence, |num_complete_frames_| | 101 // overlap-and-add one block to |wsola_output_|, hence, |num_complete_frames_| |
113 // is incremented by |ola_hop_size_|. | 102 // is incremented by |ola_hop_size_|. |
114 bool RunOneWsolaIteration(); | 103 bool RunOneWsolaIteration(float playback_rate); |
115 | 104 |
116 // Seek |audio_buffer_| forward to remove frames from input that are not used | 105 // Seek |audio_buffer_| forward to remove frames from input that are not used |
117 // any more. State of the WSOLA will be updated accordingly. | 106 // any more. State of the WSOLA will be updated accordingly. |
118 void RemoveOldInputFrames(); | 107 void RemoveOldInputFrames(float playback_rate); |
119 | 108 |
120 // Update |output_time_| by |time_change|. In turn |search_block_index_| is | 109 // Update |output_time_| by |time_change|. In turn |search_block_index_| is |
121 // updated. | 110 // updated. |
122 void UpdateOutputTime(double time_change); | 111 void UpdateOutputTime(float playback_rate, double time_change); |
123 | 112 |
124 // Is |target_block_| fully within |search_block_|? If so, we don't need to | 113 // Is |target_block_| fully within |search_block_|? If so, we don't need to |
125 // perform the search. | 114 // perform the search. |
126 bool TargetIsWithinSearchRegion() const; | 115 bool TargetIsWithinSearchRegion() const; |
127 | 116 |
128 // Do we have enough data to perform one round of WSOLA? | 117 // Do we have enough data to perform one round of WSOLA? |
129 bool CanPerformWsola() const; | 118 bool CanPerformWsola() const; |
130 | 119 |
131 // Number of channels in audio stream. | 120 // Number of channels in audio stream. |
132 int channels_; | 121 int channels_; |
133 | 122 |
134 // Sample rate of audio stream. | 123 // Sample rate of audio stream. |
135 int samples_per_second_; | 124 int samples_per_second_; |
136 | 125 |
137 // Used by algorithm to scale output. | |
138 float playback_rate_; | |
139 | |
140 // Buffered audio data. | 126 // Buffered audio data. |
141 AudioBufferQueue audio_buffer_; | 127 AudioBufferQueue audio_buffer_; |
142 | 128 |
143 // True if the audio should be muted. | |
144 bool muted_; | |
145 | |
146 // If muted, keep track of partial frames that should have been skipped over. | 129 // If muted, keep track of partial frames that should have been skipped over. |
147 double muted_partial_frame_; | 130 double muted_partial_frame_; |
148 | 131 |
149 // How many frames to have in the queue before we report the queue is full. | 132 // How many frames to have in the queue before we report the queue is full. |
150 int capacity_; | 133 int capacity_; |
151 | 134 |
152 // Book keeping of the current time of generated audio, in frames. This | 135 // Book keeping of the current time of generated audio, in frames. This |
153 // should be appropriately updated when out samples are generated, regardless | 136 // should be appropriately updated when out samples are generated, regardless |
154 // of whether we push samples out when FillBuffer() is called or we store | 137 // of whether we push samples out when FillBuffer() is called or we store |
155 // audio in |wsola_output_| for the subsequent calls to FillBuffer(). | 138 // audio in |wsola_output_| for the subsequent calls to FillBuffer(). |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 // searched for a block (|optimal_block_|) that is most similar to | 195 // searched for a block (|optimal_block_|) that is most similar to |
213 // |target_block_|. | 196 // |target_block_|. |
214 scoped_ptr<AudioBus> target_block_; | 197 scoped_ptr<AudioBus> target_block_; |
215 | 198 |
216 DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithm); | 199 DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithm); |
217 }; | 200 }; |
218 | 201 |
219 } // namespace media | 202 } // namespace media |
220 | 203 |
221 #endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ | 204 #endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_ |
OLD | NEW |