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
         |