OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 16 matching lines...) Expand all Loading... | |
27 */ | 27 */ |
28 | 28 |
29 #include "platform/audio/AudioBus.h" | 29 #include "platform/audio/AudioBus.h" |
30 #include "platform/audio/MultiChannelResampler.h" | 30 #include "platform/audio/MultiChannelResampler.h" |
31 #include "wtf/PtrUtil.h" | 31 #include "wtf/PtrUtil.h" |
32 | 32 |
33 namespace blink { | 33 namespace blink { |
34 | 34 |
35 namespace { | 35 namespace { |
36 | 36 |
37 // ChannelProvider provides a single channel of audio data (one channel at a tim e) for each channel | 37 // ChannelProvider provides a single channel of audio data (one channel at a |
38 // of data provided to us in a multi-channel provider. | 38 // time) for each channel of data provided to us in a multi-channel provider. |
39 | 39 |
40 class ChannelProvider final : public AudioSourceProvider { | 40 class ChannelProvider final : public AudioSourceProvider { |
41 public: | 41 public: |
42 ChannelProvider(AudioSourceProvider* multiChannelProvider, | 42 ChannelProvider(AudioSourceProvider* multiChannelProvider, |
43 unsigned numberOfChannels) | 43 unsigned numberOfChannels) |
44 : m_multiChannelProvider(multiChannelProvider), | 44 : m_multiChannelProvider(multiChannelProvider), |
45 m_numberOfChannels(numberOfChannels), | 45 m_numberOfChannels(numberOfChannels), |
46 m_currentChannel(0), | 46 m_currentChannel(0), |
47 m_framesToProcess(0) {} | 47 m_framesToProcess(0) {} |
48 | 48 |
49 // provideInput() will be called once for each channel, starting with the firs t channel. | 49 // provideInput() will be called once for each channel, starting with the |
50 // Each time it's called, it will provide the next channel of data. | 50 // first channel. Each time it's called, it will provide the next channel of |
51 // data. | |
51 void provideInput(AudioBus* bus, size_t framesToProcess) override { | 52 void provideInput(AudioBus* bus, size_t framesToProcess) override { |
52 bool isBusGood = bus && bus->numberOfChannels() == 1; | 53 bool isBusGood = bus && bus->numberOfChannels() == 1; |
53 ASSERT(isBusGood); | 54 ASSERT(isBusGood); |
54 if (!isBusGood) | 55 if (!isBusGood) |
55 return; | 56 return; |
56 | 57 |
57 // Get the data from the multi-channel provider when the first channel asks for it. | 58 // Get the data from the multi-channel provider when the first channel asks |
58 // For subsequent channels, we can just dish out the channel data from that (stored in m_multiChannelBus). | 59 // for it. For subsequent channels, we can just dish out the channel data |
60 // from that (stored in m_multiChannelBus). | |
59 if (!m_currentChannel) { | 61 if (!m_currentChannel) { |
60 m_framesToProcess = framesToProcess; | 62 m_framesToProcess = framesToProcess; |
61 m_multiChannelBus = AudioBus::create(m_numberOfChannels, framesToProcess); | 63 m_multiChannelBus = AudioBus::create(m_numberOfChannels, framesToProcess); |
62 m_multiChannelProvider->provideInput(m_multiChannelBus.get(), | 64 m_multiChannelProvider->provideInput(m_multiChannelBus.get(), |
63 framesToProcess); | 65 framesToProcess); |
64 } | 66 } |
65 | 67 |
66 // All channels must ask for the same amount. This should always be the case , but let's just make sure. | 68 // All channels must ask for the same amount. This should always be the |
69 // case, but let's just make sure. | |
67 bool isGood = | 70 bool isGood = |
68 m_multiChannelBus.get() && framesToProcess == m_framesToProcess; | 71 m_multiChannelBus.get() && framesToProcess == m_framesToProcess; |
69 ASSERT(isGood); | 72 ASSERT(isGood); |
70 if (!isGood) | 73 if (!isGood) |
71 return; | 74 return; |
72 | 75 |
73 // Copy the channel data from what we received from m_multiChannelProvider. | 76 // Copy the channel data from what we received from m_multiChannelProvider. |
74 ASSERT(m_currentChannel <= m_numberOfChannels); | 77 ASSERT(m_currentChannel <= m_numberOfChannels); |
75 if (m_currentChannel < m_numberOfChannels) { | 78 if (m_currentChannel < m_numberOfChannels) { |
76 memcpy(bus->channel(0)->mutableData(), | 79 memcpy(bus->channel(0)->mutableData(), |
77 m_multiChannelBus->channel(m_currentChannel)->data(), | 80 m_multiChannelBus->channel(m_currentChannel)->data(), |
78 sizeof(float) * framesToProcess); | 81 sizeof(float) * framesToProcess); |
79 ++m_currentChannel; | 82 ++m_currentChannel; |
80 } | 83 } |
81 } | 84 } |
82 | 85 |
83 private: | 86 private: |
84 AudioSourceProvider* m_multiChannelProvider; | 87 AudioSourceProvider* m_multiChannelProvider; |
85 RefPtr<AudioBus> m_multiChannelBus; | 88 RefPtr<AudioBus> m_multiChannelBus; |
86 unsigned m_numberOfChannels; | 89 unsigned m_numberOfChannels; |
87 unsigned m_currentChannel; | 90 unsigned m_currentChannel; |
88 size_t | 91 size_t m_framesToProcess; // Used to verify that all channels ask for the |
dcheng
2016/10/03 01:21:04
Nit: put this comment on the previous line to avoi
Nico
2016/10/03 02:15:24
Done (I'm not sure I agree with it though; it's 2
| |
89 m_framesToProcess; // Used to verify that all channels ask for the same a mount. | 92 // same amount. |
90 }; | 93 }; |
91 | 94 |
92 } // namespace | 95 } // namespace |
93 | 96 |
94 MultiChannelResampler::MultiChannelResampler(double scaleFactor, | 97 MultiChannelResampler::MultiChannelResampler(double scaleFactor, |
95 unsigned numberOfChannels) | 98 unsigned numberOfChannels) |
96 : m_numberOfChannels(numberOfChannels) { | 99 : m_numberOfChannels(numberOfChannels) { |
97 // Create each channel's resampler. | 100 // Create each channel's resampler. |
98 for (unsigned channelIndex = 0; channelIndex < numberOfChannels; | 101 for (unsigned channelIndex = 0; channelIndex < numberOfChannels; |
99 ++channelIndex) | 102 ++channelIndex) |
100 m_kernels.append(wrapUnique(new SincResampler(scaleFactor))); | 103 m_kernels.append(wrapUnique(new SincResampler(scaleFactor))); |
101 } | 104 } |
102 | 105 |
103 void MultiChannelResampler::process(AudioSourceProvider* provider, | 106 void MultiChannelResampler::process(AudioSourceProvider* provider, |
104 AudioBus* destination, | 107 AudioBus* destination, |
105 size_t framesToProcess) { | 108 size_t framesToProcess) { |
106 // The provider can provide us with multi-channel audio data. But each of our single-channel resamplers (kernels) | 109 // The provider can provide us with multi-channel audio data. But each of our |
107 // below requires a provider which provides a single unique channel of data. | 110 // single-channel resamplers (kernels) below requires a provider which |
108 // channelProvider wraps the original multi-channel provider and dishes out on e channel at a time. | 111 // provides a single unique channel of data. channelProvider wraps the |
112 // original multi-channel provider and dishes out one channel at a time. | |
109 ChannelProvider channelProvider(provider, m_numberOfChannels); | 113 ChannelProvider channelProvider(provider, m_numberOfChannels); |
110 | 114 |
111 for (unsigned channelIndex = 0; channelIndex < m_numberOfChannels; | 115 for (unsigned channelIndex = 0; channelIndex < m_numberOfChannels; |
112 ++channelIndex) { | 116 ++channelIndex) { |
113 // Depending on the sample-rate scale factor, and the internal buffering use d in a SincResampler | 117 // Depending on the sample-rate scale factor, and the internal buffering |
114 // kernel, this call to process() will only sometimes call provideInput() on the channelProvider. | 118 // used in a SincResampler kernel, this call to process() will only |
115 // However, if it calls provideInput() for the first channel, then it will c all it for the remaining | 119 // sometimes call provideInput() on the channelProvider. However, if it |
116 // channels, since they all buffer in the same way and are processing the sa me number of frames. | 120 // calls provideInput() for the first channel, then it will call it for the |
121 // remaining channels, since they all buffer in the same way and are | |
122 // processing the same number of frames. | |
117 m_kernels[channelIndex]->process( | 123 m_kernels[channelIndex]->process( |
118 &channelProvider, destination->channel(channelIndex)->mutableData(), | 124 &channelProvider, destination->channel(channelIndex)->mutableData(), |
119 framesToProcess); | 125 framesToProcess); |
120 } | 126 } |
121 } | 127 } |
122 | 128 |
123 } // namespace blink | 129 } // namespace blink |
OLD | NEW |