/* * This file is part of Toolkit. * * Toolkit is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * Toolkit is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU General * Public License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ "use strict"; (function(w, TK){ function invalidate_bands() { this.invalid.bands = true; this.trigger_draw(); } function sort_bands() { this.bands.sort(function (a, b) { return a.options.freq - b.options.freq; }); } function limit_bands () { if (this.options.leap) return; sort_bands.call(this); for (var i = 0; i < this.bands.length; i++) _set_freq.call(this, i, this.bands[i]); } function set_freq (band) { if (this.options.leap) return; var i = this.bands.indexOf(band); if (i < 0) { TK.error("Band no member of crossover"); return; } _set_freq.call(this, i, band); } function _set_freq (i, band) { var freq = band.options.freq; var dist = freq * this.get("distance") if (i) this.bands[i-1].set("x_max", freq - dist); if (i < this.bands.length-1) this.bands[i+1].set("x_min", freq + dist); } TK.Crossover = TK.class({ /** * TK.Crossover is a {@link TK.Equalizer} displaying the response * of a multi-band crossover filter. TK.Crossover uses {@link TK.CrossoverBand} * as response handles. * * @class TK.Crossover * * @extends TK.Equalizer * * @param {Object} [options={ }] - An object containing initial options. * * @property {Boolean} [options.leap=true] - Define if bands are allowed to leap over each other. * @property {Number} [options.distance=0] - Set a minimal distance between bands if leaping is not allowed. * Value is a factor of x. Example: if distance=0.2 a band cannot be moved beyond 800Hz if the upper next * band is at 1kHz. */ _class: "Crossover", Extends: TK.Equalizer, _options: Object.assign(Object.create(TK.Equalizer.prototype._options), { leap: "boolean", distance: "number", }), options: { range_y: {min:-60, max: 12, scale: "linear"}, leap: true, distance: 0, }, initialize: function (options) { TK.Equalizer.prototype.initialize.call(this, options); /** * @member {HTMLDivElement} TK.Equalizer#element - The main DIV container. * Has class toolkit-response-handler. */ TK.add_class(this.element, "toolkit-crossover"); }, resize: function () { invalidate_bands.call(this); TK.Equalizer.prototype.resize.call(this); }, redraw: function () { var I = this.invalid; var O = this.options; var lastb = this.bands.length - 1; var lastg = this.graphs.length - 1; if (I.validate("bands", "accuracy")) { I.bands = false; I.accuracy = false; sort_bands.call(this); for (var i = 0; i < this.bands.length; i++) { var f = [this.bands[i].lower.get_freq2gain()]; if (i) f.push(this.bands[i-1].upper.get_freq2gain()); this._draw_graph(this.graphs[i], f); } this._draw_graph(this.graphs[lastg], [this.bands[lastb].upper.get_freq2gain()]); } TK.Equalizer.prototype.redraw.call(this); }, add_band: function (options, type) { type = type || TK.CrossoverBand; this.add_graph(); var r = TK.Equalizer.prototype.add_band.call(this, options, type); var that = this; r.add_event("set_freq", function (f) { set_freq.call(that, this); }); limit_bands.call(this); return r; }, remove_band: function (band) { this.remove_graph(this.graphs[this.graphs.length-1]); var r = TK.Equalizer.prototype.remove_band.call(this, options); limit_bands.call(this); return r; }, }); TK.CrossoverBand = TK.class({ /** * TK.CrossoverBand is a {@link TK.EqBand} with an additional filter. * * @param {Object} [options={ }] - An object containing additional options. * * @property {String|Function} [lower="lowpass3"] - The type of filter for the range below cutoff frequency. See {@link TK.EqBand} for more information. * @property {String|Function} [upper="highpass3"] - The type of filter for the range above cutoff frequency. See {@link TK.EqBand} for more information. * @property {Function} [label=function (t, x, y, z) { return TK.sprintf("%.2f Hz", x); }] - The function formatting the handles label. * * @class TK.CrossoverBand * * @extends TK.EqBand */ _class: "CrossoverBand", Extends: TK.EqBand, _options: Object.assign(Object.create(TK.EqBand.prototype._options), { lower: "string", upper: "string", }), options: { lower: "lowpass3", upper: "highpass3", label: function (t, x, y, z) { return TK.sprintf("%.2f Hz", x); }, mode: "line-vertical", // undocumented, just a default differing from TK.ResponseHanlde preferences: [ "top-right", "right", "bottom-right", "top-left", "left", "bottom-left"], // undocumented, just a default differing from TK.ResponseHanlde }, initialize: function (options) { /** * @member {TK.Filter} TK.CrossoverBand#upper - The filter providing the graphical calculations for the upper graph. */ this.upper = new TK.Filter(); /** * @member {TK.Filter} TK.CrossoverBand#lower - The filter providing the graphical calculations for the lower graph. */ this.lower = new TK.Filter(); TK.EqBand.prototype.initialize.call(this, options); /** * @member {HTMLDivElement} TK.CrossoverBand#element - The main SVG group. * Has class toolkit-crossoverband. */ TK.add_class(this.element, "toolkit-crossoverband"); this.set("lower", this.options.lower); this.set("upper", this.options.upper); }, set: function (key, val) { switch (key) { case"lower": this.filter = this.lower; var r = TK.EqBand.prototype.set.call(this, "type", val); this.set("mode", "line-vertical"); return r; case "upper": this.filter = this.upper; var r = TK.EqBand.prototype.set.call(this, "type", val); this.set("mode", "line-vertical"); return r; case "freq": case "gain": case "q": if (this.lower) this.filter = this.lower; val = TK.EqBand.prototype.set.call(this, key, val); this.filter = this.upper; return TK.EqBand.prototype.set.call(this, key, val); } return TK.EqBand.prototype.set.call(this, key, val); }, }); })(this, this.TK);