Module: Cyclotone::Controls
- Defined in:
- lib/cyclotone/controls.rb
Constant Summary collapse
- CONTROL_DEFS =
{ s: { type: :string, aliases: [:sound] }, n: { type: :integer }, speed: { type: :float, default: 1.0 }, begin: { type: :float, aliases: [:sample_begin], range: 0..1 }, end: { type: :float, aliases: [:sample_end], range: 0..1 }, pan: { type: :float, default: 0.5, range: 0..1 }, gain: { type: :float, default: 1.0, minimum: 0 }, amp: { type: :float, default: 1.0, minimum: 0 }, cut: { type: :integer }, unit: { type: :string }, accelerate: { type: :float }, legato: { type: :float }, attack: { type: :float, aliases: [:att] }, hold: { type: :float }, release: { type: :float, aliases: [:rel] }, cutoff: { type: :float, aliases: [:lpf] }, resonance: { type: :float, aliases: [:lpq] }, hcutoff: { type: :float, aliases: [:hpf] }, hresonance: { type: :float, aliases: [:hpq] }, bandf: { type: :float, aliases: [:bpf] }, bandq: { type: :float, aliases: [:bpq] }, djf: { type: :float }, vowel: { type: :string }, delay: { type: :float }, delaytime: { type: :float, aliases: [:delayt] }, delayfeedback: { type: :float, aliases: [:delayfb] }, lock: { type: :integer }, dry: { type: :float }, room: { type: :float }, size: { type: :float, aliases: [:sz] }, distort: { type: :float }, triode: { type: :float }, shape: { type: :float }, squiz: { type: :float }, crush: { type: :float }, coarse: { type: :float }, tremolorate: { type: :float, aliases: [:tremr] }, tremolodepth: { type: :float, aliases: [:tremdp] }, phaserrate: { type: :float, aliases: [:phasr] }, phaserdepth: { type: :float, aliases: [:phasdp] }, leslie: { type: :float }, lrate: { type: :float }, lsize: { type: :float }, octer: { type: :float }, octersub: { type: :float }, octersubsub: { type: :float }, fshift: { type: :float }, fshiftnote: { type: :float }, fshiftphase: { type: :float }, ring: { type: :float }, ringf: { type: :float }, ringdf: { type: :float }, note: { type: :numeric_or_array }, velocity: { type: :integer, default: 100, range: 0..127 }, sustain: { type: :float, default: 1.0 }, channel: { type: :integer, default: 0, range: 0..15 }, cc: { type: :hash } }.freeze
- ALIASES =
CONTROL_DEFS.each_with_object({}) do |(name, ), mapping| mapping[name] = name Array([:aliases]).each { |alias_name| mapping[alias_name] = name } end.freeze
Class Method Summary collapse
- .canonical(name) ⇒ Object
- .coerce_pattern(pattern_or_value) ⇒ Object
- .control(name, pattern_or_value) ⇒ Object
- .factory(name, pattern_or_value) ⇒ Object
- .validate_cc(value) ⇒ Object
- .validate_range(control_name, value, definition) ⇒ Object
- .validate_type(control_name, value, type) ⇒ Object
- .validate_value(control_name, value) ⇒ Object
- .wrap_value(control_name, value) ⇒ Object
Class Method Details
.canonical(name) ⇒ Object
123 124 125 |
# File 'lib/cyclotone/controls.rb', line 123 def canonical(name) ALIASES.fetch(name.to_sym) { raise InvalidControlError, "unknown control #{name}" } end |
.coerce_pattern(pattern_or_value) ⇒ Object
97 98 99 |
# File 'lib/cyclotone/controls.rb', line 97 def coerce_pattern(pattern_or_value) Pattern.ensure_pattern(pattern_or_value, strings: :mini_notation) end |
.control(name, pattern_or_value) ⇒ Object
84 85 86 |
# File 'lib/cyclotone/controls.rb', line 84 def control(name, pattern_or_value) factory(name, pattern_or_value) end |
.factory(name, pattern_or_value) ⇒ Object
88 89 90 91 92 93 94 95 |
# File 'lib/cyclotone/controls.rb', line 88 def factory(name, pattern_or_value) canonical_name = canonical(name) pattern = coerce_pattern(pattern_or_value) pattern.fmap do |value| wrap_value(canonical_name, value) end end |
.validate_cc(value) ⇒ Object
160 161 162 163 164 165 166 167 168 |
# File 'lib/cyclotone/controls.rb', line 160 def validate_cc(value) raise InvalidControlError, "cc must be a Hash" unless value.is_a?(Hash) value.each do |controller, amount| raise InvalidControlError, "cc controllers must be within 0..127" unless controller.is_a?(Numeric) && controller.between?(0, 127) raise InvalidControlError, "cc values must be within 0..127" unless amount.is_a?(Numeric) && amount.between?(0, 127) end end |
.validate_range(control_name, value, definition) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/cyclotone/controls.rb', line 146 def validate_range(control_name, value, definition) values = value.is_a?(Array) ? value : [value] if definition[:range] range = definition[:range] raise InvalidControlError, "#{control_name} must be within #{range}" unless values.all? { |entry| range.cover?(entry) } end return unless definition.key?(:minimum) minimum = definition.fetch(:minimum) raise InvalidControlError, "#{control_name} must be >= #{minimum}" unless values.all? { |entry| entry >= minimum } end |
.validate_type(control_name, value, type) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/cyclotone/controls.rb', line 134 def validate_type(control_name, value, type) case type when :integer, :float raise InvalidControlError, "#{control_name} must be numeric" unless value.is_a?(Numeric) when :numeric_or_array values = value.is_a?(Array) ? value : [value] raise InvalidControlError, "#{control_name} must be numeric" unless values.all?(Numeric) when :hash validate_cc(value) if control_name == :cc end end |
.validate_value(control_name, value) ⇒ Object
127 128 129 130 131 132 |
# File 'lib/cyclotone/controls.rb', line 127 def validate_value(control_name, value) definition = CONTROL_DEFS.fetch(control_name) validate_type(control_name, value, definition.fetch(:type)) validate_range(control_name, value, definition) value end |
.wrap_value(control_name, value) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/cyclotone/controls.rb', line 101 def wrap_value(control_name, value) if value.is_a?(Hash) if control_name == :s && (value.key?(:s) || value.key?(:n)) sample = value.key?(:s) ? value[:s] : value[:value] value.merge(s: validate_value(control_name, sample)) elsif control_name == :note && value.key?(:note) value.merge(note: validate_value(control_name, value[:note])) else raw_value = if value.key?(control_name) value[control_name] elsif value.key?(:value) value[:value] else value end value.merge(control_name => validate_value(control_name, raw_value)) end else { control_name => validate_value(control_name, value) } end end |