beeps 0.3.11 → 0.3.13

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 447c9cdd326022c8ae82bb29c71e2b19feba8034ff75540a275a13897396632e
4
- data.tar.gz: f13e11cf3e2f0690c9cc87434b474bb717c58a2a737abbdad5377a7470fc2e86
3
+ metadata.gz: be0112d74491238712ca27ab7da557b8dbffac3075e2ac1eb13efa7ca91b4f18
4
+ data.tar.gz: 935312ec040f4dc78ab97135d8ff5035ee5f8712a5e1019bb720aead83e7bb90
5
5
  SHA512:
6
- metadata.gz: 1112849bbec8c92505651120c14aaf8bdefc4e4a97602f718fe3557e540789d7f63719357c73ab093b98e5d15c90320ce8bad5811a258c6c76bdfbe1345462cb
7
- data.tar.gz: 9e81ccd1d756546134ab2e4ba5ca11525924c7d29100a3735aeafb807af7bd99bb6c649fe3eced021306a7e48a06158f67182defbbcb5d2929d62d535f66dac4
6
+ metadata.gz: c83043583de20a32cd345f29cf01c3e56cebbbfc6dc960d9a2032e1b2d179c8fcf5013f67f0a775807e5084b00c8e7d8674f464da2e8383ce4bf5e46e8d9c804
7
+ data.tar.gz: aabb022c116a6c942b2b4c253e0caed24ed7f62320190b768dfd76d331da2acb6d28fb2f4ddd939db577b4bfce625af968baadba095de66a2a1fd2ba9667cc58
@@ -61,6 +61,57 @@ VALUE get_state(VALUE self)
61
61
  return value(THIS->state());
62
62
  }
63
63
 
64
+ static
65
+ VALUE set_position(VALUE self, VALUE position)
66
+ {
67
+ CHECK;
68
+
69
+ THIS->set_position(to<uint>(position));
70
+ return position;
71
+ }
72
+
73
+ static
74
+ VALUE get_position(VALUE self)
75
+ {
76
+ CHECK;
77
+
78
+ return value(THIS->position());
79
+ }
80
+
81
+ static
82
+ VALUE set_time(VALUE self, VALUE time)
83
+ {
84
+ CHECK;
85
+
86
+ THIS->set_time(to<float>(time));
87
+ return time;
88
+ }
89
+
90
+ static
91
+ VALUE get_time(VALUE self)
92
+ {
93
+ CHECK;
94
+
95
+ return value(THIS->time());
96
+ }
97
+
98
+ static
99
+ VALUE set_time_scale(VALUE self, VALUE scale)
100
+ {
101
+ CHECK;
102
+
103
+ THIS->set_time_scale(to<float>(scale));
104
+ return scale;
105
+ }
106
+
107
+ static
108
+ VALUE get_time_scale(VALUE self)
109
+ {
110
+ CHECK;
111
+
112
+ return value(THIS->time_scale());
113
+ }
114
+
64
115
  static
65
116
  VALUE set_gain(VALUE self, VALUE gain)
66
117
  {
@@ -116,6 +167,12 @@ Init_beeps_sound_player ()
116
167
  rb_define_method(cSoundPlayer, "rewind", RUBY_METHOD_FUNC(rewind), 0);
117
168
  rb_define_method(cSoundPlayer, "stop", RUBY_METHOD_FUNC(stop), 0);
118
169
  rb_define_method(cSoundPlayer, "state", RUBY_METHOD_FUNC(get_state), 0);
170
+ rb_define_method(cSoundPlayer, "position=", RUBY_METHOD_FUNC(set_position), 1);
171
+ rb_define_method(cSoundPlayer, "position", RUBY_METHOD_FUNC(get_position), 0);
172
+ rb_define_method(cSoundPlayer, "time=", RUBY_METHOD_FUNC(set_time), 1);
173
+ rb_define_method(cSoundPlayer, "time", RUBY_METHOD_FUNC(get_time), 0);
174
+ rb_define_method(cSoundPlayer, "time_scale=", RUBY_METHOD_FUNC(set_time_scale), 1);
175
+ rb_define_method(cSoundPlayer, "time_scale", RUBY_METHOD_FUNC(get_time_scale), 0);
119
176
  rb_define_method(cSoundPlayer, "gain=", RUBY_METHOD_FUNC(set_gain), 1);
120
177
  rb_define_method(cSoundPlayer, "gain", RUBY_METHOD_FUNC(get_gain), 0);
121
178
  rb_define_method(cSoundPlayer, "loop=", RUBY_METHOD_FUNC(set_loop), 1);
@@ -4,6 +4,9 @@ on:
4
4
  push:
5
5
  tags: ['v[0-9]*']
6
6
 
7
+ permissions:
8
+ contents: write
9
+
7
10
  jobs:
8
11
  release:
9
12
  runs-on: macos-latest
@@ -33,23 +36,9 @@ jobs:
33
36
  echo path=$(ruby -e 'print Dir.glob("*.gem").first') >> $GITHUB_OUTPUT
34
37
 
35
38
  - name: create github release
36
- id: release
37
- uses: actions/create-release@v1
38
39
  env:
39
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40
- with:
41
- tag_name: ${{ github.ref }}
42
- release_name: ${{ github.ref }}
43
-
44
- - name: upload to github release
45
- uses: actions/upload-release-asset@v1
46
- env:
47
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48
- with:
49
- upload_url: ${{ steps.release.outputs.upload_url }}
50
- asset_path: ./${{ steps.gem.outputs.path }}
51
- asset_name: ${{ steps.gem.outputs.path }}
52
- asset_content_type: application/zip
40
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41
+ run: ruby -I.github/workflows -rutils -e 'release(*ARGV)' ./${{ steps.gem.outputs.path }}
53
42
 
54
43
  - name: upload to rubygems
55
44
  env:
@@ -1,3 +1,9 @@
1
+ require 'shellwords'
2
+
3
+ ALL_REPO = 'xord/all'
4
+ ALL_DIR = '../all'
5
+ ALL_FETCH_DEPTH = 100
6
+
1
7
  RENAMES = {reflex: 'reflexion'}
2
8
 
3
9
  def sh(cmd)
@@ -5,7 +11,7 @@ def sh(cmd)
5
11
  system cmd
6
12
  end
7
13
 
8
- def setup_dependencies(build: true, only: nil)
14
+ def setup_dependencies(only: nil)
9
15
  gemspec_path = `git ls-files`.lines(chomp: true).find {|l| l =~ /\.gemspec$/}
10
16
  return unless gemspec_path
11
17
 
@@ -13,44 +19,109 @@ def setup_dependencies(build: true, only: nil)
13
19
  name = File.basename gemspec_path, '.gemspec'
14
20
 
15
21
  exts = File.readlines('Rakefile')
16
- .map {|l| l[%r|^\s*require\W+(\w+)/extension\W+$|, 1]}
22
+ .map {|l| l[%r|^\s*require\W+([\w\-\_]+)/extension\W+$|, 1]}
17
23
  .compact
18
24
  .reject {|ext| ext == name}
19
25
  exts = exts & [only].flatten.map(&:to_s) if only
26
+ return if exts.empty?
27
+
28
+ unless setup_dependencies_via_monorepo(exts)
29
+ setup_dependencies_via_each_repo_by_version(gemspec, exts)
30
+ end
31
+
32
+ exts.each {|ext| sh %( cd ../#{ext} && rake ext )}
33
+ end
34
+
35
+ def setup_dependencies_via_monorepo(exts)
36
+ return false unless checkout_monorepo
37
+ exts.each {|ext| sh %( ln -snf all/#{ext} ../#{ext} )}
38
+ true
39
+ end
40
+
41
+ def checkout_monorepo()
42
+ uuid = `git log -1 --format=%B`[/^\[\[([0-9a-fA-F-]+)\]\]$/, 1]
43
+ return false unless uuid
44
+
45
+ commit = setup_monorepo uuid
46
+ return false unless commit
47
+
48
+ Dir.chdir(ALL_DIR) {sh %( git checkout -q #{commit} )}
49
+ true
50
+ end
51
+
52
+ def setup_monorepo(uuid)
53
+ unless File.directory? ALL_DIR
54
+ url = "https://github.com/#{ALL_REPO}.git"
55
+ sh %( git clone --no-tags --depth #{ALL_FETCH_DEPTH} #{url} #{ALL_DIR} )
56
+ end
57
+ loop do
58
+ commit = find_monorepo_commit uuid
59
+ return commit if commit
60
+
61
+ deepened = Dir.chdir ALL_DIR do
62
+ before = `git rev-list --count HEAD`.to_i
63
+ sh %( git fetch --deepen #{ALL_FETCH_DEPTH} )
64
+ `git rev-list --count HEAD`.to_i > before
65
+ end
66
+ return nil unless deepened
67
+ end
68
+ end
69
+
70
+ def find_monorepo_commit(uuid)
71
+ Dir.chdir ALL_DIR do
72
+ out = `git log origin/HEAD -F --grep="[[#{uuid}]]" --format=%H -1`.strip
73
+ out.empty? ? nil : out
74
+ end
75
+ end
20
76
 
77
+ def setup_dependencies_via_each_repo_by_version(gemspec, exts)
21
78
  exts.each do |ext|
22
79
  gem = RENAMES[ext.to_sym].then {|s| s || ext}
23
- ver = gemspec[/add_dependency.*['"]#{gem}['"].*['"]\s*>=\s*([\d\.]+)\s*['"]/, 1]
80
+ ver = gemspec[/add_dependency.*['"]#{gem}['"].*['"]\s*~>\s*([\d\.]+)\s*['"]/, 1]
24
81
  opts = '-c advice.detachedHead=false --depth 1'
25
82
  clone = "git clone #{opts} https://github.com/xord/#{ext}.git ../#{ext}"
26
83
 
27
84
  # 'rake subtree:push' pushes all subrepos, so cloning by new tag
28
85
  # often fails before tagging each new tag
29
86
  sh %( #{clone} --branch v#{ver} || #{clone} )
30
- sh %( cd ../#{ext} && rake ext )
31
87
  end
32
88
  end
33
89
 
34
90
  def tag_versions()
35
- tags = `git tag`.lines chomp: true
36
- vers = `git log --oneline ./VERSION`
91
+ changes = changelogs
92
+ tags = `git tag`.lines chomp: true
93
+ vers = `git log --oneline ./VERSION`
37
94
  .lines(chomp: true)
38
95
  .map {|line| line.split.first[/^\w+$/]}
39
- .map {|hash| [`git cat-file -p #{hash}:./VERSION 2>/dev/null`[/[\d\.]+/], hash]}
40
- .select {|ver, hash| ver && hash}
96
+ .map {|sha| [`git cat-file -p #{sha}:./VERSION 2>/dev/null`[/[\d\.]+/], sha]}
97
+ .select {|ver, sha| ver && sha}
41
98
  .reverse
42
99
  .to_h
43
100
 
44
- changes = File.read('ChangeLog.md')
45
- .split(/^\s*##\s*\[\s*v([\d\.]+)\s*\].*$/)
46
- .slice(1..-1)
47
- .each_slice(2)
48
- .to_h
49
- .transform_values(&:strip!)
50
-
51
- vers.to_a.reverse.each do |ver, hash|
101
+ vers.to_a.reverse.each do |ver, sha|
52
102
  tag = "v#{ver}"
53
103
  break if tags.include?(tag)
54
- sh %( git tag -a -m \"#{changes[ver]&.gsub '"', '\\"'}\" #{tag} #{hash} )
104
+ sh %( git tag -a -m \"#{changes[tag]&.gsub '"', '\\"'}\" #{tag} #{sha} )
55
105
  end
56
106
  end
107
+
108
+ def release(*paths)
109
+ tag = ENV['GITHUB_REF']&.sub(%r|^refs/tags/|, '') || raise('GITHUB_REF tag not set')
110
+ notes = (changelogs[tag] || '').shellescape
111
+ paths = paths.flatten.join ' '
112
+
113
+ sh(%( gh release create #{tag} #{paths} --notes #{notes} )) ||
114
+ sh(%( gh release upload #{tag} #{paths} --clobber )) ||
115
+ raise('failed to upload to releases')
116
+ end
117
+
118
+ def changelogs()
119
+ File.read('ChangeLog.md')
120
+ .split(/^\s*##\s*\[\s*(v[\d\.]+)\s*\].*$/)
121
+ .slice(1..)
122
+ .each_slice(2)
123
+ .to_h
124
+ .transform_values(&:strip!)
125
+ rescue Errno::ENOENT
126
+ raise 'failed to get changelogs'
127
+ end
data/ChangeLog.md CHANGED
@@ -1,6 +1,26 @@
1
1
  # beeps ChangeLog
2
2
 
3
3
 
4
+ ## [v0.3.13] - 2026-05-17
5
+
6
+ - Rewrite README.md
7
+ - CI: Migrate release-gem.yml from actions/create-release to gh release create
8
+
9
+
10
+ ## [v0.3.12] - 2026-05-10
11
+
12
+ - Support WebAssembly
13
+ - Add adaptive stream buffering to prevent audio underruns
14
+ - Add position(), time(), time_scale() to SoundPlayer and seekable() to Processor
15
+ - Add constructors, clear(), and append() to Signals as public API
16
+ - Move set_buffering_seconds() from Filter to Processor
17
+ - Rename max_segment_size_for_process() to get_max_segment_size_for_process()
18
+ - Bump AudioFile from 1.1.1 to 1.1.4 to fix Windows CI
19
+ - Remove deprecated has_rdoc= from gemspecs
20
+
21
+ - Fix SignalSamples copying channel 0 data to all channels
22
+
23
+
4
24
  ## [v0.3.11] - 2026-04-17
5
25
 
6
26
  - Update dependencies
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Beeps - Plays beep sound
1
+ # Beeps - Audio synthesis and playback library
2
2
 
3
3
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/xord/beeps)
4
4
  ![License](https://img.shields.io/github/license/xord/beeps)
@@ -21,18 +21,37 @@ Thanks for your support! 🙌
21
21
 
22
22
  ## 🚀 About
23
23
 
24
- **Beeps** is a simple utility that plays a beep sound.
24
+ **Beeps** is an audio library for Ruby. You build a processor graph oscillators, file / mic input, filters, envelopes, effects — by wiring nodes together with the `>>` operator, then render the result to a `Sound` and play it back.
25
25
 
26
- It is designed to be lightweight and easy to use, making it perfect for adding audible notifications to your scripts or applications.
26
+ It is part of the `xord/*` family and underlies the audio support in [Reflex](https://github.com/xord/reflex), [Processing](https://github.com/xord/processing), [RubySketch](https://github.com/xord/rubysketch), and [Reight](https://github.com/xord/reight). Like the rest of the family, it is primarily developed for our own use, but it works as a standalone audio synthesis gem.
27
+
28
+ ## 📋 Requirements
29
+
30
+ - Ruby **3.0.0** or later
31
+ - A C++ compiler with C++20 support
32
+ - [Xot](https://rubygems.org/gems/xot) and [Rucy](https://rubygems.org/gems/rucy) (declared as runtime dependencies)
33
+ - Platform audio backend:
34
+ - **macOS** — OpenAL and AVFoundation (bundled with the OS)
35
+ - **Windows** — OpenAL (`MINGW_PACKAGE_PREFIX-openal`) and Media Foundation
36
+ - **Linux** — `libopenal-dev`
37
+
38
+ The following third-party DSP libraries are cloned from GitHub and statically linked while the native extension is being built, so you do not need to install them separately:
39
+
40
+ | Library | Role |
41
+ | ----------------------------------------------------------------------------- | ----------------------------------- |
42
+ | [STK](https://github.com/thestk/stk) | Core synthesis primitives |
43
+ | [AudioFile](https://github.com/adamstark/AudioFile) | WAV / AIFF file I/O |
44
+ | [r8brain-free-src](https://github.com/avaneev/r8brain-free-src) | High-quality sample-rate conversion |
45
+ | [signalsmith-stretch](https://github.com/Signalsmith-Audio/signalsmith-stretch) | Time stretching and pitch shifting |
27
46
 
28
47
  ## 📦 Installation
29
48
 
30
49
  Add this line to your Gemfile:
31
50
  ```ruby
32
- $ gem 'beeps'
51
+ gem 'beeps'
33
52
  ```
34
53
 
35
- Then, install gem:
54
+ Then install:
36
55
  ```bash
37
56
  $ bundle install
38
57
  ```
@@ -42,7 +61,131 @@ Or install it directly:
42
61
  $ gem install beeps
43
62
  ```
44
63
 
64
+ `require 'beeps'` automatically calls `Beeps.init!` and registers `Beeps.fin!` at exit. Set `$BEEPS_NOAUTOINIT = true` before requiring if you want to manage the lifetime yourself.
65
+
66
+ ## 📚 What's Included
67
+
68
+ ### Generators (signal sources)
69
+
70
+ | Class | Purpose |
71
+ | -------------------- | ------------------------------------------------------------------------ |
72
+ | `Beeps::Oscillator` | Sine / triangle / square / sawtooth / noise / sample-playback oscillator |
73
+ | `Beeps::Value` | Constant or linearly-interpolated control value over time |
74
+ | `Beeps::Sequencer` | Schedule processors at given offsets and durations |
75
+ | `Beeps::FileIn` | Stream audio from a WAV / AIFF / other supported file |
76
+ | `Beeps::MicIn` | Capture audio from a microphone |
77
+ | `Beeps::TextIn` | Synthesize speech from text |
78
+
79
+ ### Filters (processors that take an input)
80
+
81
+ | Class | Purpose |
82
+ | -------------------- | ----------------------------------------------------------------------- |
83
+ | `Beeps::Gain` | Multiply the signal by a gain coefficient |
84
+ | `Beeps::Mixer` | Sum multiple inputs |
85
+ | `Beeps::Envelope` | Attack / Decay / Sustain / Release envelope with `note_on` / `note_off` |
86
+ | `Beeps::LowPass` | Low-pass filter with cutoff frequency |
87
+ | `Beeps::HighPass` | High-pass filter with cutoff frequency |
88
+ | `Beeps::Reverb` | Reverb with `mix`, `room_size`, `damping` controls |
89
+ | `Beeps::TimeStretch` | Change duration without affecting pitch |
90
+ | `Beeps::PitchShift` | Change pitch without affecting duration |
91
+ | `Beeps::Analyser` | FFT analyser — exposes time-domain and spectrum readings |
92
+
93
+ ### Playback
94
+
95
+ | Class | Purpose |
96
+ | -------------------- | --------------------------------------------------------------------------- |
97
+ | `Beeps::Sound` | A finite, renderable audio asset (created from a processor or `load_sound`) |
98
+ | `Beeps::SoundPlayer` | Returned by `Sound#play`; supports `pause`, `stop`, `position`, `loop`, ... |
99
+
100
+ ## 💡 Usage
101
+
102
+ ### Play a 440 Hz sine tone for one second
103
+
104
+ ```ruby
105
+ require 'beeps'
106
+
107
+ osc = Beeps::Oscillator.new(:sine, frequency: 440)
108
+ sound = Beeps::Sound.new(osc, 1)
109
+ player = sound.play
110
+
111
+ sleep 1 # keep the script alive while the sound plays
112
+ ```
113
+
114
+ ### Build a processor chain with `>>`
115
+
116
+ ```ruby
117
+ require 'beeps'
118
+
119
+ # oscillator -> half-volume -> low-pass at 800 Hz -> reverb
120
+ chain =
121
+ Beeps::Oscillator.new(:sawtooth, frequency: 220) >>
122
+ Beeps::Gain.new(0.5) >>
123
+ Beeps::LowPass.new(cutoff: 800) >>
124
+ Beeps::Reverb.new(mix: 0.3, room_size: 0.7)
125
+
126
+ Beeps::Sound.new(chain, 2).play
127
+ sleep 2
128
+ ```
129
+
130
+ `a >> b` calls `b.add_input(a)` and returns `b`, so the right-most node is the head of the chain you pass to `Sound.new`.
131
+
132
+ ### ADSR envelope
133
+
134
+ ```ruby
135
+ require 'beeps'
136
+
137
+ osc = Beeps::Oscillator.new(:sine, frequency: 440)
138
+ env = Beeps::Envelope.new(0.05, 0.1, 0.7, 0.3, input: osc)
139
+ env.note_on
140
+ env.note_off 0.5 # release after 0.5 s
141
+
142
+ Beeps::Sound.new(env, 1).play
143
+ sleep 1
144
+ ```
145
+
146
+ ### Play and save a wave file
147
+
148
+ ```ruby
149
+ require 'beeps'
150
+
151
+ # play an existing file
152
+ player = Beeps.load_sound('drum.wav').play
153
+
154
+ # render a chain and save it to disk
155
+ sound = Beeps::Sound.new(Beeps::Oscillator.new(:square, frequency: 880), 0.5)
156
+ sound.save 'square.wav'
157
+ ```
158
+
159
+ ### Capture from the microphone and analyse
160
+
161
+ ```ruby
162
+ require 'beeps'
163
+
164
+ mic = Beeps::MicIn.new(1) # 1 channel
165
+ analyser = Beeps::Analyser.new(1024, mic) # 1024-point FFT
166
+ mic.start
167
+
168
+ loop do
169
+ sleep 0.1
170
+ puts analyser.spectrum.first(8).map {|v| v.round 3 }.inspect
171
+ end
172
+ ```
173
+
174
+ ## 🛠️ Development
175
+
176
+ ```bash
177
+ $ rake lib # build the native C++ library (libbeeps)
178
+ $ rake ext # build the Ruby C extension
179
+ $ rake test # run the test suite
180
+ $ rake doc # generate RDoc from C++ sources
181
+ $ rake # default: builds the extension
182
+ ```
183
+
184
+ In the [`xord/all`](https://github.com/xord/all) monorepo you can scope by module, e.g. `rake beeps test`.
185
+
45
186
  ## 📜 License
46
187
 
47
188
  **Beeps** is licensed under the MIT License.
48
189
  See the [LICENSE](./LICENSE) file for details.
190
+
191
+ The third-party DSP libraries listed above retain their own licenses.
data/Rakefile CHANGED
@@ -25,7 +25,7 @@ use_external_library 'https://github.com/thestk/stk',
25
25
  excludes: %w[stk/src/include Tcp Udp Socket Thread Mutex InetWv /Rt]
26
26
 
27
27
  use_external_library 'https://github.com/adamstark/AudioFile',
28
- tag: '1.1.1',
28
+ tag: '1.1.4',
29
29
  srcdirs: 'NOSRC',
30
30
  excludes: %w[examples/ tests/]
31
31
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.11
1
+ 0.3.13
data/beeps.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  end
11
11
 
12
12
  ext = Beeps::Extension
13
- name = ext.name.downcase
13
+ name = ext.name true
14
14
  rdocs = glob.call *%w[README .doc/ext/**/*.cpp]
15
15
 
16
16
  s.name = name
@@ -25,14 +25,13 @@ Gem::Specification.new do |s|
25
25
  s.platform = Gem::Platform::RUBY
26
26
  s.required_ruby_version = '>= 3.0.0'
27
27
 
28
- s.add_dependency 'xot', '~> 0.3.11'
29
- s.add_dependency 'rucy', '~> 0.3.11'
28
+ s.add_dependency 'xot', '~> 0.3.13'
29
+ s.add_dependency 'rucy', '~> 0.3.13'
30
30
 
31
31
  s.files = `git ls-files`.split $/
32
32
  s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
33
33
  s.test_files = s.files.grep %r{^(test|spec|features)/}
34
34
  s.extra_rdoc_files = rdocs.to_a
35
- s.has_rdoc = true
36
35
 
37
36
  s.metadata['msys2_mingw_dependencies'] = 'openal'
38
37
 
data/ext/beeps/extconf.rb CHANGED
@@ -25,7 +25,7 @@ Xot::ExtConf.new Xot, Rucy, Beeps do
25
25
  libs << 'openal'
26
26
  end
27
27
 
28
- $LDFLAGS << ' -Wl,--out-implib=beeps_ext.dll.a' if mingw? || cygwin?
28
+ $LDFLAGS << ' -Wl,--out-implib=libbeeps.dll.a' if mingw? || cygwin?
29
29
  end
30
30
 
31
31
  create_makefile 'beeps_ext'
@@ -67,6 +67,63 @@ RUCY_DEF0(get_state)
67
67
  }
68
68
  RUCY_END
69
69
 
70
+ static
71
+ RUCY_DEF1(set_position, position)
72
+ {
73
+ CHECK;
74
+
75
+ THIS->set_position(to<uint>(position));
76
+ return position;
77
+ }
78
+ RUCY_END
79
+
80
+ static
81
+ RUCY_DEF0(get_position)
82
+ {
83
+ CHECK;
84
+
85
+ return value(THIS->position());
86
+ }
87
+ RUCY_END
88
+
89
+ static
90
+ RUCY_DEF1(set_time, time)
91
+ {
92
+ CHECK;
93
+
94
+ THIS->set_time(to<float>(time));
95
+ return time;
96
+ }
97
+ RUCY_END
98
+
99
+ static
100
+ RUCY_DEF0(get_time)
101
+ {
102
+ CHECK;
103
+
104
+ return value(THIS->time());
105
+ }
106
+ RUCY_END
107
+
108
+ static
109
+ RUCY_DEF1(set_time_scale, scale)
110
+ {
111
+ CHECK;
112
+
113
+ THIS->set_time_scale(to<float>(scale));
114
+ return scale;
115
+ }
116
+ RUCY_END
117
+
118
+ static
119
+ RUCY_DEF0(get_time_scale)
120
+ {
121
+ CHECK;
122
+
123
+ return value(THIS->time_scale());
124
+ }
125
+ RUCY_END
126
+
70
127
  static
71
128
  RUCY_DEF1(set_gain, gain)
72
129
  {
@@ -126,7 +183,13 @@ Init_beeps_sound_player ()
126
183
  cSoundPlayer.define_method("pause", pause);
127
184
  cSoundPlayer.define_method("rewind", rewind);
128
185
  cSoundPlayer.define_method("stop", stop);
129
- cSoundPlayer.define_method("state", get_state);
186
+ cSoundPlayer.define_method("state", get_state);
187
+ cSoundPlayer.define_method("position=", set_position);
188
+ cSoundPlayer.define_method("position", get_position);
189
+ cSoundPlayer.define_method("time=", set_time);
190
+ cSoundPlayer.define_method("time", get_time);
191
+ cSoundPlayer.define_method("time_scale=", set_time_scale);
192
+ cSoundPlayer.define_method("time_scale", get_time_scale);
130
193
  cSoundPlayer.define_method("gain=", set_gain);
131
194
  cSoundPlayer.define_method("gain", get_gain);
132
195
  cSoundPlayer.define_method("loop=", set_loop);
data/include/beeps/defs.h CHANGED
@@ -23,6 +23,8 @@ namespace Beeps
23
23
 
24
24
  using Xot::String;
25
25
 
26
+ using Xot::StringList;
27
+
26
28
 
27
29
  typedef double Sample;
28
30
 
@@ -27,6 +27,8 @@ namespace Beeps
27
27
 
28
28
  virtual float gain () const;
29
29
 
30
+ bool seekable () const override;
31
+
30
32
  struct Data;
31
33
 
32
34
  Xot::PImpl<Data> self;
@@ -70,6 +72,8 @@ namespace Beeps
70
72
 
71
73
  virtual operator bool () const override;
72
74
 
75
+ bool seekable () const override;
76
+
73
77
  struct Data;
74
78
 
75
79
  Xot::PImpl<Data> self;
@@ -303,6 +307,8 @@ namespace Beeps
303
307
 
304
308
  virtual operator bool () const override;
305
309
 
310
+ bool seekable () const override;
311
+
306
312
  struct Data;
307
313
 
308
314
  Xot::PImpl<Data> self;
@@ -63,6 +63,8 @@ namespace Beeps
63
63
 
64
64
  virtual const_iterator end () const;
65
65
 
66
+ bool seekable () const override;
67
+
66
68
  struct Data;
67
69
 
68
70
  Xot::PImpl<Data> self;
@@ -72,7 +74,7 @@ namespace Beeps
72
74
  virtual void generate (
73
75
  Context* context, Signals* signals, uint* offset) override;
74
76
 
75
- virtual int max_segment_size_for_process (
77
+ virtual int get_max_segment_size_for_process (
76
78
  double sample_rate, uint nsamples) const override;
77
79
 
78
80
  };// Value
@@ -140,6 +142,8 @@ namespace Beeps
140
142
 
141
143
  virtual operator bool () const override;
142
144
 
145
+ bool seekable () const override;
146
+
143
147
  struct Data;
144
148
 
145
149
  Xot::PImpl<Data> self;
@@ -149,7 +153,7 @@ namespace Beeps
149
153
  virtual void generate (
150
154
  Context* context, Signals* signals, uint* offset) override;
151
155
 
152
- virtual int max_segment_size_for_process (
156
+ virtual int get_max_segment_size_for_process (
153
157
  double sample_rate, uint nsamples) const override;
154
158
 
155
159
  };// Oscillator
@@ -240,6 +244,8 @@ namespace Beeps
240
244
 
241
245
  virtual operator bool () const override;
242
246
 
247
+ bool seekable () const override;
248
+
243
249
  struct Data;
244
250
 
245
251
  Xot::PImpl<Data> self;