ramekin 0.0.7 → 0.0.8
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 +4 -4
- data/README.md +18 -0
- data/lib/ramekin/cli.rb +6 -1
- data/lib/ramekin/errors.rb +2 -2
- data/lib/ramekin/meta.rb +18 -10
- data/lib/ramekin/renderer.rb +26 -13
- data/lib/ramekin/sample_pack.rb +4 -0
- data/lib/ramekin/spc_player.rb +5 -5
- data/lib/ramekin/tokenizer.rb +4 -3
- data/lib/ramekin/util.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 463b021dd0273151c13a7590db845acf584a2df021596dd715721964e777f6d9
|
4
|
+
data.tar.gz: 432c1eccc9c5443cc63ec828f87a319141caeb3080c847948634b7935553ec86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbe078d3e43b620748e3bcd91360d06e1bf2b9b804821d21a6479479fe519abb7d48643a8a95f45abfcfe512b2654b1a1f6424773282d294503799e2ee31175b
|
7
|
+
data.tar.gz: bd829fcd1272ac8279757c73963e407b90ef9257d104475aa07a5c52cf3ed16ce691d25ade84a3333fa2c243854948b92a7fcbfa90b47ee2fedad9c845b54c33
|
data/README.md
CHANGED
@@ -210,6 +210,24 @@ After the instrument declaration, you can use several commands to change the def
|
|
210
210
|
|
211
211
|
It is generally advised to stick with the default tuning. The `o5` declaration sets the *default octave* for the instrument to octave 5 (the default is 4). Whenever this instrument is selected, Ramekin will insert a switch to the specified octave.
|
212
212
|
|
213
|
+
### Echo settings
|
214
|
+
|
215
|
+
Echo settings can be set up with the `#echo/...` family of directives:
|
216
|
+
|
217
|
+
```elisp
|
218
|
+
#echo/channels:0,1,2,3
|
219
|
+
; or
|
220
|
+
#echo/channels:all
|
221
|
+
; or
|
222
|
+
#echo/channels:none
|
223
|
+
|
224
|
+
#echo/volume:20 ; range from -7f to 80, use negatives for surround
|
225
|
+
#echo/volume:20,30 ; set different values for left vs right echo
|
226
|
+
#echo/feedback:48 ; range from -7f to 80, use negatives for surround
|
227
|
+
#echo/fir:1 ; 1 or 0 to enable/disable the FIR filter
|
228
|
+
```
|
229
|
+
|
230
|
+
|
213
231
|
## Channel Commands
|
214
232
|
|
215
233
|
With your metadata all set up, it's time to add some notes!
|
data/lib/ramekin/cli.rb
CHANGED
@@ -111,6 +111,11 @@ module Ramekin
|
|
111
111
|
when '--package'
|
112
112
|
@output_package = argv.shift or usage! 'missing dirname after --package'
|
113
113
|
when '--play'
|
114
|
+
if argv.any? && argv[0] =~ /\A\d+\z/
|
115
|
+
@play_offset = argv.shift
|
116
|
+
else
|
117
|
+
@play_offset = 0
|
118
|
+
end
|
114
119
|
@play = true
|
115
120
|
when '--wav'
|
116
121
|
arg = argv.shift or usage! 'missing wav file after --render'
|
@@ -232,7 +237,7 @@ module Ramekin
|
|
232
237
|
|
233
238
|
if @play
|
234
239
|
SPCPlayer.instance.setup!
|
235
|
-
SPCPlayer.instance.play(@play_spc)
|
240
|
+
SPCPlayer.instance.play(@play_spc, @play_offset)
|
236
241
|
end
|
237
242
|
|
238
243
|
if @verbose
|
data/lib/ramekin/errors.rb
CHANGED
@@ -15,7 +15,7 @@ module Ramekin
|
|
15
15
|
def self.error!(e, nesting: 0)
|
16
16
|
all << e
|
17
17
|
|
18
|
-
if ENV['RAMEKIN_DEBUG']
|
18
|
+
if ENV['RAMEKIN_DEBUG'] == '1'
|
19
19
|
if nesting >= 0
|
20
20
|
Pry.config.hooks.add_hook(:before_session, :ramekin) do |output, binding, pry|
|
21
21
|
Pry.config.hooks.delete_hook(:before_session, :ramekin)
|
@@ -35,7 +35,7 @@ module Ramekin
|
|
35
35
|
|
36
36
|
def present(orig)
|
37
37
|
out = []
|
38
|
-
out << "line #{@range.start.line}, col #{@range.start.col}:"
|
38
|
+
out << "line #{@range.start.line+1}, col #{@range.start.col+1}:"
|
39
39
|
out << " ---"
|
40
40
|
out << " #{orig[@range.pos_range]}"
|
41
41
|
out << " ---"
|
data/lib/ramekin/meta.rb
CHANGED
@@ -22,7 +22,7 @@ module Ramekin
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def echo_channel_bits
|
25
|
-
(@echo_channels ||= Set.new).map { |x| 1 << x }.inject(&:|)
|
25
|
+
(@echo_channels ||= Set.new).map { |x| 1 << x }.inject(0, &:|)
|
26
26
|
end
|
27
27
|
|
28
28
|
def echo_volumes
|
@@ -63,8 +63,6 @@ module Ramekin
|
|
63
63
|
error! 'invalid token in header'
|
64
64
|
end
|
65
65
|
end
|
66
|
-
|
67
|
-
@sample_groups << 'default' if @sample_groups.empty?
|
68
66
|
end
|
69
67
|
|
70
68
|
SURROUND_R = (-0x7f..0x80)
|
@@ -84,21 +82,25 @@ module Ramekin
|
|
84
82
|
when 'instrument'
|
85
83
|
name, path = expect_args(:instrument, :string)
|
86
84
|
extensions = []
|
87
|
-
while (el = check_arg(:adsr, :tuning, :o))
|
85
|
+
while (el = check_arg(:adsr, :tuning, :gain, :o))
|
88
86
|
extensions << el
|
89
87
|
end
|
90
88
|
|
91
89
|
return unless @current_pack
|
92
|
-
@instruments << Instrument.new(@current_pack, @
|
90
|
+
@instruments << Instrument.new(@current_pack, @current_directive, name, path, extensions)
|
93
91
|
when 'default', 'optimized' then @sample_groups << @current
|
94
92
|
|
95
93
|
# TODO: real echo syntax
|
96
94
|
when 'echo' then @echo = expect_args(*([:hex] * 8))
|
97
95
|
when 'echo/channels'
|
98
96
|
channels = @current_directive.values[1]
|
99
|
-
|
97
|
+
case channels
|
98
|
+
when 'all'
|
100
99
|
@echo_channels = Set.new(0..7)
|
101
100
|
return
|
101
|
+
when 'none'
|
102
|
+
@echo_channels = Set.new
|
103
|
+
return
|
102
104
|
end
|
103
105
|
|
104
106
|
unless channels && channels =~ /\A\d(,\d)+\z/
|
@@ -250,12 +252,12 @@ module Ramekin
|
|
250
252
|
|
251
253
|
def adsr
|
252
254
|
@adsr ||= ext_adsr || pack_adsr \
|
253
|
-
or error! "no adsr configured for #{name}"
|
255
|
+
or error! "no adsr configured for #{name.value}", el: name
|
254
256
|
end
|
255
257
|
|
256
258
|
def tuning
|
257
259
|
@tuning ||= ext_tuning || pack_tuning \
|
258
|
-
or error! "no tuning configured for #{name}"
|
260
|
+
or error! "no tuning configured for #{name.value}", el: name
|
259
261
|
end
|
260
262
|
|
261
263
|
def pack_tuning
|
@@ -284,8 +286,7 @@ module Ramekin
|
|
284
286
|
end
|
285
287
|
|
286
288
|
def gain
|
287
|
-
@gain ||= ext_gain || pack_gain
|
288
|
-
or error! "no gain configured for #{name}"
|
289
|
+
@gain ||= ext_gain || pack_gain || 0xFF
|
289
290
|
end
|
290
291
|
|
291
292
|
def hexes
|
@@ -293,6 +294,8 @@ module Ramekin
|
|
293
294
|
t1, t2 = self.tuning
|
294
295
|
g = self.gain
|
295
296
|
|
297
|
+
return [] unless a && d && s && r && t1 && t2 && g
|
298
|
+
|
296
299
|
adsr1 = ((7 - d)*16 | 0x80) + (15 - a)
|
297
300
|
adsr2 = (s*32 + (31-r))
|
298
301
|
|
@@ -300,6 +303,11 @@ module Ramekin
|
|
300
303
|
end
|
301
304
|
|
302
305
|
def to_amk
|
306
|
+
unless @pack.has?(@path.value)
|
307
|
+
error! "no sample named #{path.value.inspect} in pack #{pack.name.inspect}", el: @path
|
308
|
+
return ''
|
309
|
+
end
|
310
|
+
|
303
311
|
"#{File.basename(sample_name).inspect} #{hexes.map { |h| "$#{h}" }.join(' ')}"
|
304
312
|
end
|
305
313
|
|
data/lib/ramekin/renderer.rb
CHANGED
@@ -74,13 +74,17 @@ module Ramekin
|
|
74
74
|
yield "; https://codeberg.org/jneen/ramekin\n\n"
|
75
75
|
|
76
76
|
# TODO
|
77
|
-
yield "#amk 2\n\n"
|
77
|
+
yield "#amk #{@track.meta.amk&.value || 2}\n\n"
|
78
78
|
|
79
79
|
if m.instruments.any?
|
80
80
|
yield "#path #{@filename.chomp('.rmk').inspect}\n"
|
81
81
|
yield "#samples {\n"
|
82
|
-
m.sample_groups.
|
83
|
-
yield "
|
82
|
+
if m.sample_groups.empty?
|
83
|
+
yield " #default"
|
84
|
+
else
|
85
|
+
m.sample_groups.each do |group|
|
86
|
+
yield " ##{group.value}\n"
|
87
|
+
end
|
84
88
|
end
|
85
89
|
|
86
90
|
m.instruments.map(&:sample_name).sort.uniq.each do |sample|
|
@@ -170,13 +174,7 @@ module Ramekin
|
|
170
174
|
# reset tick counter for newlines
|
171
175
|
@tick = 0
|
172
176
|
when :transpose
|
173
|
-
|
174
|
-
|
175
|
-
if interval < 0
|
176
|
-
interval = 0x80 - interval
|
177
|
-
end
|
178
|
-
|
179
|
-
yield sprintf("$fa$02$%02x", token.value.to_i)
|
177
|
+
yield sprintf("$fa$02$%02x", token.value.to_i & 0x7f)
|
180
178
|
when :instrument
|
181
179
|
case token.value
|
182
180
|
when /\A\d+\z/ then yield "@#{token.value}"
|
@@ -189,11 +187,12 @@ module Ramekin
|
|
189
187
|
yield "@#{@instrument_index[token.value]}"
|
190
188
|
end
|
191
189
|
when :v
|
192
|
-
|
193
|
-
|
190
|
+
vol, time = token.values.compact.map(&:to_i)
|
191
|
+
yield velocity_command(vol, time)
|
192
|
+
@volume = vol
|
194
193
|
when :relv
|
195
194
|
relvol, duration = token.values
|
196
|
-
yield
|
195
|
+
yield velocity_command(@volume + relvol.to_i, duration)
|
197
196
|
when :adsr
|
198
197
|
vals = token.value.split(',').map { |x| x.to_i(16) }
|
199
198
|
error! 'invalid #adsr, expected 4 arguments' unless vals.size == 4
|
@@ -254,6 +253,20 @@ module Ramekin
|
|
254
253
|
end
|
255
254
|
end
|
256
255
|
|
256
|
+
def velocity_command(vol, time=nil)
|
257
|
+
vol = 255 if vol > 255
|
258
|
+
vol = 0 if vol < 0
|
259
|
+
|
260
|
+
if time.nil?
|
261
|
+
"v#{vol}"
|
262
|
+
else
|
263
|
+
time = time.to_i
|
264
|
+
time = 255 if time > 255
|
265
|
+
time = 0 if time < 0
|
266
|
+
sprintf("$E8$%02x$%02x", time, vol)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
257
270
|
def render_directive(token)
|
258
271
|
case token.value
|
259
272
|
when 'SPC'
|
data/lib/ramekin/sample_pack.rb
CHANGED
@@ -105,6 +105,10 @@ module Ramekin
|
|
105
105
|
File.join(prefix_dir, "#{path}.brr")
|
106
106
|
end
|
107
107
|
|
108
|
+
def has?(path)
|
109
|
+
File.exist?(find(path))
|
110
|
+
end
|
111
|
+
|
108
112
|
def tunings_for(path)
|
109
113
|
rel = Pathname.new(find(path)).relative_path_from(dir).to_s
|
110
114
|
(tunings[rel] || []).map(&:last)
|
data/lib/ramekin/spc_player.rb
CHANGED
@@ -37,7 +37,7 @@ module Ramekin
|
|
37
37
|
File.exist?("#@spcplay_dir/spcplay.exe")
|
38
38
|
end
|
39
39
|
|
40
|
-
def play(fname)
|
40
|
+
def play(fname, offset_=0)
|
41
41
|
fname = File.expand_path(fname)
|
42
42
|
Dir.chdir(@spcplay_dir) do
|
43
43
|
sys "spcplay.exe", fname
|
@@ -61,8 +61,8 @@ module Ramekin
|
|
61
61
|
end
|
62
62
|
|
63
63
|
class NormalSPCPlayer < SPCPlayer
|
64
|
-
def play(fname)
|
65
|
-
sys "#@spct_dir/spct", 'play', fname
|
64
|
+
def play(fname, offset=0)
|
65
|
+
sys "#@spct_dir/spct", 'play', fname, '--seek', offset
|
66
66
|
end
|
67
67
|
|
68
68
|
def render(fname, outfile, seconds=nil)
|
@@ -110,9 +110,9 @@ module Ramekin
|
|
110
110
|
sys(*args)
|
111
111
|
end
|
112
112
|
|
113
|
-
def play(fname)
|
113
|
+
def play(fname, offset=0)
|
114
114
|
if File.basename(@path, '.exe') == 'spct'
|
115
|
-
sys @path, 'play', fname
|
115
|
+
sys @path, 'play', fname, '--seek', offset
|
116
116
|
else
|
117
117
|
sys @path, fname
|
118
118
|
end
|
data/lib/ramekin/tokenizer.rb
CHANGED
@@ -135,9 +135,9 @@ module Ramekin
|
|
135
135
|
newlines = matched.count("\n")
|
136
136
|
@line += newlines
|
137
137
|
if newlines > 0
|
138
|
-
@col = find_colno(matched
|
138
|
+
@col = find_colno(matched)
|
139
139
|
else
|
140
|
-
@col += find_colno(matched
|
140
|
+
@col += find_colno(matched)
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
@@ -208,6 +208,7 @@ module Ramekin
|
|
208
208
|
return [:endif, m(1)] if match /#endif/
|
209
209
|
|
210
210
|
return [:adsr, m(1)] if match /#adsr:(\h+(?:,\h+)*)/
|
211
|
+
return [:gain, m(1)] if match /#gain:(\h+)/
|
211
212
|
return [:tuning, m(1)] if match /#tuning:(\h\h\h\h)/
|
212
213
|
return [:bpm, m(1)] if match /#bpm:(\d+)/
|
213
214
|
return [:legato_tie] if match /~/
|
@@ -259,7 +260,7 @@ module Ramekin
|
|
259
260
|
return [:q, m(1)] if match /q(\h\h)/
|
260
261
|
return [:n, m(1)] if match /n(\h\h?)/
|
261
262
|
|
262
|
-
error! "unknown token near: #{@scanner.peek(10)}"
|
263
|
+
error! "unknown token near: #{@scanner.peek(10)}", el: @last_token
|
263
264
|
|
264
265
|
return [:unknown, m] if match /./
|
265
266
|
end
|
data/lib/ramekin/util.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ramekin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jneen
|
8
8
|
autorequire:
|
9
9
|
bindir: gembin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: strscan
|