void ComputeSine(float * aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd) { for (uint32_t i = aStart; i < aEnd; ++i) { UpdateParametersIfNeeded(ticks, i); aOutput[i] = sin(mPhase); IncrementPhase(); } }
void ComputeSquare(float * aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd) { for (uint32_t i = aStart; i < aEnd; ++i) { UpdateParametersIfNeeded(ticks, i); // Integration to get us a square. It turns out we can have a // pure integrator here. mSquare += BipolarBLIT(); aOutput[i] = mSquare; // maybe we want to apply a gain, the wg has not decided yet aOutput[i] *= 1.5; IncrementPhase(); } }
void ComputeCustom(float* aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd) { MOZ_ASSERT(mPeriodicWave, "No custom waveform data"); uint32_t periodicWaveSize = mPeriodicWave->periodicWaveSize(); // Mask to wrap wave data indices into the range [0,periodicWaveSize). uint32_t indexMask = periodicWaveSize - 1; MOZ_ASSERT(periodicWaveSize && (periodicWaveSize & indexMask) == 0, "periodicWaveSize must be power of 2"); float* higherWaveData = nullptr; float* lowerWaveData = nullptr; float tableInterpolationFactor; // Phase increment at frequency of 1 Hz. // mPhase runs [0,periodicWaveSize) here instead of [0,2*M_PI). float basePhaseIncrement = static_cast<float>(periodicWaveSize) / mSource->SampleRate(); for (uint32_t i = aStart; i < aEnd; ++i) { UpdateParametersIfNeeded(ticks, i); mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency, lowerWaveData, higherWaveData, tableInterpolationFactor); // Bilinear interpolation between adjacent samples in each table. float floorPhase = floorf(mPhase); uint32_t j1 = floorPhase; j1 &= indexMask; uint32_t j2 = j1 + 1; j2 &= indexMask; float sampleInterpolationFactor = mPhase - floorPhase; float lower = (1.0f - sampleInterpolationFactor) * lowerWaveData[j1] + sampleInterpolationFactor * lowerWaveData[j2]; float higher = (1.0f - sampleInterpolationFactor) * higherWaveData[j1] + sampleInterpolationFactor * higherWaveData[j2]; aOutput[i] = (1.0f - tableInterpolationFactor) * lower + tableInterpolationFactor * higher; // Calculate next phase position from wrapped value j1 to avoid loss of // precision at large values. mPhase = j1 + sampleInterpolationFactor + basePhaseIncrement * mFinalFrequency; } }
void ComputeSawtooth(float * aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd) { float dcoffset; for (uint32_t i = aStart; i < aEnd; ++i) { UpdateParametersIfNeeded(ticks, i); // DC offset so the Saw does not ramp up to infinity when integrating. dcoffset = mFinalFrequency / mSource->SampleRate(); // Integrate and offset so we get mAmplitudeAtZero sawtooth. We have a // very low frequency component somewhere here, but I'm not sure where. mSaw += UnipolarBLIT() - dcoffset; // reverse the saw so we are spec compliant aOutput[i] = -mSaw * 1.5; IncrementPhase(); } }
void ComputeTriangle(float * aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd) { for (uint32_t i = aStart; i < aEnd; ++i) { UpdateParametersIfNeeded(ticks, i); // Integrate to get a square mSquare += BipolarBLIT(); // Leaky integrate to get a triangle. We get too much dc offset if we don't // leaky integrate here. // C6 = k0 / period // (period is samplingrate / frequency, k0 = (PI/2)/(2*PI)) = 0.25 float C6 = 0.25 / (mSource->SampleRate() / mFinalFrequency); mTriangle = mTriangle * sLeak + mSquare + C6; // DC Block, and scale back to [-1.0; 1.0] aOutput[i] = mDCBlocker.Process(mTriangle) / (mSignalPeriod/2) * 1.5; IncrementPhase(); } }
void ComputeCustom(float* aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd) { MOZ_ASSERT(mPeriodicWave, "No custom waveform data"); uint32_t periodicWaveSize = mPeriodicWave->periodicWaveSize(); float* higherWaveData = nullptr; float* lowerWaveData = nullptr; float tableInterpolationFactor; float rate = 1.0 / mSource->SampleRate(); for (uint32_t i = aStart; i < aEnd; ++i) { UpdateParametersIfNeeded(ticks, i); mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency, lowerWaveData, higherWaveData, tableInterpolationFactor); // mPhase runs 0..periodicWaveSize here instead of 0..2*M_PI. mPhase += periodicWaveSize * mFinalFrequency * rate; if (mPhase >= periodicWaveSize) { mPhase -= periodicWaveSize; } // Bilinear interpolation between adjacent samples in each table. uint32_t j1 = floor(mPhase); uint32_t j2 = j1 + 1; if (j2 >= periodicWaveSize) { j2 -= periodicWaveSize; } float sampleInterpolationFactor = mPhase - j1; float lower = sampleInterpolationFactor * lowerWaveData[j1] + (1 - sampleInterpolationFactor) * lowerWaveData[j2]; float higher = sampleInterpolationFactor * higherWaveData[j1] + (1 - sampleInterpolationFactor) * higherWaveData[j2]; aOutput[i] = tableInterpolationFactor * lower + (1 - tableInterpolationFactor) * higher; } }