fet 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9a6eaf2c2012e548d709b7c60d8bb087f55062ea7a069fade95adb5ee04f8c70
4
+ data.tar.gz: d9a82a31165883c5219fd94b042dcc0ceda2c12e4e2c8fb915257e5bb02e6df6
5
+ SHA512:
6
+ metadata.gz: 9c78069eab1b047f0e7bf72580e5d5dac1c12467e606ff8be3637fcd202a6e666d009900bbcee3e7bad66992fbf488df3abe049d0a14494a54c9209223401d30
7
+ data.tar.gz: b7d43fc3d8edff904615b9e6b681edc4b77d6becca9beee2a137c3b2e8fdd0071aab9953dffd090a3f107f5b0e24054fd5af4cdfba544920949aa6ee39490fd6
@@ -0,0 +1,18 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - name: Set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: 3.0.2
14
+ bundler-cache: true
15
+ - name: Run the default task
16
+ run: bundle exec rake
17
+ env:
18
+ CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /singing/
2
+ /listening/
3
+ /listening_single_note/
4
+ /.bundle/
5
+ /.yardoc
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,47 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.0
3
+ NewCops: enable
4
+
5
+ Style/StringLiterals:
6
+ Enabled: true
7
+ EnforcedStyle: double_quotes
8
+
9
+ Style/StringLiteralsInInterpolation:
10
+ Enabled: true
11
+ EnforcedStyle: double_quotes
12
+
13
+ Style/TrailingCommaInArrayLiteral:
14
+ Enabled: true
15
+ EnforcedStyleForMultiline: consistent_comma
16
+
17
+ Style/TrailingCommaInArguments:
18
+ Enabled: true
19
+ EnforcedStyleForMultiline: consistent_comma
20
+
21
+ Style/TrailingCommaInHashLiteral:
22
+ Enabled: true
23
+ EnforcedStyleForMultiline: consistent_comma
24
+
25
+ Style/RaiseArgs:
26
+ Enabled: true
27
+ EnforcedStyle: compact
28
+
29
+ Style/WordArray:
30
+ Enabled: true
31
+ EnforcedStyle: brackets
32
+
33
+ Style/SymbolArray:
34
+ Enabled: true
35
+ EnforcedStyle: brackets
36
+
37
+ Layout/CaseIndentation:
38
+ Enabled: true
39
+
40
+ Layout/LineLength:
41
+ Max: 175
42
+
43
+ Style/RedundantReturn:
44
+ Enabled: false
45
+
46
+ Style/EmptyCaseCondition:
47
+ Enabled: false
data/.ruby_version ADDED
@@ -0,0 +1 @@
1
+ 3.0.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2021-08-26
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's runtime dependencies in fet.gemspec
6
+ gemspec
7
+
8
+ group :test do
9
+ gem "minitest", "~> 5.0"
10
+ gem "simplecov", "~> 0.21.2"
11
+ end
12
+
13
+ group :test, :development do
14
+ gem "codecov", "~> 0.6.0"
15
+ gem "pry-byebug", "~> 3.9"
16
+ gem "rake", "~> 13.0"
17
+ gem "rdoc", "~> 6.3", ">= 6.3.2"
18
+ gem "rubocop", "~> 1.7"
19
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,71 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fet (0.2.0)
5
+ gli (~> 2.20, >= 2.20.1)
6
+ ice_nine (~> 0.11.2)
7
+ midilib (~> 2.0, >= 2.0.5)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ast (2.4.2)
13
+ byebug (11.1.3)
14
+ codecov (0.6.0)
15
+ simplecov (>= 0.15, < 0.22)
16
+ coderay (1.1.3)
17
+ docile (1.4.0)
18
+ gli (2.20.1)
19
+ ice_nine (0.11.2)
20
+ method_source (1.0.0)
21
+ midilib (2.0.5)
22
+ minitest (5.14.4)
23
+ parallel (1.20.1)
24
+ parser (3.0.2.0)
25
+ ast (~> 2.4.1)
26
+ pry (0.13.1)
27
+ coderay (~> 1.1)
28
+ method_source (~> 1.0)
29
+ pry-byebug (3.9.0)
30
+ byebug (~> 11.0)
31
+ pry (~> 0.13.0)
32
+ rainbow (3.0.0)
33
+ rake (13.0.6)
34
+ rdoc (6.3.2)
35
+ regexp_parser (2.1.1)
36
+ rexml (3.2.5)
37
+ rubocop (1.20.0)
38
+ parallel (~> 1.10)
39
+ parser (>= 3.0.0.0)
40
+ rainbow (>= 2.2.2, < 4.0)
41
+ regexp_parser (>= 1.8, < 3.0)
42
+ rexml
43
+ rubocop-ast (>= 1.9.1, < 2.0)
44
+ ruby-progressbar (~> 1.7)
45
+ unicode-display_width (>= 1.4.0, < 3.0)
46
+ rubocop-ast (1.11.0)
47
+ parser (>= 3.0.1.1)
48
+ ruby-progressbar (1.11.0)
49
+ simplecov (0.21.2)
50
+ docile (~> 1.1)
51
+ simplecov-html (~> 0.11)
52
+ simplecov_json_formatter (~> 0.1)
53
+ simplecov-html (0.12.3)
54
+ simplecov_json_formatter (0.1.3)
55
+ unicode-display_width (2.0.0)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ codecov (~> 0.6.0)
62
+ fet!
63
+ minitest (~> 5.0)
64
+ pry-byebug (~> 3.9)
65
+ rake (~> 13.0)
66
+ rdoc (~> 6.3, >= 6.3.2)
67
+ rubocop (~> 1.7)
68
+ simplecov (~> 0.21.2)
69
+
70
+ BUNDLED WITH
71
+ 2.2.22
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Dimitrios Lisenko
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Dimitrios Lisenko
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.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ [![codecov](https://codecov.io/gh/DimitriosLisenko/fet/branch/master/graph/badge.svg?token=6W2B0Z4E4S)](https://codecov.io/gh/DimitriosLisenko/fet)
2
+
3
+ # FET (Functional Ear Trainer)
4
+ Create MIDI files for functional ear training. Each file will contain a major/minor chord progression, followed by note(s) that you should identify the scale degree of by ear.
5
+
6
+ ## Installation
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'fet'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install fet
20
+
21
+ ## Usage
22
+ Refer to [the rdoc](https://github.com/DimitriosLisenko/fet/blob/master/fet.rdoc) for detailed usage instructions and descriptions of commands.
23
+
24
+ ## Filename Format
25
+ The generators will currently create MIDI files. The correct answer is included in the filename.
26
+
27
+ ### Listening exercises
28
+ For listening exercises, here is a potential list of generated MIDI files (for 2 degrees):
29
+ ```sh
30
+ $ find .
31
+ ...
32
+ ./listening/major/DbM_b6(Bbb2)_5(Ab5).mid
33
+ ./listening/major/BbM_7(A4)_2(C6).mid
34
+ ./listening/major/EM_b6(C2)_3(G#2).mid
35
+ ./listening/major/GbM_6(Eb4)_3(Bb5).mid
36
+ ./listening/major/FM_6(D4)_3(A5).mid
37
+ ...
38
+ ./listening/minor/Dm_b7(C3)_1(D4).mid
39
+ ./listening/minor/F#m_b2(G2)_3(A#4).mid
40
+ ./listening/minor/G#m_b6(E1)_b2(A2).mid
41
+ ./listening/minor/Dm_6(B0)_7(C#3).mid
42
+ ./listening/minor/C#m_5(G#4)_6(A#4).mid
43
+ ...
44
+ ```
45
+ The file name contains all the information required for the answer. For example, `EM_b6(C2)_3(G#2).mid`:
46
+
47
+ `EM`: the chord progression is in E Major.
48
+
49
+ `b6`: the bottom note will be the b6 degree
50
+
51
+ `(C2)`: the [scientific pitch notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation) of which is C2
52
+
53
+ `3`: the next note from the bottom will be the 3 degree
54
+
55
+ `(G#2)`: the [scientific pitch notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation) of which is G#2
56
+
57
+ ### Singing exercises
58
+ The singing exercises will generate all possible combinations for keys and degrees as follows:
59
+ ```sh
60
+ $ find .
61
+ ...
62
+ ./singing/major/AM_1.mid
63
+ ./singing/major/BbM_3.mid
64
+ ./singing/major/CM_4.mid
65
+ ./singing/major/CM_5.mid
66
+ ./singing/major/BbM_2.mid
67
+ ...
68
+ ./singing/minor/Am_1.mid
69
+ ./singing/minor/Bbm_3.mid
70
+ ./singing/minor/Cm_4.mid
71
+ ./singing/minor/G#m_4.mid
72
+ ./singing/minor/F#m_1.mid
73
+ ...
74
+ ```
75
+ The file name contains all the information required for the answer. For example, `BbM_3.mid`:
76
+
77
+ `BbM`: the chord progression is in Bb Major.
78
+
79
+ `3`: you should sing the 3rd degree.
80
+
81
+ ### Single Note Listening exercises
82
+ For single note listening exercises, the same note is played across all possible keys:
83
+ ```sh
84
+ $ find .
85
+ ...
86
+ ./listening_single_note/major/CM_1.mid
87
+ ./listening_single_note/major/BM_b2.mid
88
+ ./listening_single_note/major/F#M_b5.mid
89
+ ...
90
+ ./listening_single_note/minor/Am_b3.mid
91
+ ./listening_single_note/minor/G#m_3.mid
92
+ ./listening_single_note/minor/Cm_1.mid
93
+ ...
94
+ ```
95
+ The file name contains all the information required for the answer. For example, `G#m_3.mid`:
96
+
97
+ `G#m`: the chord progression is in G# Minor.
98
+
99
+ `3`: the note that is played is the 3rd degree in this key.
100
+
101
+ ## Development
102
+
103
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
104
+
105
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
106
+
107
+ ## Contributing
108
+
109
+ Bug reports and pull requests are welcome on GitHub at https://github.com/DimitriosLisenko/fet.
110
+
111
+ ## License
112
+
113
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/README.rdoc ADDED
@@ -0,0 +1,6 @@
1
+ = fet
2
+
3
+ FET (Functional Ear Trainer)
4
+
5
+ :include:fet.rdoc
6
+
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ require "rubocop/rake_task"
13
+
14
+ RuboCop::RakeTask.new
15
+
16
+ require "rdoc/task"
17
+ Rake::RDocTask.new do |rd|
18
+ rd.main = "README.rdoc"
19
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb", "bin/**/*")
20
+ rd.title = "FET (Functional Ear Trainer)"
21
+ end
22
+
23
+ task(default: [:test, :rubocop])
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ rm -rf listening
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ rm -rf singing
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+ for i in ${1}/major/*.mid ; do
3
+ timidity -Ow -o - $i | lame - ${i/mid/mp3}
4
+ # rm $i
5
+ done
6
+
7
+ for i in ${1}/minor/*.mid ; do
8
+ timidity -Ow -o - $i | lame - ${i/mid/mp3}
9
+ # rm $i
10
+ done
11
+
12
+ mv ${1}/major/*.mp3 ${1}/major/mp3
13
+ mv ${1}/minor/*.mp3 ${1}/minor/mp3
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "fet"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/fet ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "gli"
6
+ require "fet"
7
+
8
+ # Class in charge of implementing command-line interface
9
+ class App
10
+ extend GLI::App
11
+
12
+ program_desc("Functional Ear Trainer")
13
+
14
+ version(Fet::VERSION)
15
+
16
+ subcommand_option_handling(:normal)
17
+ arguments(:strict)
18
+
19
+ desc("Generate MIDI files for ear training")
20
+ # arg_name "Describe arguments to generate here"
21
+ command(:generate) do |c|
22
+ c.desc("Generate MIDI files for listening")
23
+ c.long_desc("Each MIDI file will contain a chord progression, followed by the specified number of degrees - first harmonically, then melodically after a pause.")
24
+ c.command :listening do |listening|
25
+ listening.desc("Tempo at which the chord progression is played at")
26
+ listening.default_value(120)
27
+ listening.flag([:t, :tempo], type: Integer)
28
+
29
+ listening.desc("Number of degrees to play")
30
+ listening.default_value(1)
31
+ listening.flag([:d, :degrees], type: Integer, must_match: (1..11).map(&:to_s))
32
+
33
+ listening.desc("Number of exercises to generate")
34
+ listening.default_value(200)
35
+ listening.flag([:e, :exercises], type: Integer)
36
+
37
+ listening.desc("Generate all single degree listening exercises (ignores -e and -d flag)")
38
+ listening.default_value(false)
39
+ listening.switch [:a, :"all-single-degree"]
40
+
41
+ listening.action do |global_options, options, args|
42
+ Fet::Cli::Generate::Listening.run(global_options, options, args)
43
+ end
44
+ end
45
+ end
46
+
47
+ command(:generate) do |c|
48
+ c.desc("Generate MIDI files for listening (single note)")
49
+ c.long_desc("Each MIDI file will contain a chord progression, followed the same note across all files.")
50
+ c.command :single_note_listening do |single_note_listening|
51
+ single_note_listening.desc("Tempo at which the chord progression is played at")
52
+ single_note_listening.default_value(120)
53
+ single_note_listening.flag([:t, :tempo], type: Integer)
54
+
55
+ single_note_listening.action do |global_options, options, args|
56
+ Fet::Cli::Generate::SingleNoteListening.run(global_options, options, args)
57
+ end
58
+ end
59
+ end
60
+
61
+ command(:generate) do |c|
62
+ c.desc("Generate MIDI files for singing")
63
+ c.long_desc("Each MIDI file will contain a chord progression, followed by a specified pause, during which the degree should be sung."\
64
+ " The degree is then played for confirmation.")
65
+ c.command :singing do |singing|
66
+ singing.desc("Tempo at which the chord progression is played at")
67
+ singing.default_value(120)
68
+ singing.flag([:t, :tempo], type: Integer)
69
+
70
+ singing.desc("How many seconds to wait before playing the correct note")
71
+ singing.default_value(3)
72
+ singing.flag([:p, :pause], type: Integer)
73
+
74
+ singing.action do |global_options, options, args|
75
+ Fet::Cli::Generate::Singing.run(global_options, options, args)
76
+ end
77
+ end
78
+ end
79
+
80
+ # NOTE: if you need the backtrace for an exception, this can be uncommented
81
+ # on_error do |exception|
82
+ # puts exception.backtrace
83
+ # true
84
+ # end
85
+ end
86
+
87
+ exit App.run(ARGV)