Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed USBDevice PinDetect
KarplusStrong.cpp
00001 00002 #include "KarplusStrong.h" 00003 00004 static float noiseSeed[(C::SAMPLE_RATE / C::MIN_FREQUENCY) + 1]; 00005 00006 // Calculate pluck damping constant variables. 00007 const float pluckDampingMin = 0.1; 00008 const float pluckDampingMax = 0.9; 00009 const float pluckDampingVariationMax = C::PLUCK_DAMPING + C::PLUCK_DAMPING_VARIATION * (pluckDampingMax - C::PLUCK_DAMPING); 00010 const float KarplusStrong::pluckDampingVariationMin = C::PLUCK_DAMPING - 00011 C::PLUCK_DAMPING_VARIATION * (C::PLUCK_DAMPING - pluckDampingMin); 00012 const float KarplusStrong::pluckDampingVariationDifference = pluckDampingVariationMax - pluckDampingVariationMin; 00013 00014 KarplusStrong::KarplusStrong() { 00015 initializeNoiseSeed(); 00016 00017 // These values will be overwritten under normal control flow, but give them values in case of runtime errors. 00018 lastOutput = 0.0; 00019 filterCoefficient = 0.6; 00020 nextFilterCoefficient = filterCoefficient; 00021 pluckDampingCoefficient = 0.5; 00022 } 00023 00024 void KarplusStrong::midiNoteOn(int key, float velocity) { 00025 // Calculate the smoothing filter coefficient for this note. 00026 float noteIndex = float(key - 24) / 48.0; // normalize the lower two octaves. 00027 // Clip to 1.0 00028 if (noteIndex > 1.0) { 00029 noteIndex = 1.0; 00030 } 00031 00032 // The volume is always pretty quiet, even at full velocity, so use velocity as a filter cutoff instead. 00033 float stringDamping = C::STRING_DAMPING_MIN + velocity * (C::STRING_DAMPING_MAX - C::STRING_DAMPING_MIN); 00034 00035 nextFilterCoefficient = stringDamping // Initial damping. 00036 + 0.5 * (1.0 - stringDamping) * sqrt(noteIndex) // Keyboard tracking 00037 + C::STRING_DAMPING_VARIATION * (1.0 - stringDamping) * getRand(); // Random variation 00038 00039 // Calculate the pluck damping for this note. 00040 pluckDampingCoefficient = pluckDampingVariationMin + getRand() * pluckDampingVariationDifference; 00041 } 00042 00043 float KarplusStrong::fillBuffer(const int bufferIndex) { 00044 // Copy over the calculated filter coefficient. 00045 filterCoefficient = nextFilterCoefficient; 00046 00047 // Get the noise sample from the static noise seed while making room for character variation. 00048 float noiseSample = noiseSeed[bufferIndex] * (1.0 - C::CHARACTER_VARIATION); 00049 // Add in some character randomness to make it more realistic. 00050 noiseSample += getRandSample() * C::CHARACTER_VARIATION; 00051 00052 // Filter using the pluck damping coefficient to control sprectral content. 00053 noiseSample = lowpassFilter(lastOutput, noiseSample, pluckDampingCoefficient); 00054 return processBuffer(noiseSample); 00055 } 00056 00057 float KarplusStrong::processBuffer(const float inputSample) { 00058 // Put the sample from the last period through the lowpass filter. 00059 lastOutput = lowpassFilter(lastOutput, inputSample, filterCoefficient); 00060 return lastOutput; 00061 } 00062 00063 void KarplusStrong::initializeNoiseSeed() { 00064 // Initialize the random function with a static seed. 00065 srand(time(NULL)); 00066 00067 int seedLength = (C::SAMPLE_RATE / C::MIN_FREQUENCY) + 1; 00068 for (int i = 0; i < seedLength; i++) { 00069 // Create a random number in [-1.0, 1.0] 00070 noiseSeed[i] = getRandSample(); 00071 } 00072 } 00073 00074 float KarplusStrong::lowpassFilter(const float output, const float input, const float smoothingFactor) { 00075 // Simple single pole recursive IIR lowpass filter. 00076 return input * smoothingFactor + output * (1.0 - smoothingFactor); 00077 }
Generated on Thu Aug 11 2022 16:09:57 by
1.7.2