wavify 0.1.0 → 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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -1
  3. data/README.md +204 -22
  4. data/exe/wavify +6 -0
  5. data/lib/wavify/adapters.rb +81 -0
  6. data/lib/wavify/audio.rb +1066 -120
  7. data/lib/wavify/cli.rb +237 -0
  8. data/lib/wavify/codecs/aiff.rb +388 -87
  9. data/lib/wavify/codecs/base.rb +98 -5
  10. data/lib/wavify/codecs/flac.rb +660 -170
  11. data/lib/wavify/codecs/ogg_vorbis.rb +515 -155
  12. data/lib/wavify/codecs/raw.rb +235 -45
  13. data/lib/wavify/codecs/registry.rb +272 -10
  14. data/lib/wavify/codecs/wav.rb +453 -74
  15. data/lib/wavify/core/duration.rb +54 -2
  16. data/lib/wavify/core/format.rb +96 -11
  17. data/lib/wavify/core/sample_buffer.rb +648 -60
  18. data/lib/wavify/core/stream.rb +590 -34
  19. data/lib/wavify/dsl.rb +712 -100
  20. data/lib/wavify/dsp/automation.rb +109 -0
  21. data/lib/wavify/dsp/effects/auto_pan.rb +71 -0
  22. data/lib/wavify/dsp/effects/bitcrusher.rb +74 -0
  23. data/lib/wavify/dsp/effects/chorus.rb +15 -4
  24. data/lib/wavify/dsp/effects/compressor.rb +133 -23
  25. data/lib/wavify/dsp/effects/delay.rb +46 -1
  26. data/lib/wavify/dsp/effects/distortion.rb +3 -2
  27. data/lib/wavify/dsp/effects/effect_base.rb +69 -2
  28. data/lib/wavify/dsp/effects/effect_chain.rb +94 -0
  29. data/lib/wavify/dsp/effects/envelope_controlled_effect.rb +93 -0
  30. data/lib/wavify/dsp/effects/eq.rb +102 -0
  31. data/lib/wavify/dsp/effects/expander.rb +90 -0
  32. data/lib/wavify/dsp/effects/flanger.rb +112 -0
  33. data/lib/wavify/dsp/effects/limiter.rb +259 -0
  34. data/lib/wavify/dsp/effects/mastering_chain.rb +31 -0
  35. data/lib/wavify/dsp/effects/noise_gate.rb +72 -0
  36. data/lib/wavify/dsp/effects/phaser.rb +112 -0
  37. data/lib/wavify/dsp/effects/podcast_chain.rb +32 -0
  38. data/lib/wavify/dsp/effects/reverb.rb +100 -14
  39. data/lib/wavify/dsp/effects/soft_limiter.rb +55 -0
  40. data/lib/wavify/dsp/effects/stereo_widener.rb +73 -0
  41. data/lib/wavify/dsp/effects/tremolo.rb +66 -0
  42. data/lib/wavify/dsp/effects/vibrato.rb +102 -0
  43. data/lib/wavify/dsp/effects.rb +106 -0
  44. data/lib/wavify/dsp/envelope.rb +90 -19
  45. data/lib/wavify/dsp/filter.rb +149 -8
  46. data/lib/wavify/dsp/headroom.rb +57 -0
  47. data/lib/wavify/dsp/lfo.rb +65 -0
  48. data/lib/wavify/dsp/loudness_meter.rb +281 -0
  49. data/lib/wavify/dsp/oscillator.rb +261 -22
  50. data/lib/wavify/dsp/processor.rb +90 -0
  51. data/lib/wavify/errors.rb +2 -2
  52. data/lib/wavify/sequencer/engine.rb +405 -89
  53. data/lib/wavify/sequencer/note_sequence.rb +45 -7
  54. data/lib/wavify/sequencer/pattern.rb +121 -12
  55. data/lib/wavify/sequencer/track.rb +149 -10
  56. data/lib/wavify/version.rb +1 -1
  57. data/lib/wavify.rb +18 -0
  58. data/sig/audio.rbs +86 -0
  59. data/sig/codecs.rbs +77 -0
  60. data/sig/core.rbs +108 -0
  61. data/sig/dsl.rbs +32 -0
  62. data/sig/dsp.rbs +87 -0
  63. data/sig/effects.rbs +129 -0
  64. data/sig/public_api.yml +111 -0
  65. data/sig/sequencer.rbs +126 -0
  66. data/sig/stream.rbs +30 -0
  67. data/sig/wavify.rbs +24 -0
  68. metadata +44 -58
  69. data/.serena/.gitignore +0 -1
  70. data/.serena/memories/project_overview.md +0 -5
  71. data/.serena/memories/style_and_completion.md +0 -5
  72. data/.serena/memories/suggested_commands.md +0 -11
  73. data/.serena/project.yml +0 -126
  74. data/.simplecov +0 -18
  75. data/.yardopts +0 -4
  76. data/Rakefile +0 -190
  77. data/benchmarks/README.md +0 -46
  78. data/benchmarks/benchmark_helper.rb +0 -112
  79. data/benchmarks/dsp_effects_benchmark.rb +0 -46
  80. data/benchmarks/flac_benchmark.rb +0 -74
  81. data/benchmarks/streaming_memory_benchmark.rb +0 -94
  82. data/benchmarks/wav_io_benchmark.rb +0 -110
  83. data/examples/audio_processing.rb +0 -73
  84. data/examples/cinematic_transition.rb +0 -118
  85. data/examples/drum_machine.rb +0 -74
  86. data/examples/format_convert.rb +0 -81
  87. data/examples/hybrid_arrangement.rb +0 -165
  88. data/examples/streaming_master_chain.rb +0 -129
  89. data/examples/synth_pad.rb +0 -42
  90. data/tools/fixture_writer.rb +0 -85
data/sig/codecs.rbs ADDED
@@ -0,0 +1,77 @@
1
+ module Wavify
2
+ module Codecs
3
+ class Base
4
+ def self.available?: () -> bool
5
+ def self.can_read?: (String | IO io_or_path) -> bool
6
+ def self.read: (String | IO io_or_path, **untyped options) -> Core::SampleBuffer
7
+ def self.write: (String | IO io_or_path, Core::SampleBuffer sample_buffer, **untyped options) -> untyped
8
+ def self.stream_read: (String | IO io_or_path, **untyped options) { (Core::SampleBuffer) -> void } -> untyped
9
+ def self.stream_write: (String | IO io_or_path, **untyped options) { (untyped) -> void } -> untyped
10
+ def self.metadata: (String | IO io_or_path, **untyped options) -> Hash[Symbol, untyped]
11
+ end
12
+
13
+ class Wav < Base
14
+ def self.can_read?: (String | IO io_or_path) -> bool
15
+ def self.read: (String | IO io_or_path, ?format: Core::Format?, ?warning_io: IO?) -> Core::SampleBuffer
16
+ def self.write: (String | IO io_or_path, Core::SampleBuffer sample_buffer, ?format: Core::Format?, ?info: Hash[Symbol, untyped]?, **untyped codec_options) -> Core::SampleBuffer
17
+ def self.stream_read: (String | IO io_or_path, ?chunk_size: Integer, ?warning_io: IO?) { (Core::SampleBuffer) -> void } -> Core::Format
18
+ def self.stream_write: (String | IO io_or_path, format: Core::Format, ?info: Hash[Symbol, untyped]?, **untyped codec_options) { (untyped) -> void } -> untyped
19
+ def self.metadata: (String | IO io_or_path) -> Hash[Symbol, untyped]
20
+ end
21
+
22
+ class Aiff < Base
23
+ def self.can_read?: (String | IO io_or_path) -> bool
24
+ def self.read: (String | IO io_or_path, ?format: Core::Format?, ?warning_io: IO?) -> Core::SampleBuffer
25
+ def self.write: (String | IO io_or_path, Core::SampleBuffer sample_buffer, ?format: Core::Format?, **untyped options) -> Core::SampleBuffer
26
+ def self.stream_read: (String | IO io_or_path, ?chunk_size: Integer, ?warning_io: IO?) { (Core::SampleBuffer) -> void } -> Core::Format
27
+ def self.stream_write: (String | IO io_or_path, format: Core::Format, **untyped options) { (untyped) -> void } -> untyped
28
+ def self.metadata: (String | IO io_or_path) -> Hash[Symbol, untyped]
29
+ end
30
+
31
+ class Flac < Base
32
+ def self.can_read?: (String | IO io_or_path) -> bool
33
+ def self.read: (String | IO io_or_path, ?format: Core::Format?) -> Core::SampleBuffer
34
+ def self.write: (String | IO io_or_path, Core::SampleBuffer sample_buffer, format: Core::Format, **untyped options) -> Core::SampleBuffer
35
+ def self.stream_read: (String | IO io_or_path, ?chunk_size: Integer) { (Core::SampleBuffer) -> void } -> Core::Format
36
+ def self.stream_write: (String | IO io_or_path, format: Core::Format, **untyped options) { (untyped) -> void } -> untyped
37
+ def self.metadata: (String | IO io_or_path) -> Hash[Symbol, untyped]
38
+ end
39
+
40
+ class OggVorbis < Base
41
+ def self.available?: () -> bool
42
+ def self.runtime_diagnostics: () -> Hash[Symbol, untyped]
43
+ def self.can_read?: (String | IO io_or_path) -> bool
44
+ def self.read: (String | IO io_or_path, ?format: Core::Format?, ?mix_strategy: Symbol) -> Core::SampleBuffer
45
+ def self.write: (String | IO io_or_path, Core::SampleBuffer sample_buffer, format: Core::Format, ?quality: Numeric, **untyped options) -> Core::SampleBuffer
46
+ def self.stream_read: (String | IO io_or_path, ?chunk_size: Integer, ?mix_strategy: Symbol) { (Core::SampleBuffer) -> void } -> Core::Format
47
+ def self.stream_write: (String | IO io_or_path, format: Core::Format, ?quality: Numeric, **untyped options) { (untyped) -> void } -> untyped
48
+ def self.metadata: (String | IO io_or_path) -> Hash[Symbol, untyped]
49
+ end
50
+
51
+ class Raw < Base
52
+ def self.can_read?: (String | IO io_or_path) -> bool
53
+ def self.read: (String | IO io_or_path, ?format: Core::Format?, ?endianness: Symbol, ?signed: bool?, ?float_domain: Symbol, **untyped options) -> Core::SampleBuffer
54
+ def self.write: (String | IO io_or_path, Core::SampleBuffer sample_buffer, format: Core::Format, ?endianness: Symbol, ?signed: bool?, ?float_domain: Symbol, **untyped options) -> String | IO
55
+ def self.stream_read: (String | IO io_or_path, format: Core::Format, ?chunk_size: Integer, ?endianness: Symbol, ?signed: bool?, ?float_domain: Symbol, **untyped options) { (Core::SampleBuffer) -> void } -> nil
56
+ def self.stream_write: (String | IO io_or_path, format: Core::Format, ?endianness: Symbol, ?signed: bool?, ?float_domain: Symbol, **untyped options) { (untyped) -> void } -> String | IO
57
+ def self.metadata: (String | IO io_or_path, format: Core::Format, ?endianness: Symbol, ?signed: bool?, ?float_domain: Symbol, **untyped options) -> Hash[Symbol, untyped]
58
+ end
59
+
60
+ class Registry
61
+ def self.detect: (String | IO io_or_path, ?strict: bool, ?filename: String?) -> singleton(Base)
62
+ def self.detect_for_read: (String | IO io_or_path, ?strict: bool, ?filename: String?) -> singleton(Base)
63
+ def self.detect_for_write: (String | IO io_or_path, ?filename: String?) -> singleton(Base)
64
+ def self.resolve: (String | Symbol | singleton(Base) codec) -> singleton(Base)
65
+ def self.register: (String extension, singleton(Base) codec, ?magic: String | untyped, ?priority: Integer, ?probe_size: Integer) -> singleton(Base)
66
+ def self.unregister: (String extension) -> singleton(Base)?
67
+ def self.supported_formats: () -> Array[String]
68
+ def self.available_formats: () -> Array[String]
69
+ end
70
+
71
+ def self.detect: (String | IO io_or_path, ?strict: bool, ?filename: String?) -> singleton(Base)
72
+ def self.register: (String extension, singleton(Base) codec, **untyped options) -> singleton(Base)
73
+ def self.unregister: (String extension) -> singleton(Base)?
74
+ def self.supported_formats: () -> Array[String]
75
+ def self.available_formats: () -> Array[String]
76
+ end
77
+ end
data/sig/core.rbs ADDED
@@ -0,0 +1,108 @@
1
+ module Wavify
2
+ module Core
3
+ class Duration
4
+ include Comparable[Duration]
5
+
6
+ attr_reader total_seconds: Float
7
+
8
+ def self.from_samples: (Integer sample_frames, Integer sample_rate) -> Duration
9
+ def self.parse: (String value) -> Duration
10
+ def initialize: (Numeric total_seconds) -> void
11
+ def <=>: (Duration other) -> Integer?
12
+ def eql?: (untyped other) -> bool
13
+ def hash: () -> Integer
14
+ def +: (Duration other) -> Duration
15
+ def -: (Duration other) -> Duration
16
+ def hours: () -> Integer
17
+ def minutes: () -> Integer
18
+ def seconds: () -> Integer
19
+ def milliseconds: () -> Integer
20
+ def to_s: () -> String
21
+ end
22
+
23
+ class Format
24
+ attr_reader channels: Integer
25
+ attr_reader sample_rate: Integer
26
+ attr_reader bit_depth: Integer
27
+ attr_reader valid_bits: Integer
28
+ attr_reader sample_format: Symbol
29
+ attr_reader channel_layout: Array[Symbol]?
30
+
31
+ def initialize: (channels: Integer, sample_rate: Integer, bit_depth: Integer, ?sample_format: Symbol, ?valid_bits: Integer?, ?channel_layout: Array[Symbol] | :unknown | nil) -> void
32
+ def with: (?channels: Integer?, ?sample_rate: Integer?, ?bit_depth: Integer?, ?sample_format: Symbol?, ?valid_bits: Integer?, ?channel_layout: Array[Symbol] | :unknown | nil) -> Format
33
+ def mono?: () -> bool
34
+ def stereo?: () -> bool
35
+ def block_align: () -> Integer
36
+ def byte_rate: () -> Integer
37
+ def bytes_per_sample: () -> Integer
38
+ def ==: (untyped other) -> bool
39
+ def eql?: (untyped other) -> bool
40
+ def hash: () -> Integer
41
+ end
42
+
43
+ class SampleBuffer
44
+ class FrameView
45
+ include Enumerable[Array[Numeric]]
46
+
47
+ attr_reader channels: Integer
48
+ attr_reader frame_count: Integer
49
+
50
+ def initialize: (Array[Numeric] samples, Integer channels, ?start_frame: Integer, ?frame_count: Integer?) -> void
51
+ def each: () { (Array[Numeric]) -> void } -> FrameView
52
+ | () -> Enumerator[Array[Numeric], FrameView]
53
+ def []: (Integer index) -> Array[Numeric]?
54
+ def slice: (Integer start_frame, Integer frame_length) -> FrameView
55
+ def length: () -> Integer
56
+ end
57
+
58
+ class View
59
+ include Enumerable[Numeric]
60
+
61
+ attr_reader format: Format
62
+ attr_reader duration: Duration
63
+
64
+ def initialize: (Array[Numeric] samples, Format format, ?start_frame: Integer, ?frame_count: Integer?) -> void
65
+ def each: () { (Numeric) -> void } -> View
66
+ | () -> Enumerator[Numeric, View]
67
+ def samples: () -> Array[Numeric]
68
+ def length: () -> Integer
69
+ def size: () -> Integer
70
+ def sample_frame_count: () -> Integer
71
+ def frame_view: () -> FrameView
72
+ def slice: (Integer start_frame, Integer frame_length) -> View
73
+ def to_sample_buffer: () -> SampleBuffer
74
+ def convert: (Format new_format, **untyped options) -> SampleBuffer
75
+ end
76
+
77
+ include Enumerable[Numeric]
78
+
79
+ attr_reader format: Format
80
+ attr_reader duration: Duration
81
+
82
+ def self.from_pcm_samples: (Array[Numeric] samples, Format format, ?storage: Symbol) -> SampleBuffer
83
+ def self.from_normalized_samples: (Array[Numeric] samples, Format format, ?storage: Symbol) -> SampleBuffer
84
+ def initialize: (Array[Numeric] samples, Format format, ?storage: Symbol) -> void
85
+ def samples: () -> Array[Numeric]
86
+ def each: () { (Numeric) -> void } -> SampleBuffer
87
+ | () -> Enumerator[Numeric, SampleBuffer]
88
+ def each_frame_sample: () { (Numeric, Integer, Integer) -> void } -> SampleBuffer
89
+ | () -> Enumerator[Numeric, SampleBuffer]
90
+ def storage: () -> Symbol
91
+ def packed?: () -> bool
92
+ def packed_bytesize: () -> Integer
93
+ def length: () -> Integer
94
+ def size: () -> Integer
95
+ def sample_frame_count: () -> Integer
96
+ def frame_view: () -> FrameView
97
+ def view: (?start_frame: Integer, ?frame_length: Integer?) -> View
98
+ def convert: (Format new_format, ?dither: bool, ?dither_seed: Integer?, ?resampler: Symbol) -> SampleBuffer
99
+ def reverse: () -> SampleBuffer
100
+ def slice: (Integer start_frame, Integer frame_length) -> SampleBuffer
101
+ def concat: (SampleBuffer other) -> SampleBuffer
102
+ def +: (SampleBuffer other) -> SampleBuffer
103
+ def ==: (untyped other) -> bool
104
+ def eql?: (untyped other) -> bool
105
+ def hash: () -> Integer
106
+ end
107
+ end
108
+ end
data/sig/dsl.rbs ADDED
@@ -0,0 +1,32 @@
1
+ module Wavify
2
+ module DSL
3
+ class SongDefinition
4
+ attr_reader format: Core::Format
5
+ attr_reader tempo: Float
6
+ attr_reader beats_per_bar: Integer
7
+ attr_reader swing: Float
8
+ attr_reader tracks: Array[untyped]
9
+ attr_reader sections: Array[untyped]
10
+ attr_reader default_bars: Integer
11
+ attr_reader random_seed: Integer
12
+
13
+ def arrangement?: () -> bool
14
+ def engine: () -> Sequencer::Engine
15
+ def sequencer_tracks: () -> Array[Sequencer::Track]
16
+ def validate!: (?deep: bool) -> true
17
+ def arrangement: () -> Array[Hash[Symbol, untyped]]
18
+ def duration: (?default_bars: Integer) -> Core::Duration
19
+ def length: (?default_bars: Integer) -> Core::Duration
20
+ def timeline: (?default_bars: Integer) -> Array[Hash[Symbol, untyped]]
21
+ def timeline_json: (?default_bars: Integer) -> String
22
+ def timeline_text: (?default_bars: Integer) -> String
23
+ def render: (?default_bars: Integer, ?stems: bool) -> Audio | Hash[Symbol, Audio]
24
+ def write: (String path, ?default_bars: Integer) -> Audio
25
+ def write_stems: (String directory, ?default_bars: Integer, ?overwrite: bool) -> Hash[Symbol, String]
26
+ end
27
+
28
+ def self.build_definition: (format: Core::Format, ?tempo: Numeric, ?beats_per_bar: Integer, ?swing: Numeric, ?default_bars: Integer, ?random_seed: Integer) { () -> void } -> SongDefinition
29
+ def self.validate: (format: Core::Format, ?tempo: Numeric, ?beats_per_bar: Integer, ?swing: Numeric, ?default_bars: Integer, ?random_seed: Integer) { () -> void } -> true
30
+ def self.effect: (String | Symbol name, **untyped params) -> untyped
31
+ end
32
+ end
data/sig/dsp.rbs ADDED
@@ -0,0 +1,87 @@
1
+ module Wavify
2
+ module DSP
3
+ module Processor
4
+ def self.build_runtime: (untyped processor) -> untyped
5
+ def self.process: (untyped processor, Core::SampleBuffer buffer) -> Core::SampleBuffer
6
+ def self.flush: (untyped processor, ?format: Core::Format?) -> Enumerator[Core::SampleBuffer, nil]
7
+ def self.render: (untyped processor, Core::SampleBuffer buffer) -> Core::SampleBuffer
8
+ def self.duration: (untyped processor, Symbol method_name) -> Float
9
+ end
10
+
11
+ module Headroom
12
+ def self.apply!: (Array[Numeric] samples, ?strategy: Symbol, ?format: Core::Format?, ?smoothing: Numeric) -> Array[Numeric]
13
+ end
14
+
15
+ class Automation
16
+ attr_reader points: Array[[Float, Float]]
17
+
18
+ def initialize: (Array[untyped] points) -> void
19
+ def value_at: (Numeric time) -> Float
20
+ def apply: (Core::SampleBuffer buffer) { (Numeric, Float, Integer) -> Numeric } -> Core::SampleBuffer
21
+ def apply_gain: (Core::SampleBuffer buffer, ?unit: Symbol) -> Core::SampleBuffer
22
+ end
23
+
24
+ class Envelope
25
+ attr_reader attack: Float
26
+ attr_reader hold: Float
27
+ attr_reader decay: Float
28
+ attr_reader sustain: Float
29
+ attr_reader release: Float
30
+ attr_reader curve: Symbol
31
+
32
+ def initialize: (attack: Numeric, decay: Numeric, sustain: Numeric, release: Numeric, ?hold: Numeric, ?curve: Symbol) -> void
33
+ def gain_at: (Numeric time, note_on_duration: Numeric) -> Float
34
+ def apply: (Core::SampleBuffer buffer, note_on_duration: Numeric) -> Core::SampleBuffer
35
+ def render_with_tail: (Core::SampleBuffer buffer, note_on_duration: Numeric) -> Core::SampleBuffer
36
+ def tail_duration: () -> Float
37
+ def latency: () -> Float
38
+ def lookahead: () -> Float
39
+ end
40
+
41
+ class Filter
42
+ attr_reader type: Symbol
43
+ attr_reader cutoff: Float
44
+ attr_reader q: Float
45
+ attr_reader gain_db: Float
46
+
47
+ def self.lowpass: (cutoff: Numeric, ?q: Numeric) -> Filter
48
+ def self.highpass: (cutoff: Numeric, ?q: Numeric) -> Filter
49
+ def self.bandpass: (?center: Numeric?, ?bandwidth: Numeric?, ?cutoff: Numeric?, ?q: Numeric?) -> Filter
50
+ def self.notch: (cutoff: Numeric, ?q: Numeric) -> Filter
51
+ def self.peaking: (cutoff: Numeric, ?q: Numeric, ?gain_db: Numeric) -> Filter
52
+ def self.lowshelf: (cutoff: Numeric, gain_db: Numeric) -> Filter
53
+ def self.highshelf: (cutoff: Numeric, gain_db: Numeric) -> Filter
54
+ def initialize: (Symbol type, cutoff: Numeric, ?q: Numeric, ?gain_db: Numeric) -> void
55
+ def apply: (Core::SampleBuffer buffer) -> Core::SampleBuffer
56
+ def process: (Core::SampleBuffer buffer) -> Core::SampleBuffer
57
+ def process_sample: (Numeric sample, sample_rate: Integer, channel: Integer, channels: Integer) -> Float
58
+ def flush: (?format: Core::Format?) -> Core::SampleBuffer?
59
+ def reset: () -> Filter
60
+ def build_runtime: () -> Filter
61
+ def tail_duration: () -> Float
62
+ def latency: () -> Float
63
+ def lookahead: () -> Float
64
+ end
65
+
66
+ class LFO
67
+ def initialize: (rate: Numeric, sample_rate: Numeric, ?waveform: Symbol, ?phase: Numeric) -> void
68
+ def next_value: () -> Float
69
+ def value_at: (?Numeric offset) -> Float
70
+ def reset: () -> LFO
71
+ end
72
+
73
+ class LoudnessMeter
74
+ def self.integrated: (Array[Numeric] | Core::SampleBuffer samples, ?sample_rate: Integer?, ?channels: Integer?, ?format: Core::Format?, ?channel_layout: Array[Symbol]?) -> Float
75
+ def self.momentary: (Array[Numeric] | Core::SampleBuffer samples, ?sample_rate: Integer?, ?channels: Integer?, ?format: Core::Format?, ?channel_layout: Array[Symbol]?) -> Float
76
+ def self.short_term: (Array[Numeric] | Core::SampleBuffer samples, ?sample_rate: Integer?, ?channels: Integer?, ?format: Core::Format?, ?channel_layout: Array[Symbol]?) -> Float
77
+ def self.true_peak: (Array[Numeric] | Core::SampleBuffer samples, ?sample_rate: Integer?, ?channels: Integer?, ?format: Core::Format?, ?oversampling: Integer) -> Float
78
+ end
79
+
80
+ class Oscillator
81
+ def initialize: (waveform: Symbol, frequency: Numeric, ?amplitude: Numeric, ?phase: Numeric, ?pulse_width: Numeric, ?detune: Numeric, ?unison: Integer, ?random: Random) -> void
82
+ def reset_phase: (?Numeric phase) -> Oscillator
83
+ def generate: (Numeric duration_seconds, format: Core::Format) -> Core::SampleBuffer
84
+ def each_sample: (format: Core::Format) -> Enumerator[Float, nil]
85
+ end
86
+ end
87
+ end
data/sig/effects.rbs ADDED
@@ -0,0 +1,129 @@
1
+ module Wavify
2
+ module DSP
3
+ module Effects
4
+ def self.register: (String | Symbol name, ?untyped factory) ?{ (**untyped) -> untyped } -> untyped
5
+ def self.unregister: (String | Symbol name) -> untyped
6
+ def self.build: (String | Symbol name, **untyped params) -> untyped
7
+ def self.registered_effects: () -> Hash[Symbol, untyped]
8
+
9
+ class EffectBase
10
+ def apply: (Core::SampleBuffer buffer) -> Core::SampleBuffer
11
+ def process: (Core::SampleBuffer buffer) -> Core::SampleBuffer
12
+ def flush: (?format: Core::Format?) -> Enumerator[Core::SampleBuffer, nil]?
13
+ def process_sample: (Numeric sample, channel: Integer, sample_rate: Integer) -> Numeric
14
+ def reset: () -> EffectBase
15
+ def build_runtime: () -> EffectBase
16
+ def tail_duration: () -> Float
17
+ def latency: () -> Float
18
+ def lookahead: () -> Float
19
+ end
20
+
21
+ class EffectChain
22
+ attr_reader effects: Array[untyped]
23
+
24
+ def initialize: (Array[untyped] effects) -> void
25
+ def apply: (Core::SampleBuffer buffer) -> Core::SampleBuffer
26
+ def process: (Core::SampleBuffer buffer) -> Core::SampleBuffer
27
+ def flush: (?format: Core::Format?) -> Enumerator[Core::SampleBuffer, nil]
28
+ def reset: () -> EffectChain
29
+ def build_runtime: () -> EffectChain
30
+ def tail_duration: () -> Float
31
+ def latency: () -> Float
32
+ def lookahead: () -> Float
33
+ end
34
+
35
+ class Delay < EffectBase
36
+ def self.beat: (Numeric bpm, ?division: Numeric) -> Float
37
+ def initialize: (?time: Numeric, ?feedback: Numeric, ?mix: Numeric, ?ping_pong: bool) -> void
38
+ end
39
+
40
+ class Reverb < EffectBase
41
+ def initialize: (?room_size: Numeric, ?damping: Numeric, ?mix: Numeric, ?pre_delay: Numeric, ?width: Numeric) -> void
42
+ end
43
+
44
+ class Chorus < EffectBase
45
+ def initialize: (?rate: Numeric, ?depth: Numeric, ?mix: Numeric, ?delay: Numeric, ?voices: Integer) -> void
46
+ end
47
+
48
+ class Distortion < EffectBase
49
+ def initialize: (?drive: Numeric, ?mix: Numeric, ?tone: Numeric) -> void
50
+ end
51
+
52
+ class Compressor < EffectBase
53
+ def initialize: (?threshold: Numeric, ?ratio: Numeric, ?attack: Numeric, ?release: Numeric, ?makeup_gain: Numeric, ?knee: Numeric, ?sidechain: Audio | Core::SampleBuffer?, ?sidechain_end: Symbol) -> void
54
+ end
55
+
56
+ class Limiter < EffectBase
57
+ def initialize: (?ceiling: Numeric, ?input_gain: Numeric, ?attack: Numeric, ?release: Numeric, ?lookahead: Numeric, ?oversampling: Integer) -> void
58
+ end
59
+
60
+ class SoftLimiter < EffectBase
61
+ def initialize: (?threshold: Numeric, ?ceiling: Numeric, ?drive: Numeric) -> void
62
+ end
63
+
64
+ class NoiseGate < EffectBase
65
+ def initialize: (?threshold: Numeric, ?floor: Numeric, ?attack: Numeric, ?hold: Numeric, ?release: Numeric, ?gain_attack: Numeric, ?gain_release: Numeric) -> void
66
+ end
67
+
68
+ class Tremolo < EffectBase
69
+ def initialize: (?rate: Numeric, ?depth: Numeric, ?mix: Numeric) -> void
70
+ end
71
+
72
+ class Vibrato < EffectBase
73
+ def initialize: (?rate: Numeric, ?depth: Numeric, ?mix: Numeric) -> void
74
+ end
75
+
76
+ class Flanger < EffectBase
77
+ def initialize: (?rate: Numeric, ?depth: Numeric, ?feedback: Numeric, ?mix: Numeric, ?delay: Numeric) -> void
78
+ end
79
+
80
+ class Phaser < EffectBase
81
+ def initialize: (?rate: Numeric, ?depth: Numeric, ?feedback: Numeric, ?mix: Numeric, ?stages: Integer) -> void
82
+ end
83
+
84
+ class Bitcrusher < EffectBase
85
+ def initialize: (?bits: Integer, ?sample_rate_reduction: Integer, ?mix: Numeric) -> void
86
+ end
87
+
88
+ class Expander < EffectBase
89
+ def initialize: (?threshold: Numeric, ?ratio: Numeric, ?floor: Numeric, ?attack: Numeric, ?hold: Numeric, ?release: Numeric, ?gain_attack: Numeric, ?gain_release: Numeric) -> void
90
+ end
91
+
92
+ class AutoPan < EffectBase
93
+ def initialize: (?rate: Numeric, ?depth: Numeric) -> void
94
+ end
95
+
96
+ class StereoWidener
97
+ def initialize: (?width: Numeric) -> void
98
+ def process: (Core::SampleBuffer buffer) -> Core::SampleBuffer
99
+ def apply: (Core::SampleBuffer buffer) -> Core::SampleBuffer
100
+ def reset: () -> StereoWidener
101
+ def build_runtime: () -> StereoWidener
102
+ def tail_duration: () -> Float
103
+ def latency: () -> Float
104
+ def lookahead: () -> Float
105
+ end
106
+
107
+ class EQ
108
+ def self.simple: (?low_gain: Numeric, ?mid_gain: Numeric, ?high_gain: Numeric) -> EQ
109
+ def initialize: (Array[DSP::Filter] filters) -> void
110
+ def apply: (Core::SampleBuffer buffer) -> Core::SampleBuffer
111
+ def process: (Core::SampleBuffer buffer) -> Core::SampleBuffer
112
+ def flush: (?format: Core::Format?) -> untyped
113
+ def reset: () -> EQ
114
+ def build_runtime: () -> EQ
115
+ def tail_duration: () -> Float
116
+ def latency: () -> Float
117
+ def lookahead: () -> Float
118
+ end
119
+
120
+ class MasteringChain < EffectChain
121
+ def initialize: (?highpass: Numeric, ?presence: Numeric, ?threshold: Numeric, ?ratio: Numeric, ?ceiling: Numeric) -> void
122
+ end
123
+
124
+ class PodcastChain < EffectChain
125
+ def initialize: (?gate_threshold: Numeric, ?highpass: Numeric, ?presence: Numeric, ?compression_threshold: Numeric, ?ceiling: Numeric) -> void
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,111 @@
1
+ Wavify:
2
+ signature_file: wavify.rbs
3
+ class_methods: [build, ms, seconds]
4
+ Wavify::Adapters:
5
+ signature_file: wavify.rbs
6
+ class_methods: [find, known, load]
7
+ Wavify::Audio:
8
+ signature_file: audio.rbs
9
+ class_methods: [info, metadata, mix, read, silence, stream, tone]
10
+ instance_methods: ['+', '==', append, apply, apply!, balance, bit_depth, buffer, channels, clipped?, concat, convert, crop, crossfade, dc_offset, dc_offsets, duration, each_frame, eql?, fade, fade_in, fade_in!, fade_out, fade_out!, format, frames, gain, gain!, hash, insert_silence, inspect, lufs, map_frames, map_samples, normalize, normalize!, overlay, pad_end, pad_start, pan, pan!, peak_amplitude, peak_dbfs, prepend, remove_dc_offset, repeat, repeat!, repeat_chunks, resample, reverse, reverse!, rms_amplitude, rms_dbfs, sample_frame_count, sample_peak_amplitude, sample_peak_dbfs, sample_rate, silent?, slice, split, stats, stereo_rotate, to_mono, to_stereo, trim, trim!, true_peak_amplitude, true_peak_dbfs, with_bit_depth, write, zero_crossing_rate]
11
+ Wavify::Core::Duration:
12
+ signature_file: core.rbs
13
+ class_methods: [from_samples, parse]
14
+ instance_methods: ['+', '-', '<=>', eql?, hash, hours, milliseconds, minutes, seconds, to_s, total_seconds]
15
+ Wavify::Core::Format:
16
+ signature_file: core.rbs
17
+ instance_methods: ['==', bit_depth, block_align, byte_rate, bytes_per_sample, channel_layout, channels, eql?, hash, mono?, sample_format, sample_rate, stereo?, valid_bits, with]
18
+ Wavify::Core::SampleBuffer:
19
+ signature_file: core.rbs
20
+ class_methods: [from_normalized_samples, from_pcm_samples]
21
+ instance_methods: ['+', '==', concat, convert, duration, each, each_frame_sample, eql?, format, frame_view, hash, length, packed?, packed_bytesize, reverse, sample_frame_count, samples, size, slice, storage, view]
22
+ Wavify::Core::Stream:
23
+ signature_file: stream.rbs
24
+ instance_methods: [chunk_size, drop_duration, dry_run, each, each_chunk, format, latency, lookahead, map_chunks, meter, pipe, pipeline, pipeline_steps, progress, take_duration, tee, to_audio, write_to]
25
+ Wavify::Codecs:
26
+ signature_file: codecs.rbs
27
+ class_methods: [available_formats, detect, register, supported_formats, unregister]
28
+ Wavify::Codecs::Registry:
29
+ signature_file: codecs.rbs
30
+ class_methods: [available_formats, detect, detect_for_read, detect_for_write, register, resolve, supported_formats, unregister]
31
+ Wavify::Codecs::Wav:
32
+ signature_file: codecs.rbs
33
+ class_methods: [can_read?, metadata, read, stream_read, stream_write, write]
34
+ Wavify::Codecs::Aiff:
35
+ signature_file: codecs.rbs
36
+ class_methods: [can_read?, metadata, read, stream_read, stream_write, write]
37
+ Wavify::Codecs::Flac:
38
+ signature_file: codecs.rbs
39
+ class_methods: [can_read?, metadata, read, stream_read, stream_write, write]
40
+ Wavify::Codecs::OggVorbis:
41
+ signature_file: codecs.rbs
42
+ class_methods: [available?, can_read?, metadata, read, runtime_diagnostics, stream_read, stream_write, write]
43
+ Wavify::Codecs::Raw:
44
+ signature_file: codecs.rbs
45
+ class_methods: [can_read?, metadata, read, stream_read, stream_write, write]
46
+ Wavify::DSP::Processor:
47
+ signature_file: dsp.rbs
48
+ class_methods: [build_runtime, duration, flush, process, render]
49
+ Wavify::DSP::Headroom:
50
+ signature_file: dsp.rbs
51
+ class_methods: [apply!]
52
+ Wavify::DSP::Automation:
53
+ signature_file: dsp.rbs
54
+ instance_methods: [apply, apply_gain, points, value_at]
55
+ Wavify::DSP::Envelope:
56
+ signature_file: dsp.rbs
57
+ instance_methods: [apply, attack, curve, decay, gain_at, hold, latency, lookahead, release, render_with_tail, sustain, tail_duration]
58
+ Wavify::DSP::Filter:
59
+ signature_file: dsp.rbs
60
+ class_methods: [bandpass, highpass, highshelf, lowpass, lowshelf, notch, peaking]
61
+ instance_methods: [apply, build_runtime, cutoff, flush, gain_db, latency, lookahead, process, process_sample, q, reset, tail_duration, type]
62
+ Wavify::DSP::LFO:
63
+ signature_file: dsp.rbs
64
+ instance_methods: [next_value, reset, value_at]
65
+ Wavify::DSP::LoudnessMeter:
66
+ signature_file: dsp.rbs
67
+ class_methods: [integrated, momentary, short_term, true_peak]
68
+ Wavify::DSP::Oscillator:
69
+ signature_file: dsp.rbs
70
+ instance_methods: [each_sample, generate, reset_phase]
71
+ Wavify::DSP::Effects:
72
+ signature_file: effects.rbs
73
+ class_methods: [build, register, registered_effects, unregister]
74
+ Wavify::DSP::Effects::EffectBase:
75
+ signature_file: effects.rbs
76
+ instance_methods: [apply, build_runtime, flush, latency, lookahead, process, process_sample, reset, tail_duration]
77
+ Wavify::DSP::Effects::EffectChain:
78
+ signature_file: effects.rbs
79
+ instance_methods: [apply, build_runtime, effects, flush, latency, lookahead, process, reset, tail_duration]
80
+ Wavify::DSP::Effects::Delay:
81
+ signature_file: effects.rbs
82
+ class_methods: [beat]
83
+ Wavify::DSP::Effects::EQ:
84
+ signature_file: effects.rbs
85
+ class_methods: [simple]
86
+ instance_methods: [apply, build_runtime, flush, latency, lookahead, process, reset, tail_duration]
87
+ Wavify::DSP::Effects::Limiter:
88
+ signature_file: effects.rbs
89
+ instance_methods: [apply, flush, latency, lookahead, process, process_sample, tail_duration]
90
+ Wavify::DSP::Effects::StereoWidener:
91
+ signature_file: effects.rbs
92
+ instance_methods: [apply, build_runtime, latency, lookahead, process, reset, tail_duration]
93
+ Wavify::Sequencer::Pattern:
94
+ signature_file: sequencer.rbs
95
+ instance_methods: ['[]', accented_indices, each, length, notation, resolution, size, steps, to_a, trigger_indices]
96
+ Wavify::Sequencer::NoteSequence:
97
+ signature_file: sequencer.rbs
98
+ instance_methods: ['[]', default_octave, each, events, length, midi_notes, notation, note_events, size]
99
+ Wavify::Sequencer::Track:
100
+ signature_file: sequencer.rbs
101
+ class_methods: [apply_chord_inversion, apply_chord_voicing, parse_chord_token, parse_chords, quantize_midi_note]
102
+ instance_methods: [chord_progression, chord_voicing, chords?, copy, default_octave, effects, effects?, envelope, event_sources?, gain_db, key_root, name, note_resolution, note_sequence, notes?, pan_position, parse_chords, pattern, pattern?, pattern_resolution, quantize_midi_note, scale, synth_options, waveform, with_chord_voicing, with_chords, with_effects, with_envelope, with_gain, with_key, with_notes, with_pan, with_pattern, with_synth]
103
+ Wavify::Sequencer::Engine:
104
+ signature_file: sequencer.rbs
105
+ instance_methods: [bar_duration_seconds, beats_per_bar, build_timeline, expand_pattern_step, format, render, seconds_per_beat, step_duration_at, step_duration_seconds, step_start_seconds, swing, tempo, timeline_for_track]
106
+ Wavify::DSL:
107
+ signature_file: dsl.rbs
108
+ class_methods: [build_definition, effect, validate]
109
+ Wavify::DSL::SongDefinition:
110
+ signature_file: dsl.rbs
111
+ instance_methods: [arrangement, arrangement?, beats_per_bar, default_bars, duration, engine, format, length, random_seed, render, sections, sequencer_tracks, swing, tempo, timeline, timeline_json, timeline_text, tracks, validate!, write, write_stems]
data/sig/sequencer.rbs ADDED
@@ -0,0 +1,126 @@
1
+ module Wavify
2
+ module Sequencer
3
+ class Pattern
4
+ class Step
5
+ attr_reader index: Integer
6
+ attr_reader trigger: bool
7
+ attr_reader accent: bool
8
+ attr_reader symbol: String
9
+ attr_reader velocity: Float
10
+ attr_reader probability: Float
11
+ attr_reader ratchet: Integer
12
+
13
+ def rest?: () -> bool
14
+ def trigger?: () -> bool
15
+ def accent?: () -> bool
16
+ end
17
+
18
+ include Enumerable[Step]
19
+
20
+ attr_reader resolution: Integer
21
+ attr_reader steps: Array[Step]
22
+ attr_reader notation: String
23
+
24
+ def initialize: (String notation, ?resolution: Integer) -> void
25
+ def each: () { (Step) -> void } -> Pattern
26
+ | () -> Enumerator[Step, Pattern]
27
+ def []: (Integer index) -> Step?
28
+ def length: () -> Integer
29
+ def size: () -> Integer
30
+ def trigger_indices: () -> Array[Integer]
31
+ def accented_indices: () -> Array[Integer]
32
+ def to_a: () -> Array[Step]
33
+ end
34
+
35
+ class NoteSequence
36
+ class Event
37
+ attr_reader index: Integer
38
+ attr_reader token: String
39
+ attr_reader midi_note: Integer?
40
+ attr_reader duration_denominator: Integer?
41
+ attr_reader duration_multiplier: Float
42
+ attr_reader tie: bool
43
+
44
+ def rest?: () -> bool
45
+ def tie?: () -> bool
46
+ end
47
+
48
+ include Enumerable[Event]
49
+
50
+ attr_reader default_octave: Integer
51
+ attr_reader events: Array[Event]
52
+ attr_reader notation: String
53
+
54
+ def initialize: (String notation, ?default_octave: Integer) -> void
55
+ def each: () { (Event) -> void } -> NoteSequence
56
+ | () -> Enumerator[Event, NoteSequence]
57
+ def []: (Integer index) -> Event?
58
+ def length: () -> Integer
59
+ def size: () -> Integer
60
+ def midi_notes: () -> Array[Integer?]
61
+ def note_events: () -> Array[Event]
62
+ end
63
+
64
+ class Track
65
+ attr_reader name: Symbol
66
+ attr_reader pattern: Pattern?
67
+ attr_reader note_sequence: NoteSequence?
68
+ attr_reader chord_progression: Array[untyped]?
69
+ attr_reader waveform: Symbol
70
+ attr_reader gain_db: Float
71
+ attr_reader pan_position: Float
72
+ attr_reader envelope: DSP::Envelope?
73
+ attr_reader effects: Array[untyped]
74
+ attr_reader pattern_resolution: Integer
75
+ attr_reader note_resolution: Integer
76
+ attr_reader default_octave: Integer
77
+ attr_reader key_root: Symbol?
78
+ attr_reader scale: Symbol?
79
+ attr_reader chord_voicing: Symbol
80
+ attr_reader synth_options: Hash[Symbol, untyped]
81
+
82
+ def self.parse_chords: (String | Array[untyped] chords, ?default_octave: Integer) -> Array[untyped]
83
+ def self.parse_chord_token: (String token, default_octave: Integer) -> untyped
84
+ def self.apply_chord_inversion: (Array[Integer] midi_notes, String bass_name, Integer root_midi, Integer default_octave) -> Array[Integer]
85
+ def self.apply_chord_voicing: (Array[Integer] midi_notes, Symbol voicing) -> Array[Integer]
86
+ def self.quantize_midi_note: (Integer midi_note, key: Symbol, scale: Symbol) -> Integer
87
+ def initialize: (String | Symbol name, **untyped options) -> void
88
+ def with_pattern: (String | Pattern pattern) -> Track
89
+ def with_notes: (String | NoteSequence notes, ?default_octave: Integer) -> Track
90
+ def with_chords: (String | Array[untyped] chords, ?default_octave: Integer) -> Track
91
+ def with_key: (String | Symbol key, ?scale: String | Symbol) -> Track
92
+ def with_chord_voicing: (String | Symbol voicing) -> Track
93
+ def with_synth: (String | Symbol waveform) -> Track
94
+ def with_gain: (Numeric db) -> Track
95
+ def with_pan: (Numeric position) -> Track
96
+ def with_envelope: (DSP::Envelope envelope) -> Track
97
+ def with_effects: (Array[untyped] effects) -> Track
98
+ def event_sources?: () -> bool
99
+ def pattern?: () -> bool
100
+ def notes?: () -> bool
101
+ def chords?: () -> bool
102
+ def effects?: () -> bool
103
+ def copy: (**untyped overrides) -> Track
104
+ def parse_chords: (String | Array[untyped] chords) -> Array[untyped]
105
+ def quantize_midi_note: (Integer midi_note) -> Integer
106
+ end
107
+
108
+ class Engine
109
+ attr_reader tempo: Float
110
+ attr_reader format: Core::Format
111
+ attr_reader beats_per_bar: Integer
112
+ attr_reader swing: Float
113
+
114
+ def initialize: (tempo: Numeric, ?format: Core::Format, ?beats_per_bar: Integer, ?swing: Numeric) -> void
115
+ def seconds_per_beat: () -> Float
116
+ def bar_duration_seconds: () -> Float
117
+ def step_duration_seconds: (Integer resolution) -> Float
118
+ def step_start_seconds: (Integer index, Integer resolution) -> Float
119
+ def step_duration_at: (Integer index, Integer resolution) -> Float
120
+ def expand_pattern_step: (Pattern::Step step, start_time: Numeric, duration: Numeric) -> Array[Hash[Symbol, untyped]]
121
+ def timeline_for_track: (Track track, bars: Integer, ?start_bar: Integer, ?start_time: Numeric?) -> Array[Hash[Symbol, untyped]]
122
+ def build_timeline: (tracks: Array[Track], ?arrangement: Array[Hash[Symbol, untyped]]?, ?default_bars: Integer) -> Array[Hash[Symbol, untyped]]
123
+ def render: (tracks: Array[Track], ?arrangement: Array[Hash[Symbol, untyped]]?, ?default_bars: Integer) -> Audio
124
+ end
125
+ end
126
+ end