seal 0.1.2 → 0.1.3

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6a4ec328c05b480d1e4771accd5feddc120359f0
4
+ data.tar.gz: 5006a20741965f24f45f4e0f1d1f5ccc41859956
5
+ SHA512:
6
+ metadata.gz: be6c6509925a48baddd68cf0089becceaff0d84394c85cae4e68c6b485a5037728dabac4b5492555ea833ad8c0fd95c895bbbf0145ce31b68a6fa33074549806
7
+ data.tar.gz: 589899ce37a1f214815c3aa5860752cecf1398cf39e0236104bd4ce2d9dc4b0a3d8760e91febd767608c9bd302d80baac74bac7baa69f319773c67edc725bd7f
data/README.md CHANGED
@@ -3,10 +3,17 @@
3
3
  Seal is a C library with Ruby binding for audio rendering and manipulation,
4
4
  such as direction and distance attenuation, the simulation of the Doppler
5
5
  effect and reverberation, in a 3D space. It is built on top of [OpenAL]
6
- (http://connect.creativelabs.com/openal/default.aspx), adding support for
7
- audio streaming and audio formats like Ogg Vorbis, MPEG Audio and WAVE.
6
+ (http://connect.creativelabs.com/openal/default.aspx).
8
7
 
9
- ## Basic Use
8
+ ## Why Seal? Why not Simply Use OpenAL?
9
+
10
+ 0. Seal has a Ruby binding and many syntactic sugars.
11
+ 1. Seal supports audio formats like Ogg Vorbis, MPEG Audio and WAVE.
12
+ 2. Seal abstracts automatic audio streaming (also preventing problems like
13
+ discontinued stream due to I/O stress).
14
+ 3. More stuff in the future...
15
+
16
+ ## Basic Usage
10
17
 
11
18
  Initialize Seal:
12
19
 
@@ -167,6 +174,11 @@ CC=/usr/bin/gcc-4.2 cmake -DCMAKE_BUILD_TYPE=Release ..
167
174
  After OpenAL is installed, you can start building Seal. Seal will dynamically
168
175
  link OpenAL.
169
176
 
177
+ Note that depending on where OpenAL's `make install` installs the actual
178
+ shared library, you may need to add the lib path to `LD_LIBRARY_PATH` in
179
+ order for Seal to find the shared `libopenal.so` file.
180
+
181
+
170
182
  ### Install as a Gem (in a sane environment)
171
183
 
172
184
  ```Bash
@@ -12,7 +12,7 @@ mpg123_dir = File.join root_dir, 'mpg123'
12
12
  mpg123_src_dir = File.join mpg123_dir, 'src'
13
13
  mpg123_lib_dir = File.join mpg123_src_dir, 'libmpg123', '.libs'
14
14
 
15
- $defs << '-DNDEBUG'
15
+ $defs << '-DNDEBUG' << '-DMPG123_NO_LARGENAME'
16
16
  $LDFLAGS << ' -s'
17
17
 
18
18
  unless File.exists?(File.join(mpg123_src_dir, 'config.h'))
@@ -1,8 +1,4 @@
1
1
  /*
2
- * seal.h is part of the Scorched End Audio Library (SEAL) and is licensed
3
- * under the terms of the GNU Lesser General Public License. See COPYING
4
- * attached with the library.
5
- *
6
2
  * seal.h is the master header file for the Scorched End Audio Library. By
7
3
  * including seal.h, there will be no need to include the inidividual modules'
8
4
  * header files.
@@ -166,10 +166,14 @@ seal_err_t SEAL_API seal_set_src_stream(seal_src_t*, seal_stream_t*);
166
166
  seal_err_t SEAL_API seal_feed_efs(seal_src_t*, seal_efs_t*, int /*index*/);
167
167
 
168
168
  /*
169
- * Updates a streaming source. If the source is not up-to-date, the playback
170
- * will end before the end of the stream is reached. Does nothing if the
171
- * passed-in source is not a streaming source. Also does nothing if auto
172
- * update is on.
169
+ * Updates a streaming source by filling up the audio queue until it is full.
170
+ * If the source is not up-to-date, the playback will end before the end of
171
+ * the stream is reached. Does nothing if the passed-in source is not a
172
+ * streaming source. Also does nothing if auto update is on. When auto update
173
+ * is off, it is the caller's responsibility to handle cases where the consumer
174
+ * (OpenAL) consumes faster than the producer (the caller) produces and causes
175
+ * the playback to stop. Automatic sources automatically resume playing in such
176
+ * cases.
173
177
  *
174
178
  * @param src the source to update
175
179
  */
@@ -453,6 +457,7 @@ struct seal_src_t
453
457
  size_t queue_size : 6;
454
458
  unsigned int looping : 1;
455
459
  unsigned int automatic : 1;
460
+ unsigned int early_stop : 1;
456
461
  };
457
462
 
458
463
  #endif /* _SEAL_SRC_H_ */
@@ -1,15 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Seal do
4
- it 'should initialize and finalize correctly on default device' do
5
- expect do
6
- Seal.startup
7
- Seal.cleanup
8
- end.to_not raise_error
9
- end
4
+ context 'initially' do
5
+ # Examples in this group needs to call Seal.startup themselves instead of
6
+ # relying on it being implicitly called by the global before hook.
7
+ # Therefore, Seal must be finalized in order to avoid double startup, which
8
+ # may fail for some devices due to opening an already opened, busy device.
9
+ before { Seal.cleanup }
10
+ # Since there is a global after hook for Seal.cleanup, we insert this after
11
+ # hook before the global one so the global one will then cleans up
12
+ # properly.
13
+ prepend_after { Seal.startup }
14
+
15
+ it 'starts up and cleans up properly on default device' do
16
+ expect do
17
+ Seal.startup
18
+ Seal.cleanup
19
+ end.to_not raise_error
20
+ end
10
21
 
11
- it 'should fail when trying to initialize non-existing device' do
12
- expect { Seal.startup 'foo42' }.to raise_error SealError
22
+ it 'fails when trying to start up on non-existing device' do
23
+ expect { Seal.startup 'foo42' }.to raise_error SealError
24
+ end
13
25
  end
14
26
 
15
27
  it 'has only one instance of Listener' do
@@ -11,7 +11,7 @@ describe EffectSlot do
11
11
 
12
12
  it_validates 'the boolean attribute', :auto
13
13
  it_validates 'the float attribute', :gain, "[0, 1]"
14
- it_defines 'boolean reader aliases', [:auto]
14
+ it_defines 'boolean reader aliases', %i(auto)
15
15
 
16
16
  it 'can initialize with an effect' do
17
17
  reverb = Reverb.new
@@ -30,7 +30,7 @@ describe Reverb do
30
30
  it_validates 'the float attribute', :reflections_delay, '[0, 0.3]'
31
31
  it_validates 'the float attribute', :reflections_gain, '[0, 3.16]'
32
32
  it_validates 'the float attribute', :room_rolloff_factor, '[0, 10]'
33
- it_defines 'boolean reader aliases', [:hfdecay_limited]
33
+ it_defines 'boolean reader aliases', %i(hfdecay_limited)
34
34
 
35
35
  specify_preset_loading = -> mod do
36
36
  mod.constants.each do |const_sym|
@@ -28,7 +28,7 @@ describe Source do
28
28
  it_validates 'the boolean attribute', :auto
29
29
  it_validates 'the float attribute', :pitch, "[0, +inf.)"
30
30
  it_validates 'the float attribute', :gain, "[0, +inf.)"
31
- it_defines 'boolean reader aliases', [:auto, :relative, :looping]
31
+ it_defines 'boolean reader aliases', %i(auto relative looping)
32
32
 
33
33
  it 'validates its queue size is in [2, 63]' do
34
34
  error_pattern = /Invalid parameter value/
@@ -773,9 +773,13 @@ feed_efs(VALUE rsrc, VALUE rslot, VALUE rindex)
773
773
  * call-seq:
774
774
  * source.update -> source
775
775
  *
776
- * Updates _source_. If _source_ is not up-to-date, the playback will end
777
- * before the end of the stream is reached. Does nothing if _source_ is not a
778
- * streaming source. Also does nothing if auto update is on.
776
+ * Updates a streaming _source_ by filling up the audio queue until it is full.
777
+ * If _source_ is not up-to-date, the playback will end before the end of the
778
+ * stream is reached. Does nothing if _source_ is not a streaming source. Also
779
+ * does nothing if auto update is on. When auto update is off, it is the
780
+ * caller's responsibility to handle cases where the consumer (OpenAL) consumes
781
+ * faster than the producer (the caller) produces and causes the playback to
782
+ * stop. Automatic sources automatically resume playing in such cases.
779
783
  */
780
784
  static
781
785
  VALUE update_src(VALUE rsrc)
@@ -1701,6 +1705,14 @@ get_listener()
1701
1705
  return rb_const_get(mSeal, rb_intern("LISTENER"));
1702
1706
  }
1703
1707
 
1708
+ /*
1709
+ * call-seq:
1710
+ * listener.move -> listener
1711
+ *
1712
+ * Moves the listener (changes the position) based on the source velocity. This
1713
+ * is a syntactic sugar for adding the velocity vector and position vector. See
1714
+ * Source#move.
1715
+ */
1704
1716
  static
1705
1717
  VALUE
1706
1718
  move_listener(VALUE rlistener)
@@ -31,7 +31,7 @@ const char*
31
31
  SEAL_API
32
32
  seal_get_version(void)
33
33
  {
34
- return "0.1.2";
34
+ return "0.1.3";
35
35
  }
36
36
 
37
37
  static
@@ -27,6 +27,9 @@ static const size_t DEFAULT_CHUNK_SIZE = MIN_CHUNK_SIZE << 2;
27
27
  static const size_t MAX_CHUNK_SIZE = CHUNK_STORAGE_CAP -
28
28
  CHUNK_STORAGE_CAP % MIN_CHUNK_SIZE;
29
29
 
30
+ /*
31
+ * Checks if `val` is in the closed interval [`lower_bound`, `upper_bound`].
32
+ */
30
33
  static
31
34
  seal_err_t
32
35
  check_val_limit(int val, int lower_bound, int upper_bound)
@@ -39,13 +42,42 @@ check_val_limit(int val, int lower_bound, int upper_bound)
39
42
  return SEAL_OK;
40
43
  }
41
44
 
45
+ /*
46
+ * Called when the state of a source is preemptively changed by a caller.
47
+ */
42
48
  static
43
49
  seal_err_t
44
- operate(seal_src_t* src, void (*op)(unsigned int))
50
+ on_preemptive_state_change(seal_src_t* src)
45
51
  {
52
+ seal_err_t err;
53
+ seal_src_state_t state;
54
+
55
+ if ((err = seal_get_src_state(src, &state)) != SEAL_OK)
56
+ return err;
57
+
58
+ /* Set `early_stop` to true after playing so it will only be set to false
59
+ * when playback ended with the end of stream reached or the state is
60
+ * preemptively changed.
61
+ */
62
+ src->early_stop = state == SEAL_PLAYING ? 1 : 0;
63
+
64
+ return SEAL_OK;
65
+ }
66
+
67
+ /*
68
+ * Changes the source state by calling one of the four operations on a source.
69
+ */
70
+ static
71
+ seal_err_t
72
+ change_state(seal_src_t* src, void (*op)(unsigned int))
73
+ {
74
+ seal_err_t err;
75
+
46
76
  op(src->id);
77
+ if ((err = _seal_get_openal_err()) != SEAL_OK)
78
+ return err;
47
79
 
48
- return _seal_get_openal_err();
80
+ return on_preemptive_state_change(src);
49
81
  }
50
82
 
51
83
  static
@@ -76,6 +108,9 @@ wait4updater(seal_src_t* src)
76
108
  }
77
109
  }
78
110
 
111
+ /*
112
+ * The main routine for updater threads.
113
+ */
79
114
  static
80
115
  void*
81
116
  update(void* args)
@@ -85,11 +120,22 @@ update(void* args)
85
120
 
86
121
  while (alIsSource(src->id)) {
87
122
  seal_src_state_t state;
88
- err = seal_get_src_state(src, &state);
89
- if (err != SEAL_OK || state != SEAL_PLAYING)
90
- break;
123
+
124
+ /* Check source state before checking if interrupted by caller. */
125
+ if ((err = seal_get_src_state(src, &state)) != SEAL_OK)
126
+ break;
127
+ if (state != SEAL_PLAYING) {
128
+ /* Early stopping, most likely due to I/O load. Restart playing. */
129
+ if (src->early_stop) {
130
+ if ((err = change_state(src, alSourcePlay)) != SEAL_OK)
131
+ break;
132
+ } else {
133
+ break;
134
+ }
135
+ }
91
136
  if ((err = seal_update_src(src)) != SEAL_OK)
92
137
  break;
138
+
93
139
  _seal_sleep(50);
94
140
  }
95
141
 
@@ -119,6 +165,10 @@ unqueue_bufs(seal_src_t* src, int nbufs, unsigned int* bufs)
119
165
  return queue_op(src, nbufs, bufs, alSourceUnqueueBuffers);
120
166
  }
121
167
 
168
+ /*
169
+ * Cleans the queue and free any allocated buffers in the queue. This function
170
+ * assumes the source is stopped at the time of calling.
171
+ */
122
172
  static
123
173
  seal_err_t
124
174
  clean_queue(seal_src_t* src)
@@ -151,8 +201,9 @@ clean_queue(seal_src_t* src)
151
201
  }
152
202
 
153
203
  /*
154
- * Stopping a source will mark all the buffers in its queue processed so that
155
- * they can be unqueued.
204
+ * Cleans the queue after stopping the source. A stopped source will have all
205
+ * the buffers in its queue marked as processed so that they can be unqueued.
206
+ * This function assumes the source is playing at the time of calling.
156
207
  */
157
208
  static
158
209
  seal_err_t
@@ -160,7 +211,7 @@ stop_then_clean_queue(seal_src_t* src)
160
211
  {
161
212
  seal_err_t err;
162
213
 
163
- if ((err = operate(src, alSourceStop)) != SEAL_OK)
214
+ if ((err = change_state(src, alSourceStop)) != SEAL_OK)
164
215
  return err;
165
216
 
166
217
  return clean_queue(src);
@@ -178,6 +229,10 @@ restart_queuing(seal_src_t* src)
178
229
  return seal_rewind_stream(src->stream);
179
230
  }
180
231
 
232
+ /*
233
+ * This does the same thing as `stop_then_clean_queue` except it works for
234
+ * sources in any state at the time of calling.
235
+ */
181
236
  static
182
237
  seal_err_t
183
238
  empty_queue(seal_src_t* src)
@@ -185,7 +240,7 @@ empty_queue(seal_src_t* src)
185
240
  seal_err_t err;
186
241
 
187
242
  /* Need to be playing first in order to become stopped. */
188
- if ((err = operate(src, alSourcePlay)) != SEAL_OK)
243
+ if ((err = change_state(src, alSourcePlay)) != SEAL_OK)
189
244
  return err;
190
245
 
191
246
  return stop_then_clean_queue(src);
@@ -210,11 +265,13 @@ seal_init_src(seal_src_t* src)
210
265
  if (err == SEAL_OK) {
211
266
  src->buf = 0;
212
267
  src->stream = 0;
268
+ /* The id of the thread that is updating the source. */
213
269
  src->updater = 0;
214
270
  src->chunk_size = DEFAULT_CHUNK_SIZE;
215
271
  src->queue_size = DEFAULT_QUEUE_SIZE;
216
272
  src->looping = 0;
217
273
  src->automatic = 1;
274
+ src->early_stop = 0;
218
275
  }
219
276
 
220
277
  return err;
@@ -257,18 +314,23 @@ seal_play_src(seal_src_t* src)
257
314
  /* Stream some data so plackback can start immediately. */
258
315
  if ((err = seal_update_src(src)) != SEAL_OK)
259
316
  return err;
317
+ /* Actually start playing. */
318
+ if ((err = change_state(src, alSourcePlay)) != SEAL_OK)
319
+ return err;
320
+ /* Create background updater for automatic sources. */
260
321
  if (src->automatic)
261
322
  src->updater = _seal_create_thread(update, src);
323
+ return SEAL_OK;
324
+ } else {
325
+ return change_state(src, alSourcePlay);
262
326
  }
263
-
264
- return operate(src, alSourcePlay);
265
327
  }
266
328
 
267
329
  seal_err_t
268
330
  SEAL_API
269
331
  seal_pause_src(seal_src_t* src)
270
332
  {
271
- return operate(src, alSourcePause);
333
+ return change_state(src, alSourcePause);
272
334
  }
273
335
 
274
336
  seal_err_t
@@ -277,7 +339,10 @@ seal_stop_src(seal_src_t* src)
277
339
  {
278
340
  seal_err_t err;
279
341
 
280
- if ((err = operate(src, alSourceStop)) == SEAL_OK && src->stream != 0)
342
+ if ((err = change_state(src, alSourceStop)) != SEAL_OK)
343
+ return err;
344
+
345
+ if (src->stream != 0)
281
346
  /* Already stopped so all buffers are proccessed. */
282
347
  if ((err = clean_queue(src)) == SEAL_OK)
283
348
  err = seal_rewind_stream(src->stream);
@@ -299,7 +364,7 @@ seal_rewind_src(seal_src_t* src)
299
364
  return err;
300
365
  }
301
366
 
302
- return operate(src, alSourceRewind);
367
+ return change_state(src, alSourceRewind);
303
368
  }
304
369
 
305
370
  seal_err_t
@@ -312,13 +377,17 @@ seal_detach_src_audio(seal_src_t* src)
312
377
  return err;
313
378
 
314
379
  /* Sets the state to `SEAL_INITIAL' for consistency. */
315
- if ((err = operate(src, alSourceRewind)) != SEAL_OK)
380
+ if ((err = change_state(src, alSourceRewind)) != SEAL_OK)
316
381
  return err;
317
382
 
318
- if ((err = _seal_seti(src, AL_BUFFER, AL_NONE, alSourcei)) == SEAL_OK) {
319
- src->buf = 0;
320
- src->stream = 0;
321
- }
383
+ if ((err = _seal_seti(src, AL_BUFFER, AL_NONE, alSourcei)) != SEAL_OK)
384
+ return err;
385
+
386
+ if ((err = on_preemptive_state_change(src)) != SEAL_OK)
387
+ return err;
388
+
389
+ src->buf = 0;
390
+ src->stream = 0;
322
391
 
323
392
  return err;
324
393
  }
@@ -486,6 +555,7 @@ start_streaming:
486
555
  goto start_streaming;
487
556
  /* End of stream reached. */
488
557
  } else {
558
+ src->early_stop = 0;
489
559
  break;
490
560
  }
491
561
  } /* for (;;) */
metadata CHANGED
@@ -1,36 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
5
- prerelease:
4
+ version: 0.1.3
6
5
  platform: ruby
7
6
  authors:
8
7
  - Su Zhang
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-25 00:00:00.000000000 Z
11
+ date: 2013-06-22 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake-compiler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rspec
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,55 +41,51 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: guard-rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: yard
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: rb-inotify
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
- description: ! " Seal is a library for 3D audio rendering and manipulation, supporting\n
95
- \ effects such as direction and distance attenuation, the simulation of the\n
96
- \ Doppler effect and reverberation. It is built on top of OpenAL, adding\n support
97
- for audio streaming and audio formats like Ogg Vorbis, MPEG Audio\n and WAVE.\n"
83
+ description: |2
84
+ Seal is a library for 3D audio rendering and manipulation, supporting
85
+ effects such as direction and distance attenuation, the simulation of the
86
+ Doppler effect and reverberation. It is built on top of OpenAL, adding
87
+ support for audio streaming and audio formats like Ogg Vorbis, MPEG Audio
88
+ and WAVE.
98
89
  email: me@zhang.su
99
90
  executables: []
100
91
  extensions:
@@ -525,41 +516,39 @@ files:
525
516
  homepage: https://github.com/zhangsu/seal
526
517
  licenses:
527
518
  - WTFPL
519
+ metadata: {}
528
520
  post_install_message: Enjoy!
529
521
  rdoc_options: []
530
522
  require_paths:
531
523
  - lib
532
524
  required_ruby_version: !ruby/object:Gem::Requirement
533
- none: false
534
525
  requirements:
535
- - - ~>
526
+ - - '>='
536
527
  - !ruby/object:Gem::Version
537
- version: '1.9'
528
+ version: 1.9.2
538
529
  required_rubygems_version: !ruby/object:Gem::Requirement
539
- none: false
540
530
  requirements:
541
- - - ! '>='
531
+ - - '>='
542
532
  - !ruby/object:Gem::Version
543
533
  version: '0'
544
534
  requirements:
545
535
  - libopenal
546
536
  - a sound card
547
537
  rubyforge_project:
548
- rubygems_version: 1.8.24
538
+ rubygems_version: 2.0.0
549
539
  signing_key:
550
- specification_version: 3
540
+ specification_version: 4
551
541
  summary: An OpenAL-based 3D audio library
552
542
  test_files:
553
543
  - spec/seal/buffer_spec.rb
554
544
  - spec/seal/core_spec.rb
555
- - spec/seal/stream_spec.rb
545
+ - spec/seal/effect_slot_spec.rb
556
546
  - spec/seal/listener_spec.rb
557
547
  - spec/seal/reverb_spec.rb
558
- - spec/seal/effect_slot_spec.rb
559
548
  - spec/seal/source_spec.rb
560
- - spec/support/movable_object.rb
549
+ - spec/seal/stream_spec.rb
550
+ - spec/spec_helper.rb
551
+ - spec/support/attribute_examples.rb
561
552
  - spec/support/audio_object_with_format.rb
562
553
  - spec/support/boolean_reader_aliases.rb
563
- - spec/support/attribute_examples.rb
564
- - spec/spec_helper.rb
565
- has_rdoc: yard
554
+ - spec/support/movable_object.rb