OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 } | 80 } |
81 | 81 |
82 PeriodicWave* PeriodicWave::createTriangle(float sampleRate) | 82 PeriodicWave* PeriodicWave::createTriangle(float sampleRate) |
83 { | 83 { |
84 PeriodicWave* periodicWave = new PeriodicWave(sampleRate); | 84 PeriodicWave* periodicWave = new PeriodicWave(sampleRate); |
85 periodicWave->generateBasicWaveform(OscillatorHandler::TRIANGLE); | 85 periodicWave->generateBasicWaveform(OscillatorHandler::TRIANGLE); |
86 return periodicWave; | 86 return periodicWave; |
87 } | 87 } |
88 | 88 |
89 PeriodicWave::PeriodicWave(float sampleRate) | 89 PeriodicWave::PeriodicWave(float sampleRate) |
90 : m_sampleRate(sampleRate) | 90 : m_v8ExternalMemory(0) |
| 91 , m_sampleRate(sampleRate) |
91 , m_centsPerRange(CentsPerRange) | 92 , m_centsPerRange(CentsPerRange) |
92 { | 93 { |
93 float nyquist = 0.5 * m_sampleRate; | 94 float nyquist = 0.5 * m_sampleRate; |
94 m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials(); | 95 m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials(); |
95 m_rateScale = periodicWaveSize() / m_sampleRate; | 96 m_rateScale = periodicWaveSize() / m_sampleRate; |
96 // Compute the number of ranges needed to cover the entire frequency range,
assuming | 97 // Compute the number of ranges needed to cover the entire frequency range,
assuming |
97 // kNumberOfOctaveBands per octave. | 98 // kNumberOfOctaveBands per octave. |
98 m_numberOfRanges = 0.5 + kNumberOfOctaveBands * log2f(periodicWaveSize()); | 99 m_numberOfRanges = 0.5 + kNumberOfOctaveBands * log2f(periodicWaveSize()); |
99 } | 100 } |
100 | 101 |
| 102 PeriodicWave::~PeriodicWave() |
| 103 { |
| 104 adjustV8ExternalMemory(-static_cast<int64_t>(m_v8ExternalMemory)); |
| 105 } |
| 106 |
101 unsigned PeriodicWave::periodicWaveSize() const | 107 unsigned PeriodicWave::periodicWaveSize() const |
102 { | 108 { |
103 // Choose an appropriate wave size for the given sample rate. This allows u
s to use shorter | 109 // Choose an appropriate wave size for the given sample rate. This allows u
s to use shorter |
104 // FFTs when possible to limit the complexity. The breakpoints here are som
ewhat arbitrary, but | 110 // FFTs when possible to limit the complexity. The breakpoints here are som
ewhat arbitrary, but |
105 // we want sample rates around 44.1 kHz or so to have a size of 4096 to pres
erve backward | 111 // we want sample rates around 44.1 kHz or so to have a size of 4096 to pres
erve backward |
106 // compatibility. | 112 // compatibility. |
107 if (m_sampleRate <= 24000) { | 113 if (m_sampleRate <= 24000) { |
108 return 2048; | 114 return 2048; |
109 } | 115 } |
110 | 116 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 | 161 |
156 // A value from 0 -> 1 representing what fraction of the partials to keep. | 162 // A value from 0 -> 1 representing what fraction of the partials to keep. |
157 float cullingScale = pow(2, -centsToCull / 1200); | 163 float cullingScale = pow(2, -centsToCull / 1200); |
158 | 164 |
159 // The very top range will have all the partials culled. | 165 // The very top range will have all the partials culled. |
160 unsigned numberOfPartials = cullingScale * maxNumberOfPartials(); | 166 unsigned numberOfPartials = cullingScale * maxNumberOfPartials(); |
161 | 167 |
162 return numberOfPartials; | 168 return numberOfPartials; |
163 } | 169 } |
164 | 170 |
| 171 // Tell V8 about the memory we're using so it can properly schedule garbage coll
ects. |
| 172 void PeriodicWave::adjustV8ExternalMemory(int delta) |
| 173 { |
| 174 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(delta); |
| 175 m_v8ExternalMemory += delta; |
| 176 } |
| 177 |
165 // Convert into time-domain wave buffers. | 178 // Convert into time-domain wave buffers. |
166 // One table is created for each range for non-aliasing playback at different pl
ayback rates. | 179 // One table is created for each range for non-aliasing playback at different pl
ayback rates. |
167 // Thus, higher ranges have more high-frequency partials culled out. | 180 // Thus, higher ranges have more high-frequency partials culled out. |
168 void PeriodicWave::createBandLimitedTables(const float* realData, const float* i
magData, unsigned numberOfComponents, bool disableNormalization) | 181 void PeriodicWave::createBandLimitedTables(const float* realData, const float* i
magData, unsigned numberOfComponents, bool disableNormalization) |
169 { | 182 { |
170 // TODO(rtoy): Figure out why this needs to be 0.5 when normalization is dis
abled. | 183 // TODO(rtoy): Figure out why this needs to be 0.5 when normalization is dis
abled. |
171 float normalizationScale = 0.5; | 184 float normalizationScale = 0.5; |
172 | 185 |
173 unsigned fftSize = periodicWaveSize(); | 186 unsigned fftSize = periodicWaveSize(); |
174 unsigned halfSize = fftSize / 2; | 187 unsigned halfSize = fftSize / 2; |
(...skipping 26 matching lines...) Expand all Loading... |
201 for (i = std::min(numberOfComponents, numberOfPartials + 1); i < halfSiz
e; ++i) { | 214 for (i = std::min(numberOfComponents, numberOfPartials + 1); i < halfSiz
e; ++i) { |
202 realP[i] = 0; | 215 realP[i] = 0; |
203 imagP[i] = 0; | 216 imagP[i] = 0; |
204 } | 217 } |
205 | 218 |
206 // Clear packed-nyquist and any DC-offset. | 219 // Clear packed-nyquist and any DC-offset. |
207 realP[0] = 0; | 220 realP[0] = 0; |
208 imagP[0] = 0; | 221 imagP[0] = 0; |
209 | 222 |
210 // Create the band-limited table. | 223 // Create the band-limited table. |
211 OwnPtr<AudioFloatArray> table = adoptPtr(new AudioFloatArray(periodicWav
eSize())); | 224 unsigned waveSize = periodicWaveSize(); |
| 225 OwnPtr<AudioFloatArray> table = adoptPtr(new AudioFloatArray(waveSize)); |
| 226 adjustV8ExternalMemory(waveSize * sizeof(float)); |
212 m_bandLimitedTables.append(table.release()); | 227 m_bandLimitedTables.append(table.release()); |
213 | 228 |
214 // Apply an inverse FFT to generate the time-domain table data. | 229 // Apply an inverse FFT to generate the time-domain table data. |
215 float* data = m_bandLimitedTables[rangeIndex]->data(); | 230 float* data = m_bandLimitedTables[rangeIndex]->data(); |
216 frame.doInverseFFT(data); | 231 frame.doInverseFFT(data); |
217 | 232 |
218 // For the first range (which has the highest power), calculate its peak
value then compute normalization scale. | 233 // For the first range (which has the highest power), calculate its peak
value then compute normalization scale. |
219 if (!disableNormalization) { | 234 if (!disableNormalization) { |
220 if (!rangeIndex) { | 235 if (!rangeIndex) { |
221 float maxValue; | 236 float maxValue; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 | 322 |
308 realP[n] = 0; | 323 realP[n] = 0; |
309 imagP[n] = b; | 324 imagP[n] = b; |
310 } | 325 } |
311 | 326 |
312 createBandLimitedTables(realP, imagP, halfSize, false); | 327 createBandLimitedTables(realP, imagP, halfSize, false); |
313 } | 328 } |
314 | 329 |
315 } // namespace blink | 330 } // namespace blink |
316 | 331 |
OLD | NEW |