beeps 0.3.8 → 0.3.9

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: ffb1fb953e77f054413c28ff5a7758ec0255d4d6f6cd421a83e7efcebccf12c6
4
- data.tar.gz: e3c7c7aa33a20f78b19513466aef28406587df39d0ae81c3d62b8cee48f4bb9f
3
+ metadata.gz: f8f411f90d8d0ed9b8672d08b5039799ac6f9178835dac7dc24acccd8c93cc0e
4
+ data.tar.gz: e7ba8574e7962d3b9de62238f4f42cb897dd0edbecce3d298928acc07f2fe161
5
5
  SHA512:
6
- metadata.gz: d8a51e36b23f7ac02078c95bfe8a5b22d894ed53a11f88dd12c078d3649350e236e4655ef0edce4acf3d41d3d719145a42ef5b5a6f0db5606a593294d8001932
7
- data.tar.gz: aa2feca97761804c84df4c75079330913b6025218061e3e3df3745a3cd3edca8a6ff1647159953a49980e41b324f3a99b6fc84ffc0819ea7d37d57a779305573
6
+ metadata.gz: 4874e8fba3a4e1962853b9ce05454c703065b89c77fa89a286aebbf76bc775c43fb9f6e47c326b9725d005d8f2c680a13ee6981d686836a50e19900ab4c9436e
7
+ data.tar.gz: f84446b0b666cc6852fc95845e303668c844012208210b647bc71611539972d0d24339113ade1b1903d0df5f2cbc9264ff2d339dfdcf4bccb9ee6e501f6eb163
@@ -13,6 +13,7 @@ void Init_beeps_oscillator ();
13
13
  void Init_beeps_sequencer ();
14
14
  void Init_beeps_file_in ();
15
15
  void Init_beeps_mic_in ();
16
+ void Init_beeps_text_in ();
16
17
 
17
18
  void Init_beeps_gain ();
18
19
  void Init_beeps_mixer ();
@@ -48,6 +49,7 @@ extern "C" void
48
49
  Init_beeps_sequencer();
49
50
  Init_beeps_file_in();
50
51
  Init_beeps_mic_in();
52
+ Init_beeps_text_in();
51
53
 
52
54
  Init_beeps_gain();
53
55
  Init_beeps_mixer();
@@ -106,7 +106,7 @@ VALUE save(VALUE self, VALUE path)
106
106
  static
107
107
  VALUE load(VALUE self, VALUE path)
108
108
  {
109
- return value(Beeps::load_sound(to<const char*>(path)));
109
+ return value(Beeps::load_sound(path.c_str()));
110
110
  }
111
111
 
112
112
 
@@ -0,0 +1,63 @@
1
+ #include "beeps/ruby/generator.h"
2
+
3
+
4
+ #include "beeps/ruby/processor.h"
5
+ #include "defs.h"
6
+
7
+
8
+ RUCY_DEFINE_WRAPPER_VALUE_FROM_TO(BEEPS_EXPORT, Beeps::TextIn)
9
+
10
+ #define THIS to<Beeps::TextIn*>(self)
11
+
12
+ #define CHECK RUCY_CHECK_OBJ(Beeps::TextIn, self)
13
+
14
+
15
+ static
16
+ VALUE alloc(VALUE klass)
17
+ {
18
+ return value(new Beeps::RubyProcessor<Beeps::TextIn>, klass);
19
+ }
20
+
21
+ static
22
+ VALUE synthesize(VALUE self, VALUE text)
23
+ {
24
+ CHECK;
25
+
26
+ THIS->synthesize(text.c_str());
27
+ }
28
+
29
+ static
30
+ VALUE get_sample_rate(VALUE self)
31
+ {
32
+ CHECK;
33
+
34
+ return value(THIS->sample_rate());
35
+ }
36
+
37
+
38
+ static Class cTextIn;
39
+
40
+ void
41
+ Init_beeps_text_in ()
42
+ {
43
+ Module mBeeps = rb_define_module("Beeps");
44
+
45
+ cTextIn = mBeeps.define_class("TextIn", Beeps::processor_class());
46
+ rb_define_alloc_func(cTextIn, alloc);
47
+ rb_define_method(cTextIn, "synthesize", RUBY_METHOD_FUNC(synthesize), 1);
48
+ rb_define_method(cTextIn, "sample_rate", RUBY_METHOD_FUNC(get_sample_rate), 0);
49
+ }
50
+
51
+
52
+ namespace Beeps
53
+ {
54
+
55
+
56
+ Class
57
+ text_in_class ()
58
+ {
59
+ return cTextIn;
60
+ }
61
+
62
+
63
+ }// Beeps
data/ChangeLog.md CHANGED
@@ -1,6 +1,15 @@
1
1
  # beeps ChangeLog
2
2
 
3
3
 
4
+ ## [v0.3.9] - 2025-07-06
5
+
6
+ - Add TextIn class
7
+ - Add Signals::full()
8
+ - Add Siangls_shift() and Signals_set_capacity()
9
+ - Add Signals_create() and Signals_append() for AVAudioPCMBuffer
10
+ - Add deepwiki badge
11
+
12
+
4
13
  ## [v0.3.8] - 2025-05-22
5
14
 
6
15
  - The oscillator resets the frequency to 0.001 if it is set to 0
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Beeps - Plays beep sound
2
2
 
3
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/xord/beeps)
3
4
  ![License](https://img.shields.io/github/license/xord/beeps)
4
5
  ![Build Status](https://github.com/xord/beeps/actions/workflows/test.yml/badge.svg)
5
6
  ![Gem Version](https://badge.fury.io/rb/beeps.svg)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.8
1
+ 0.3.9
data/beeps.gemspec CHANGED
@@ -25,8 +25,8 @@ 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.8', '>= 0.3.8'
29
- s.add_dependency 'rucy', '~> 0.3.8', '>= 0.3.8'
28
+ s.add_dependency 'xot', '~> 0.3.9', '>= 0.3.9'
29
+ s.add_dependency 'rucy', '~> 0.3.9', '>= 0.3.9'
30
30
 
31
31
  s.files = `git ls-files`.split $/
32
32
  s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
data/ext/beeps/native.cpp CHANGED
@@ -13,6 +13,7 @@ void Init_beeps_oscillator ();
13
13
  void Init_beeps_sequencer ();
14
14
  void Init_beeps_file_in ();
15
15
  void Init_beeps_mic_in ();
16
+ void Init_beeps_text_in ();
16
17
 
17
18
  void Init_beeps_gain ();
18
19
  void Init_beeps_mixer ();
@@ -48,6 +49,7 @@ extern "C" void
48
49
  Init_beeps_sequencer();
49
50
  Init_beeps_file_in();
50
51
  Init_beeps_mic_in();
52
+ Init_beeps_text_in();
51
53
 
52
54
  Init_beeps_gain();
53
55
  Init_beeps_mixer();
data/ext/beeps/sound.cpp CHANGED
@@ -117,7 +117,7 @@ RUCY_END
117
117
  static
118
118
  RUCY_DEF1(load, path)
119
119
  {
120
- return value(Beeps::load_sound(to<const char*>(path)));
120
+ return value(Beeps::load_sound(path.c_str()));
121
121
  }
122
122
  RUCY_END
123
123
 
@@ -0,0 +1,66 @@
1
+ #include "beeps/ruby/generator.h"
2
+
3
+
4
+ #include "beeps/ruby/processor.h"
5
+ #include "defs.h"
6
+
7
+
8
+ RUCY_DEFINE_WRAPPER_VALUE_FROM_TO(BEEPS_EXPORT, Beeps::TextIn)
9
+
10
+ #define THIS to<Beeps::TextIn*>(self)
11
+
12
+ #define CHECK RUCY_CHECK_OBJ(Beeps::TextIn, self)
13
+
14
+
15
+ static
16
+ RUCY_DEF_ALLOC(alloc, klass)
17
+ {
18
+ return value(new Beeps::RubyProcessor<Beeps::TextIn>, klass);
19
+ }
20
+ RUCY_END
21
+
22
+ static
23
+ RUCY_DEF1(synthesize, text)
24
+ {
25
+ CHECK;
26
+
27
+ THIS->synthesize(text.c_str());
28
+ }
29
+ RUCY_END
30
+
31
+ static
32
+ RUCY_DEF0(get_sample_rate)
33
+ {
34
+ CHECK;
35
+
36
+ return value(THIS->sample_rate());
37
+ }
38
+ RUCY_END
39
+
40
+
41
+ static Class cTextIn;
42
+
43
+ void
44
+ Init_beeps_text_in ()
45
+ {
46
+ Module mBeeps = define_module("Beeps");
47
+
48
+ cTextIn = mBeeps.define_class("TextIn", Beeps::processor_class());
49
+ cTextIn.define_alloc_func(alloc);
50
+ cTextIn.define_method("synthesize", synthesize);
51
+ cTextIn.define_method("sample_rate", get_sample_rate);
52
+ }
53
+
54
+
55
+ namespace Beeps
56
+ {
57
+
58
+
59
+ Class
60
+ text_in_class ()
61
+ {
62
+ return cTextIn;
63
+ }
64
+
65
+
66
+ }// Beeps
@@ -193,6 +193,35 @@ namespace Beeps
193
193
  };// MicIn
194
194
 
195
195
 
196
+ class TextIn : public Generator
197
+ {
198
+
199
+ typedef Generator Super;
200
+
201
+ public:
202
+
203
+ TextIn (const char* text = NULL, double sample_rate = 0);
204
+
205
+ virtual ~TextIn ();
206
+
207
+ virtual void synthesize (const char* text);
208
+
209
+ virtual double sample_rate () const;
210
+
211
+ virtual operator bool () const override;
212
+
213
+ struct Data;
214
+
215
+ Xot::PImpl<Data> self;
216
+
217
+ protected:
218
+
219
+ virtual void generate (
220
+ Context* context, Signals* signals, uint* offset) override;
221
+
222
+ };// TextIn
223
+
224
+
196
225
  }// Beeps
197
226
 
198
227
 
@@ -17,6 +17,8 @@ RUCY_DECLARE_WRAPPER_VALUE_FROM_TO(BEEPS_EXPORT, Beeps::FileIn)
17
17
 
18
18
  RUCY_DECLARE_WRAPPER_VALUE_FROM_TO(BEEPS_EXPORT, Beeps::MicIn)
19
19
 
20
+ RUCY_DECLARE_WRAPPER_VALUE_FROM_TO(BEEPS_EXPORT, Beeps::TextIn)
21
+
20
22
 
21
23
  namespace Beeps
22
24
  {
@@ -34,6 +36,9 @@ namespace Beeps
34
36
  BEEPS_EXPORT Rucy::Class mic_in_class ();
35
37
  // class Beeps::MicIn
36
38
 
39
+ BEEPS_EXPORT Rucy::Class text_in_class ();
40
+ // class Beeps::TextIn
41
+
37
42
 
38
43
  }// Beeps
39
44
 
@@ -66,6 +71,12 @@ namespace Rucy
66
71
  return Beeps::mic_in_class();
67
72
  }
68
73
 
74
+ template <> inline Class
75
+ get_ruby_class<Beeps::TextIn> ()
76
+ {
77
+ return Beeps::text_in_class();
78
+ }
79
+
69
80
 
70
81
  }// Rucy
71
82
 
@@ -33,6 +33,8 @@ namespace Beeps
33
33
 
34
34
  bool empty () const;
35
35
 
36
+ bool full() const;
37
+
36
38
  const Sample* samples () const;
37
39
 
38
40
  operator bool () const;
@@ -94,6 +94,16 @@ module Beeps
94
94
  end# FileIn
95
95
 
96
96
 
97
+ class TextIn
98
+
99
+ def initialize(text = nil, **kwargs, &block)
100
+ super(**kwargs, &block)
101
+ synthesize text if text
102
+ end
103
+
104
+ end# TextIn
105
+
106
+
97
107
  class Gain
98
108
 
99
109
  def initialize(gain = 1, **kwargs, &block)
data/src/osx/signals.h ADDED
@@ -0,0 +1,23 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __BEEPS_SRC_OSX_SIGNALS_H__
4
+ #define __BEEPS_SRC_OSX_SIGNALS_H__
5
+
6
+
7
+ #import <AVFoundation/AVFoundation.h>
8
+ #include "../signals.h"
9
+
10
+
11
+ namespace Beeps
12
+ {
13
+
14
+
15
+ Signals Signals_create (AVAudioPCMBuffer* buffer, uint capacity = 0);
16
+
17
+ void Signals_append (Signals* to, AVAudioPCMBuffer* buffer);
18
+
19
+
20
+ }// Beeps
21
+
22
+
23
+ #endif//EOH
data/src/osx/signals.mm CHANGED
@@ -1,8 +1,7 @@
1
1
  // -*- c++ -*-
2
- #include "../signals.h"
2
+ #include "signals.h"
3
3
 
4
4
 
5
- #import <AVFoundation/AVFoundation.h>
6
5
  #include "beeps/exception.h"
7
6
 
8
7
 
@@ -24,6 +23,70 @@ namespace Beeps
24
23
  }
25
24
 
26
25
 
26
+ Signals
27
+ Signals_create (AVAudioPCMBuffer* buffer, uint capacity)
28
+ {
29
+ if (!buffer)
30
+ argument_error(__FILE__, __LINE__);
31
+
32
+ uint nchannels = buffer.format.channelCount;
33
+ if (nchannels <= 0)
34
+ beeps_error(__FILE__, __LINE__, "invalid nchannels %d", nchannels);
35
+
36
+ uint nsamples = buffer.frameLength;
37
+ if (nsamples <= 0)
38
+ beeps_error(__FILE__, __LINE__, "invalid buffer length %d", nsamples);
39
+
40
+ const float* const* channels = buffer.floatChannelData;
41
+ if (!channels)
42
+ beeps_error(__FILE__, __LINE__, "failed to get channel data");
43
+
44
+ return Signals_create(
45
+ channels, nsamples, nchannels, (uint) buffer.format.sampleRate, capacity);
46
+ }
47
+
48
+ static uint
49
+ get_next_capacity (const Signals& signals, uint nsamples)
50
+ {
51
+ uint cap = signals.capacity();
52
+ while (cap < nsamples) cap *= 2;
53
+ return cap;
54
+ }
55
+
56
+ void
57
+ Signals_append (Signals* to, AVAudioPCMBuffer* buffer)
58
+ {
59
+ if (!buffer)
60
+ argument_error(__FILE__, __LINE__);
61
+
62
+ uint nchannels = buffer.format.channelCount;
63
+ if (nchannels <= 0)
64
+ beeps_error(__FILE__, __LINE__, "invalid nchannels %d", nchannels);
65
+ if (nchannels != to->nchannels())
66
+ beeps_error(__FILE__, __LINE__, "nchannels does not match", nchannels);
67
+
68
+ uint nsamples = buffer.frameLength;
69
+ if (nsamples <= 0)
70
+ beeps_error(__FILE__, __LINE__, "invalid buffer length %d", nsamples);
71
+
72
+ const float* const* channels = buffer.floatChannelData;
73
+ if (!channels)
74
+ beeps_error(__FILE__, __LINE__, "failed to get channel data");
75
+
76
+ uint new_nsamples = to->nsamples() + nsamples;
77
+ if (new_nsamples > to->capacity())
78
+ Signals_set_capacity(to, get_next_capacity(*to, new_nsamples));
79
+
80
+ for (uint channel = 0; channel < nchannels; ++channel)
81
+ {
82
+ Sample* p = Signals_at(to, to->nsamples(), channel);
83
+ for (uint i = 0; i < nsamples; ++i, p += nchannels)
84
+ *p = channels[channel][i];
85
+ }
86
+
87
+ Signals_set_nsamples(to, new_nsamples);
88
+ }
89
+
27
90
  static AVAudioPCMBuffer*
28
91
  load_buffer (const char* path)
29
92
  {
@@ -64,19 +127,7 @@ namespace Beeps
64
127
  AVAudioPCMBuffer* buffer = load_buffer(path);
65
128
  if (!buffer) return Signals();
66
129
 
67
- uint nchannels = buffer.format.channelCount;
68
- if (nchannels <= 0)
69
- beeps_error(__FILE__, __LINE__, "invalid nchannels %d", nchannels);
70
-
71
- uint len = buffer.frameLength;
72
- if (len <= 0)
73
- beeps_error(__FILE__, __LINE__, "invalid buffer length %d", len);
74
-
75
- const float* const* data = buffer.floatChannelData;
76
- if (!data)
77
- beeps_error(__FILE__, __LINE__, "failed to get channel data");
78
-
79
- return Signals_create(data, len, nchannels, (uint) buffer.format.sampleRate);
130
+ return Signals_create(buffer);
80
131
  }
81
132
 
82
133
 
@@ -0,0 +1,133 @@
1
+ // -*- c++ -*-
2
+ #include "beeps/generator.h"
3
+
4
+
5
+ #include <deque>
6
+ #import <Foundation/Foundation.h>
7
+ #include "beeps/exception.h"
8
+ #include "beeps/debug.h"
9
+ #include "signals.h"
10
+
11
+
12
+ namespace Beeps
13
+ {
14
+
15
+
16
+ typedef Xot::Ref<TextIn> TextInRef;
17
+
18
+
19
+ struct TextIn::Data
20
+ {
21
+
22
+ double sample_rate = 0;
23
+
24
+ bool finished = false;
25
+
26
+ Signals signals;
27
+
28
+ };// TextIn::Data
29
+
30
+
31
+ TextIn::TextIn (const char* text, double sample_rate)
32
+ {
33
+ if (sample_rate == 0)
34
+ sample_rate = Beeps::sample_rate();
35
+ if (sample_rate <= 0)
36
+ argument_error(__FILE__, __LINE__);
37
+
38
+ self->sample_rate = sample_rate;
39
+
40
+ if (text) synthesize(text);
41
+ }
42
+
43
+ TextIn::~TextIn ()
44
+ {
45
+ }
46
+
47
+ void
48
+ TextIn::synthesize (const char* text)
49
+ {
50
+ if (@available(macOS 10.15, *))
51
+ {
52
+ TextInRef pthis = this;
53
+ AVSpeechSynthesizer* synth = [[AVSpeechSynthesizer alloc] init];
54
+
55
+ NSString* str = [NSString stringWithUTF8String: text];
56
+ auto* utt = [[[AVSpeechUtterance alloc] initWithString: str] autorelease];
57
+ utt.voice = [AVSpeechSynthesisVoice voiceWithLanguage: @"ja-JP"];
58
+ utt.rate = 0.5;
59
+
60
+ [synth writeUtterance: utt
61
+ toBufferCallback: ^(AVAudioBuffer* buffer)
62
+ {
63
+ auto finish = [&]()
64
+ {
65
+ pthis->self->finished = true;
66
+ [synth release];
67
+ };
68
+
69
+ if (![buffer isKindOfClass: AVAudioPCMBuffer.class])
70
+ return finish();
71
+
72
+ AVAudioPCMBuffer* pcmbuf = (AVAudioPCMBuffer*) buffer;
73
+ if (pcmbuf.frameLength == 0)
74
+ return finish();
75
+
76
+ [pcmbuf retain];
77
+ dispatch_async(dispatch_get_main_queue(), ^()
78
+ {
79
+ if (!pthis->self->signals)
80
+ pthis->self->signals = Signals_create(pcmbuf, 4096);
81
+ else
82
+ Signals_append(&pthis->self->signals, pcmbuf);
83
+ [pcmbuf release];
84
+ });
85
+ }];
86
+ }
87
+ else
88
+ not_implemented_error(__FILE__, __LINE__);
89
+ }
90
+
91
+ double
92
+ TextIn::sample_rate () const
93
+ {
94
+ return self->sample_rate;
95
+ }
96
+
97
+ TextIn::operator bool () const
98
+ {
99
+ if (!Super::operator bool()) return false;
100
+ return self->sample_rate > 0;
101
+ }
102
+
103
+ void
104
+ TextIn::generate (Context* context, Signals* signals, uint* offset)
105
+ {
106
+ Super::generate(context, signals, offset);
107
+
108
+ if (self->signals)
109
+ {
110
+ if (signals->sample_rate() != self->signals.sample_rate())
111
+ {
112
+ beeps_error(
113
+ __FILE__, __LINE__,
114
+ "sample_rate does not match: %f and %f",
115
+ signals->sample_rate(),
116
+ self->signals.sample_rate());
117
+ }
118
+
119
+ uint copied_size = Signals_copy(signals, self->signals);
120
+ Signals_shift(&self->signals, copied_size);
121
+ *offset += copied_size;
122
+ }
123
+
124
+ if (!self->finished)
125
+ {
126
+ uint fill_size = signals->capacity() - signals->nsamples();
127
+ Signals_fill(signals, fill_size, 0, signals->nsamples());
128
+ *offset += fill_size;
129
+ }
130
+ }
131
+
132
+
133
+ }// Beeps
data/src/signals.cpp CHANGED
@@ -116,13 +116,13 @@ namespace Beeps
116
116
  Signals
117
117
  Signals_create (
118
118
  const float* const* channels,
119
- uint nsamples, uint nchannels, double sample_rate)
119
+ uint nsamples, uint nchannels, double sample_rate, uint capacity)
120
120
  {
121
121
  if (!channels)
122
122
  argument_error(__FILE__, __LINE__);
123
123
 
124
- Signals s = Signals_create(nsamples, nchannels, sample_rate);
125
- s.self->nsamples = nsamples;
124
+ Signals s = Signals_create(
125
+ capacity > nsamples ? capacity : nsamples, nchannels, sample_rate);
126
126
 
127
127
  for (uint channel = 0; channel < nchannels; ++channel)
128
128
  {
@@ -131,32 +131,10 @@ namespace Beeps
131
131
  *p = channels[channel][i];
132
132
  }
133
133
 
134
+ s.self->nsamples = nsamples;
134
135
  return s;
135
136
  }
136
137
 
137
- void
138
- Signals_clear (Signals* signals)
139
- {
140
- if (!signals)
141
- argument_error(__FILE__, __LINE__);
142
-
143
- signals->self->nsamples = 0;
144
- }
145
-
146
- void
147
- Signals_clear (Signals* signals, uint capacity)
148
- {
149
- if (!signals)
150
- argument_error(__FILE__, __LINE__);
151
- if (!*signals)
152
- argument_error(__FILE__, __LINE__);
153
- if (capacity <= 0)
154
- argument_error(__FILE__, __LINE__);
155
-
156
- Signals_clear(signals);
157
- signals->self->frames->resize(capacity, signals->nchannels());
158
- }
159
-
160
138
  uint
161
139
  Signals_tick (Signals* signals, std::function<void(stk::StkFrames*)> fun)
162
140
  {
@@ -212,20 +190,70 @@ namespace Beeps
212
190
  }
213
191
 
214
192
  void
215
- Signals_fill (Signals* signals, uint nsamples, Sample value)
193
+ Signals_clear (Signals* signals)
194
+ {
195
+ if (!signals)
196
+ argument_error(__FILE__, __LINE__);
197
+
198
+ signals->self->nsamples = 0;
199
+ }
200
+
201
+ void
202
+ Signals_clear (Signals* signals, uint capacity)
216
203
  {
217
204
  if (!signals)
218
205
  argument_error(__FILE__, __LINE__);
219
206
  if (!*signals)
220
207
  argument_error(__FILE__, __LINE__);
208
+ if (capacity <= 0)
209
+ argument_error(__FILE__, __LINE__);
221
210
 
222
211
  Signals_clear(signals);
223
- Signals_set_nsamples(signals, nsamples);
212
+ signals->self->frames->resize(capacity, signals->nchannels());
213
+ }
224
214
 
225
- Sample* p = Signals_at(signals, 0);
215
+ void
216
+ Signals_fill (Signals* signals, uint nsamples, Sample value, uint offset)
217
+ {
218
+ if (!signals)
219
+ argument_error(__FILE__, __LINE__);
220
+ if (!*signals)
221
+ argument_error(__FILE__, __LINE__);
222
+
223
+ uint new_nsamples = offset + nsamples;
224
+ if (new_nsamples > signals->capacity())
225
+ beeps_error(__FILE__, __LINE__);
226
+
227
+ Sample* p = Signals_at(signals, offset);
226
228
  size_t size = nsamples * signals->nchannels();
227
229
  for (size_t i = 0; i < size; ++i)
228
230
  *p++ = value;
231
+
232
+ Signals_set_nsamples(signals, new_nsamples);
233
+ }
234
+
235
+ void
236
+ Signals_shift (Signals* signals, uint nsamples)
237
+ {
238
+ if (!signals)
239
+ argument_error(__FILE__, __LINE__);
240
+ if (!*signals)
241
+ argument_error(__FILE__, __LINE__);
242
+
243
+ if (nsamples == 0)
244
+ return;
245
+
246
+ int new_nsamples = signals->nsamples() - nsamples;
247
+ if (new_nsamples < 0)
248
+ new_nsamples = 0;
249
+
250
+ Sample* from = Signals_at(signals, nsamples);
251
+ Sample* to = Signals_at(signals, 0);
252
+ int size = new_nsamples * signals->nchannels();
253
+ for (int i = 0; i < size; ++i)
254
+ *to++ = *from++;
255
+
256
+ Signals_set_nsamples(signals, new_nsamples);
229
257
  }
230
258
 
231
259
  static uint
@@ -450,6 +478,43 @@ namespace Beeps
450
478
  write_samples(signals, samples, nsamples);
451
479
  }
452
480
 
481
+ void
482
+ Signals_set_capacity (Signals* signals, uint capacity)
483
+ {
484
+ if (!signals)
485
+ argument_error(__FILE__, __LINE__);
486
+ if (!*signals)
487
+ argument_error(__FILE__, __LINE__);
488
+ if (capacity == 0)
489
+ argument_error(__FILE__, __LINE__);
490
+
491
+ if (capacity == signals->capacity())
492
+ return;
493
+
494
+ uint nsamples = signals->nsamples();
495
+ uint nchannels = signals->nchannels();
496
+
497
+ if (capacity < signals->capacity())
498
+ {
499
+ signals->self->frames->resize(capacity, nchannels);
500
+ if (capacity < nsamples) Signals_set_nsamples(signals, capacity);
501
+ }
502
+ else
503
+ {
504
+ double sample_rate = signals->sample_rate();
505
+ const Sample* from = Signals_at(signals, 0);
506
+
507
+ std::unique_ptr<Frames> old = std::move(signals->self->frames);
508
+ signals->self->frames.reset(
509
+ new Frames(capacity * nchannels, nchannels, sample_rate));
510
+
511
+ Sample* to = Signals_at(signals, 0);
512
+ uint size = nsamples * nchannels;
513
+ for (uint i = 0; i < size; ++i)
514
+ *to++ = *from++;
515
+ }
516
+ }
517
+
453
518
  void
454
519
  Signals_set_nsamples (Signals* signals, uint nsamples)
455
520
  {
@@ -568,7 +633,16 @@ namespace Beeps
568
633
  bool
569
634
  Signals::empty () const
570
635
  {
571
- return self->nsamples == 0;
636
+ return nsamples() == 0;
637
+ }
638
+
639
+ bool
640
+ Signals::full () const
641
+ {
642
+ uint n = nsamples();
643
+ if (n == 0) return false;
644
+
645
+ return n == capacity();
572
646
  }
573
647
 
574
648
  const Sample*
data/src/signals.h CHANGED
@@ -26,7 +26,7 @@ namespace Beeps
26
26
 
27
27
  Signals Signals_create (
28
28
  const float* const* channels,
29
- uint nsamples, uint nchannels, double sample_rate = 0);
29
+ uint nsamples, uint nchannels, double sample_rate = 0, uint capacity = 0);
30
30
 
31
31
  uint Signals_tick (
32
32
  Signals* signals,
@@ -44,9 +44,13 @@ namespace Beeps
44
44
 
45
45
  void Signals_clear (Signals* signals, uint capacity);
46
46
 
47
- void Signals_fill (Signals* signals, uint nsamples, Sample value);
47
+ void Signals_fill (
48
+ Signals* signals, uint nsamples, Sample value,
49
+ uint offset = 0);
48
50
 
49
- uint Signals_copy (Signals* to, const Signals& from, uint from_offset);
51
+ void Signals_shift (Signals* signals, uint nsamples);
52
+
53
+ uint Signals_copy (Signals* to, const Signals& from, uint from_offset = 0);
50
54
 
51
55
  void Signals_add ( Signals* signals, const Signals& add);
52
56
 
@@ -60,7 +64,9 @@ namespace Beeps
60
64
  void Signals_write_samples (
61
65
  Signals* signals, const SignalSamples<T>& samples, long nsamples = -1);
62
66
 
63
- void Signals_set_nsamples (Signals* signals, uint nsamples);
67
+ void Signals_set_capacity (Signals* signals, uint capacity);
68
+
69
+ void Signals_set_nsamples (Signals* signals, uint nsamples);
64
70
 
65
71
  Sample* Signals_at ( Signals* signals, uint index, uint channel = 0);
66
72
 
@@ -0,0 +1,62 @@
1
+ // -*- c++ -*-
2
+ #include "beeps/generator.h"
3
+
4
+
5
+ #include "beeps/exception.h"
6
+ #include "../signals.h"
7
+
8
+
9
+ namespace Beeps
10
+ {
11
+
12
+
13
+ struct TextIn::Data
14
+ {
15
+
16
+ double sample_rate = 0;
17
+
18
+ };// TextIn::Data
19
+
20
+
21
+ TextIn::TextIn (const char* text, double sample_rate)
22
+ {
23
+ if (sample_rate == 0)
24
+ sample_rate = Beeps::sample_rate();
25
+ if (sample_rate <= 0)
26
+ argument_error(__FILE__, __LINE__);
27
+
28
+ self->sample_rate = sample_rate;
29
+
30
+ if (text) synthesize(text);
31
+ }
32
+
33
+ TextIn::~TextIn ()
34
+ {
35
+ }
36
+
37
+ void
38
+ TextIn::synthesize (const char* text)
39
+ {
40
+ not_implemented_error(__FILE__, __LINE__);
41
+ }
42
+
43
+ double
44
+ TextIn::sample_rate () const
45
+ {
46
+ return self->sample_rate;
47
+ }
48
+
49
+ TextIn::operator bool () const
50
+ {
51
+ if (!Super::operator bool()) return false;
52
+ return self->sample_rate > 0;
53
+ }
54
+
55
+ void
56
+ TextIn::generate (Context* context, Signals* signals, uint* offset)
57
+ {
58
+ Super::generate(context, signals, offset);
59
+ }
60
+
61
+
62
+ }// Beeps
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beeps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - xordog
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-22 00:00:00.000000000 Z
11
+ date: 2025-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: xot
@@ -16,40 +16,40 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.3.8
19
+ version: 0.3.9
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 0.3.8
22
+ version: 0.3.9
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: 0.3.8
29
+ version: 0.3.9
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.3.8
32
+ version: 0.3.9
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rucy
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.3.8
39
+ version: 0.3.9
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 0.3.8
42
+ version: 0.3.9
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: 0.3.8
49
+ version: 0.3.9
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 0.3.8
52
+ version: 0.3.9
53
53
  description: Synthesize and play beep sounds.
54
54
  email: xordog@gmail.com
55
55
  executables: []
@@ -75,6 +75,7 @@ extra_rdoc_files:
75
75
  - ".doc/ext/beeps/signals.cpp"
76
76
  - ".doc/ext/beeps/sound.cpp"
77
77
  - ".doc/ext/beeps/sound_player.cpp"
78
+ - ".doc/ext/beeps/text_in.cpp"
78
79
  - ".doc/ext/beeps/time_stretch.cpp"
79
80
  files:
80
81
  - ".doc/ext/beeps/analyser.cpp"
@@ -96,6 +97,7 @@ files:
96
97
  - ".doc/ext/beeps/signals.cpp"
97
98
  - ".doc/ext/beeps/sound.cpp"
98
99
  - ".doc/ext/beeps/sound_player.cpp"
100
+ - ".doc/ext/beeps/text_in.cpp"
99
101
  - ".doc/ext/beeps/time_stretch.cpp"
100
102
  - ".github/PULL_REQUEST_TEMPLATE.md"
101
103
  - ".github/workflows/release-gem.yml"
@@ -132,6 +134,7 @@ files:
132
134
  - ext/beeps/signals.cpp
133
135
  - ext/beeps/sound.cpp
134
136
  - ext/beeps/sound_player.cpp
137
+ - ext/beeps/text_in.cpp
135
138
  - ext/beeps/time_stretch.cpp
136
139
  - include/beeps.h
137
140
  - include/beeps/beeps.h
@@ -176,7 +179,9 @@ files:
176
179
  - src/openal.h
177
180
  - src/oscillator.cpp
178
181
  - src/osx/beeps.mm
182
+ - src/osx/signals.h
179
183
  - src/osx/signals.mm
184
+ - src/osx/text_in.mm
180
185
  - src/pitch_shift.cpp
181
186
  - src/processor.cpp
182
187
  - src/processor.h
@@ -191,6 +196,7 @@ files:
191
196
  - src/win32/exception.cpp
192
197
  - src/win32/exception.h
193
198
  - src/win32/signals.cpp
199
+ - src/win32/text_in.cpp
194
200
  - src/x_pass.h
195
201
  - test/helper.rb
196
202
  - test/test_analyser.rb