From fe96c4d1e323ab8e93d6b0a6c8948626ab6a387c Mon Sep 17 00:00:00 2001 From: Alexander Kojevnikov Date: Thu, 6 May 2010 19:55:21 +1000 Subject: [PATCH] Use the visible spectrum --- src/spek-spectrogram.vala | 57 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/src/spek-spectrogram.vala b/src/spek-spectrogram.vala index 045e735..a89d3f4 100644 --- a/src/spek-spectrogram.vala +++ b/src/spek-spectrogram.vala @@ -6,6 +6,8 @@ namespace Spek { private Source source; + private struct Color { uchar r; uchar g; uchar b; } + public Spectrogram () { } @@ -22,12 +24,59 @@ namespace Spek { for (int y = 0; y < values.length; y++) { var i = (values.length - y - 1) * rowstride + x * 3; var level = float.min (1f, Math.log10f (101f + values[y]) / 2f); - var value = (uchar) (level * 255f); - pixels[i] = value; - pixels[i + 1] = value; - pixels[i + 2] = value; + var color = get_color (level); + if (sample < 20) { + // TODO: allocate additional space for this. + color = get_color (((float) y) / values.length); + } + pixels[i] = color.r; + pixels[i + 1] = color.g; + pixels[i + 2] = color.b; } queue_draw_area (allocation.x + sample, allocation.y, 1, allocation.height); } + + // Modified version of Dan Bruton's algorithm: + // http://www.physics.sfasu.edu/astro/color/spectra.html + private Color get_color (float level) { + float r = 0.0f, g = 0.0f, b = 0.0f; + if (level >= 0f && level < 0.15f) { + r = (0.15f - level) / (0.15f + 0.075f); + g = 0.0f; + b = 1.0f; + } else if (level >= 0.15f && level < 0.275f) { + r = 0.0f; + g = (level - 0.15f) / (0.275f - 0.15f); + b = 1.0f; + } else if (level >= 0.275f && level < 0.325f) { + r = 0.0f; + g = 1.0f; + b = (0.325f - level) / (0.325f - 0.275f); + } else if (level >= 0.325f && level < 0.5f) { + r = (level - 0.325f) / (0.5f - 0.325f); + g = 1.0f; + b = 0.0f; + } else if (level >= 0.5f && level < 0.6625f) { + r = 1.0f; + g = (0.6625f - level) / (0.6625f - 0.5f); + b = 0.0f; + } else if (level >= 0.6625 && level <= 1.0f) { + r = 1.0f; + g = 0.0f; + b = 0.0f; + } + + // Intensity correction. + float cf = 0.0f; + if (level >= 0 && level < 0.1f) { + cf = 0.3f + 0.7f * (level + 0.075f) / (0.1f + 0.075f); + } else if (level >= 0.1f && level <= 0.8f) { + cf = 1.0f; + } else if (level > 0.8f && level <= 1.0f) { + cf = 0.3f + 0.7f * (1.0f - level) / (1.0f - 0.8f); + } + cf *= 255f; + return { (uchar) (r * cf + 0.5f), (uchar) (g * cf + 0.5f), (uchar) (b * cf + 0.5f) }; + } } } \ No newline at end of file