| 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 |