void LightEffectSoundSolid::renderColor(Spectrum spectrum) { double bassFreq = getParameter("bass freq").getValue().getDouble(); double trebbleFreq = getParameter("trebble freq").getValue().getDouble(); double bassBoost = getParameter("bass boost").getValue().getDouble(); double trebbleBoost = getParameter("trebble boost").getValue().getDouble(); double fStart = getParameter("start frequency").getValue().getDouble(); double fEnd = getParameter("end frequency").getValue().getDouble(); double dbScaler = getParameter("db scaler").getValue().getDouble(); double dbFactor = getParameter("db factor").getValue().getDouble(); double avgFactor = getParameter("average factor").getValue().getDouble(); double changeFactor = getParameter("change factor").getValue().getDouble(); double noiseFloor = getParameter("noise floor").getValue().getDouble(); double avgFilterStrength = getParameter("average filter strength").getValue().getDouble(); uint8_t minSaturation = getParameter("min saturation").getValue().getDouble()*255; double filterStrength = getParameter("color filter strength").getValue().getDouble(); uint8_t threshold = getParameter("threshold").getValue().getDouble()*255; double r = 0., g = 0., b = 0.; size_t binCount = spectrum.getBinCount(); if(bassIndex == -1) { for(bassIndex = 0; (bassIndex < binCount) && (spectrum.getByIndex(bassIndex).getFreqCenter() <= bassFreq); ++bassIndex); std::cout << "Bass Index: " << bassIndex << std::endl; for(endIndex = 0; (endIndex < binCount) && (spectrum.getByIndex(endIndex).getFreqCenter() <= fEnd); ++endIndex); std::cout << "End Index: " << endIndex << std::endl; prevSpectrum = spectrum; } //Compute average double curAvg = 0; for(unsigned int i = 0; i < endIndex; ++i) { curAvg += spectrum.getByIndex(i).getEnergy(); } curAvg = 20.*std::log10(curAvg/endIndex) + noiseFloor; //double curAvg = spectrum.getAverageEnergyDB() + noiseFloor; if(curAvg < 0) curAvg = 0; avg = avg*avgFilterStrength + curAvg*(1. - avgFilterStrength); //Scale to be applied to each bin double scale = 1. / dbScaler; for(unsigned int i = 0; i < binCount; ++i) { FrequencyBin& bin = spectrum.getByIndex(i); double f = bin.getFreqCenter(); if(f > fEnd) break; if(f >= fStart) { //float hue = (f <= bassFreq) ? 40.f*std::pow((double)i/(bassIndex-1), 4.) //: (45.f + 240.f * (i-bassIndex) / (binCount - bassIndex - 1)); //float hue = 240. * i / (binCount - 1); int yellowPoint = 11; float hue; if(i < yellowPoint) { hue = 60. * i / (yellowPoint-1); } else { hue = 60. + 180.*(i-yellowPoint) / (binCount - yellowPoint - 1); } Color c = Color::HSV(255.f*hue/360.f, 255, 255); double db = bin.getEnergyDB(); FrequencyBin& prevBin = prevSpectrum.getByIndex(i); double change = db - prevBin.getEnergyDB(); if(change < 0) change = 0; //Bass boost if(f <= bassFreq) db += bassBoost; //Trebble boost if(f >= trebbleFreq) db += trebbleBoost; //Raise by noise floor, subtract loosly-tracking average db += noiseFloor - avg; //Reject anything below the average if(db < 0) continue; //Scale partially based on average level db *= dbFactor; db += avgFactor*avg + changeFactor*change; r += db * c.getRed(); g += db * c.getGreen(); b += db * c.getBlue(); } } //Scale color r *= scale; g *= scale; b *= scale; //Compute largest component double largest = std::max(r, std::max(g, b)); //Use the largest value to limit the maximum brightness to 255 if(largest > 255) { double scale = 255. / largest; r *= scale; g *= scale; b *= scale; } Color cTmp(r, g, b); uint8_t h = cTmp.getHue(), s = cTmp.getSat(), v = cTmp.getVal(); if(v < threshold) { v = 0; } //Enforce saturation minimum cTmp = Color::HSV(h, std::max(minSaturation, s), v); //Filter the color c.filter(cTmp, filterStrength); //Update previous spectrum prevSpectrum = spectrum; }