negasonic 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2778cf477ddcdaf271a622ad962e83556f6885f4cca5bfd0c05317ac0cc86fca
4
+ data.tar.gz: a909003d32f6b3582b61606016c8a7f54b57b006ef2d214e9181f7f08677f6dc
5
+ SHA512:
6
+ metadata.gz: d15b5eeb23e968cb43671c98e7a792ab3fab3d4814a2ab8b240ea9a1064f63d35449341c2394e6d558eb26fb0373300e5db06159cc4a85f8750ab9a9a36184cb
7
+ data.tar.gz: 574ca728dbcb3d14ae25308c8ecfdf7e0eee8b50bb85b9830061c8cf2b28afc6f5c0adaaa156fe2452768a875071242445bffa05f15bab363a53eaadfbc5c7d5
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ before_install: gem install bundler -v 1.16.2
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gem 'tone.rb', git: "https://github.com/merongivian/tone.rb"
6
+
7
+ # Specify your gem's dependencies in negasonic.gemspec
8
+ gemspec
@@ -0,0 +1,41 @@
1
+ GIT
2
+ remote: https://github.com/merongivian/tone.rb
3
+ revision: 6115d2e89d6d00e67b2d0fd7e942af4703b46e93
4
+ specs:
5
+ tone.rb (0.1.0)
6
+ opal (>= 0.10.2)
7
+
8
+ PATH
9
+ remote: .
10
+ specs:
11
+ negasonic (0.1.0)
12
+ tone.rb
13
+
14
+ GEM
15
+ remote: https://rubygems.org/
16
+ specs:
17
+ ast (2.4.0)
18
+ hike (1.2.3)
19
+ minitest (5.11.3)
20
+ opal (0.11.0)
21
+ ast (>= 2.3.0)
22
+ hike (~> 1.2)
23
+ parser (= 2.3.3.1)
24
+ sourcemap (~> 0.1.0)
25
+ parser (2.3.3.1)
26
+ ast (~> 2.2)
27
+ rake (10.5.0)
28
+ sourcemap (0.1.1)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler (~> 1.16)
35
+ minitest (~> 5.0)
36
+ negasonic!
37
+ rake (~> 10.0)
38
+ tone.rb!
39
+
40
+ BUNDLED WITH
41
+ 1.16.2
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Jose Anasco
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,54 @@
1
+ # Negasonic
2
+
3
+ Ruby DSL for music live coding in the browser, you can play with it in the [online editor](https://negasonic.herokuapp.com/)
4
+
5
+ DISCLAIMER: The current DSL might change in the future
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'negasonic'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install negasonic
22
+
23
+ ## Usage
24
+
25
+ Most of the audio capabilities are handled by [Tone.rb](https://github.com/merongivian/tone.rb), which is a wrapper
26
+ over [Tone.js](https://github.com/Tonejs/Tone.js), you can check how effects/synths works in the [official docs](https://tonejs.github.io/docs/)
27
+
28
+ `instrument` is in charged of hooking up a synth with a chain of effects
29
+
30
+ ```ruby
31
+ # instruments need to be named in order to use it later
32
+ instrument(:lead, synth: :am, volume: 1) do
33
+ # The order of the effects will affect the final sound
34
+ vibrato frequency: 5, depth: 0.1
35
+ jc_reverb room_size: 0.5
36
+ end
37
+ ```
38
+
39
+ In `pattern` we define which notes will be played in the instrument. The interval value uses
40
+ Tone.js's time notation, [read about time notation](https://github.com/Tonejs/Tone.js/wiki/Time)
41
+
42
+ ```ruby
43
+ pattern(instrument: :lead, interval: '4n', type: :random, notes: [36, "D2", 40, "A2"])
44
+ ```
45
+
46
+ Notes can be plain normal or MIDI notes
47
+
48
+ ## Contributing
49
+
50
+ Bug reports and pull requests are welcome on GitHub at https://github.com/merongivian/negasonic.
51
+
52
+ ## License
53
+
54
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "negasonic"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ if RUBY_ENGINE == 'opal'
2
+ require 'tone'
3
+ require 'negasonic/instrument'
4
+ require 'negasonic/looped_event'
5
+ require 'negasonic/dsl'
6
+
7
+ extend Negasonic::DSL
8
+ else
9
+ require 'opal'
10
+
11
+ Opal.append_path File.expand_path('../', __FILE__).untaint
12
+ end
@@ -0,0 +1,38 @@
1
+ module Negasonic
2
+ module DSL
3
+ def part(instrument:, &block)
4
+ the_instrument = Negasonic::Instrument.find(instrument)
5
+
6
+ the_loop = Negasonic::LoopedEvent::Part.new(the_instrument.input_node)
7
+ the_loop.instance_eval(&block)
8
+ the_loop.start
9
+ end
10
+
11
+ def sequence(instrument:, interval: , &block)
12
+ the_instrument = Negasonic::Instrument.find(instrument)
13
+
14
+ the_loop = Negasonic::LoopedEvent::Sequence.new(the_instrument.input_node)
15
+ the_loop.instance_eval(&block)
16
+ the_loop.start(interval)
17
+ end
18
+
19
+ def pattern(instrument:, interval:, type:, notes:)
20
+ the_instrument = Negasonic::Instrument.find(instrument)
21
+
22
+ Negasonic::LoopedEvent::Pattern.new(the_instrument.input_node, notes)
23
+ .start(interval, type)
24
+ end
25
+
26
+ def instrument(name, synth:, volume: nil, &block)
27
+ instrument = Negasonic::Instrument.find(name) ||
28
+ Negasonic::Instrument.add(name)
29
+
30
+ synth_node = Negasonic::Instrument::Synth.send(synth, { volume: volume })
31
+
32
+ instrument.tap do |i|
33
+ i.instance_eval(&block)
34
+ i.connect_nodes(synth_node)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,53 @@
1
+ require 'negasonic/instrument/effects_set'
2
+ require 'negasonic/instrument/synth'
3
+
4
+ module Negasonic
5
+ class Instrument
6
+ @all = []
7
+
8
+ class << self
9
+ attr_accessor :all
10
+
11
+ def find(name)
12
+ @all.find do |instrument|
13
+ instrument.name == name
14
+ end
15
+ end
16
+
17
+ def add(name)
18
+ new(name).tap do |instrument|
19
+ @all << instrument
20
+ end
21
+ end
22
+ end
23
+
24
+ attr_reader :input_node, :name
25
+
26
+ def initialize(name)
27
+ @name = name
28
+ @nodes = []
29
+ @effects_set = EffectsSet.new
30
+ end
31
+
32
+ def effects(&block)
33
+ @effects_set.reload
34
+ @effects_set.instance_eval(&block)
35
+ end
36
+
37
+ def connect_nodes(new_synth)
38
+ new_nodes = [new_synth, @effects_set.nodes].flatten
39
+
40
+ if @nodes != new_nodes
41
+ @input_node = new_synth
42
+ @input_node.chain(*@effects_set.nodes)
43
+
44
+ old_nodes = @nodes
45
+ @nodes = new_nodes
46
+
47
+ Tone::Transport.schedule_after(1) do |time|
48
+ old_nodes.each(&:dispose)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,51 @@
1
+ module Negasonic
2
+ class Instrument
3
+ class EffectsSet
4
+ attr_reader :nodes
5
+
6
+ def initialize
7
+ @nodes = []
8
+ end
9
+
10
+ def reload
11
+ @nodes = []
12
+ end
13
+
14
+ def vibrato(**opts)
15
+ @nodes << Tone::Effect::Vibrato.new(**opts)
16
+ end
17
+
18
+ def distortion(**opts)
19
+ @nodes << Tone::Effect::Distortion.new(**opts)
20
+ end
21
+
22
+ def chorus(**opts)
23
+ @nodes << Tone::Effect::Chorus.new(**opts)
24
+ end
25
+
26
+ def tremolo(**opts)
27
+ @nodes << Tone::Effect::Tremolo.new(**opts)
28
+ end
29
+
30
+ def feedback_delay(**opts)
31
+ @nodes << Tone::Effect::FeedbackDelay.new(**opts)
32
+ end
33
+
34
+ def freeverb(**opts)
35
+ @nodes << Tone::Effect::Freeverb.new(**opts)
36
+ end
37
+
38
+ def jc_reverb(**opts)
39
+ @nodes << Tone::Effect::JCReverb.new(**opts)
40
+ end
41
+
42
+ def phaser(**opts)
43
+ @nodes << Tone::Effect::Phaser.new(**opts)
44
+ end
45
+
46
+ def ping_pong_delay(**opts)
47
+ @nodes << Tone::Effect::PingPongDelay.new(**opts)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,39 @@
1
+ module Negasonic
2
+ class Instrument
3
+ class Synth
4
+ class << self
5
+ def simple(**opts)
6
+ Tone::Synth::Simple.new(**opts)
7
+ end
8
+
9
+ def membrane(**opts)
10
+ Tone::Synth::Membrane.new(**opts)
11
+ end
12
+
13
+ def am(**opts)
14
+ Tone::Synth::AM.new(**opts)
15
+ end
16
+
17
+ def fm(**opts)
18
+ Tone::Synth::FM.new(**opts)
19
+ end
20
+
21
+ def duo(**opts)
22
+ Tone::Synth::Duo.new(**opts)
23
+ end
24
+
25
+ def mono(**opts)
26
+ Tone::Synth::Mono.new(**opts)
27
+ end
28
+
29
+ def pluck(**opts)
30
+ Tone::Synth::Pluck.new(**opts)
31
+ end
32
+
33
+ def poly(**opts)
34
+ Tone::Synth::Poly.new(**opts)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,36 @@
1
+ require 'js'
2
+ require 'negasonic/looped_event/part'
3
+ require 'negasonic/looped_event/pattern'
4
+ require 'negasonic/looped_event/sequence'
5
+
6
+ module Negasonic
7
+ module LoopedEvent
8
+ @events = []
9
+
10
+ class << self
11
+ attr_accessor :events
12
+
13
+ def dispose_all
14
+ @events.each(&:dispose)
15
+ @events = []
16
+ end
17
+
18
+ def start(looped_element)
19
+ looped_element.start(0)
20
+ looped_element.loop = true
21
+ @events << looped_element
22
+ end
23
+
24
+ def to_tone_notes(notes)
25
+ notes.map do |note|
26
+ if JS.typeof(note) == 'string'
27
+ note
28
+ else
29
+ # is a midi note
30
+ (2**((note-69)/12) * 440).to_f
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ module Negasonic
2
+ module LoopedEvent
3
+ class Part
4
+ def initialize(synth)
5
+ @synth = synth
6
+ @definitions = []
7
+ end
8
+
9
+ def start
10
+ do_start do |time, event|
11
+ @synth.trigger_attack_release(event.JS['note'], event.JS['duration'], time)
12
+ end
13
+ end
14
+
15
+ def play(note, time, duration)
16
+ @definitions << { note: note, time: time, duration: duration }
17
+ end
18
+
19
+ private
20
+
21
+ def do_start(&block)
22
+ LoopedEvent.start(Tone::Event::Part.new @definitions, &block)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ module Negasonic
2
+ module LoopedEvent
3
+ class Pattern
4
+ TYPES = {
5
+ random: 'random',
6
+ random_walk: 'randomWalk',
7
+ random_once: 'randomOnce',
8
+ up: 'up',
9
+ down: 'down',
10
+ up_down: 'upDown',
11
+ down_up: 'downUp',
12
+ alternate_up: 'alternateUp',
13
+ alternate_down: 'alternateDown'
14
+ }
15
+
16
+ def initialize(synth, notes = [])
17
+ @synth = synth
18
+ @notes = LoopedEvent.to_tone_notes(notes)
19
+ end
20
+
21
+ def start(duration, type)
22
+ raise 'invalid pattern type' unless TYPES.keys.include?(type)
23
+
24
+ do_start(duration, TYPES[type]) do |time, note|
25
+ @synth.trigger_attack_release(note, duration, time)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def do_start(duration, type, &block)
32
+ pattern = Tone::Event::Pattern.new(@notes, type, &block)
33
+ pattern.interval = duration
34
+ LoopedEvent.start(pattern)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,26 @@
1
+ module Negasonic
2
+ module LoopedEvent
3
+ class Sequence
4
+ def initialize(synth, segments = [])
5
+ @synth = synth
6
+ @segments = segments
7
+ end
8
+
9
+ def start(duration)
10
+ do_start(duration) do |time, note|
11
+ @synth.trigger_attack_release(note, duration, time)
12
+ end
13
+ end
14
+
15
+ def play(*notes)
16
+ @segments << LoopedEvent.to_tone_notes(notes)
17
+ end
18
+
19
+ private
20
+
21
+ def do_start(duration, &block)
22
+ LoopedEvent.start(Tone::Event::Sequence.new @segments, duration, &block)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Negasonic
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,30 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "negasonic/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "negasonic"
8
+ spec.version = Negasonic::VERSION
9
+ spec.authors = ["Jose Anasco"]
10
+ spec.email = ["joseanasco1@gmail.com"]
11
+
12
+ spec.summary = %q{Music live coding in the browser}
13
+ spec.description = %q{Ruby DSL for music live coding in web-audio}
14
+ spec.homepage = "http://github.com/merongivian/negasonic"
15
+ spec.license = "MIT"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_runtime_dependency 'tone.rb'
27
+ spec.add_development_dependency "bundler", "~> 1.16"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "minitest", "~> 5.0"
30
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: negasonic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jose Anasco
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-05-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tone.rb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description: Ruby DSL for music live coding in web-audio
70
+ email:
71
+ - joseanasco1@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - lib/negasonic.rb
86
+ - lib/negasonic/dsl.rb
87
+ - lib/negasonic/instrument.rb
88
+ - lib/negasonic/instrument/effects_set.rb
89
+ - lib/negasonic/instrument/synth.rb
90
+ - lib/negasonic/looped_event.rb
91
+ - lib/negasonic/looped_event/part.rb
92
+ - lib/negasonic/looped_event/pattern.rb
93
+ - lib/negasonic/looped_event/sequence.rb
94
+ - lib/negasonic/version.rb
95
+ - negasonic.gemspec
96
+ homepage: http://github.com/merongivian/negasonic
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.7.6
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Music live coding in the browser
120
+ test_files: []