sound 0.0.9 → 0.1.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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NzdkMGRkZDM3ODkxZTM4NDNkY2FhMjU3M2JiYTE2Y2MwM2M2Y2MzOQ==
4
+ YjA0NGNiZGY0MzRkN2IzMjMyY2JhZDhhMzM0OWI2ZDFiN2QzN2EyMQ==
5
5
  data.tar.gz: !binary |-
6
- NmUxZmE3NGMyZjQ1ZTExZjhmMmMyMTNhYmYyMTQ3ZDJmY2I3NjlmZg==
6
+ MmRkM2IyYjY4NTlhZjRkNDZiODc4ODhiN2RiN2ZiY2I1YjIxNDVmNw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- N2MyNDZkYzE4Y2U4YjU4ZTBiN2YwOTRmNjk5OTFmMTMxMmZmNjI3NzljMTBk
10
- YmIxNmU1NzU0MDgxNzQ5NGQwZTQxNTQ4NjE0ODE4MmY4MDFjMzgyMjVlYWVl
11
- NjgyZjY3ZDQzZGQxYTZkZGUwYThiZmEwMWIzNTZlNzkxNmZjZTM=
9
+ Y2ExM2QwNDg5NjI2MjM1NmE2MzE0YTVmODdjMGFiMjNiZjM4ZDRiMzRlNTA4
10
+ ZTQwNjBmZTE1OGJiZmExZWQyNjA1Nzc1ZDk1YzM2NzViNWQ0NzM1NDdkMWMz
11
+ M2ExNDM3ODlhZjAyZWMwY2JiZmE1ZWFmYWZmZWFkYTAxNzQ2ODM=
12
12
  data.tar.gz: !binary |-
13
- ODJlYzA5MzQyYjljYzZjODY5OGM2NGUzMTBlODNjZTE0NDZmOWZmNzEwNDU0
14
- MWM3OWU3MDI3YzU3NzA3ODc2NzMwODJlMTE1NGExYWMyMGU3M2M5MmM4ZmU0
15
- NTFhMzEyNTM4ZGE3YTdkODVmNzkxOTgyYzY0NjU5ZDEwMzBmYmU=
13
+ Njk3N2I3NjY1Y2Q4ODk4ODYxMzU3NjA2ODIwZWI2ZmJhMWUwM2ZlMTA4Zjgz
14
+ NjdhNjQzZjA0OWY1YjdkZjc4ODk4YTEwM2RkZTM4N2ZlOWJmOTk1ZmZhOWNl
15
+ ZTA4NjllZGQ3ZmE0YTI2MTE2OTJhMjZjNWZmMTU2MTA3Yjg5MWY=
@@ -12,7 +12,7 @@ Sound.verbose = true
12
12
  device = Sound::Device.new("w")
13
13
 
14
14
  # creates a PCM format object
15
- format = Sound::Format.new(Sound::Format::PCM)
15
+ format = Sound::Format.new#(Sound::Format::PCM)
16
16
 
17
17
  # creates a new Sound Data object with a PCM format
18
18
  data = Sound::Data.new(format)
@@ -1,5 +1,9 @@
1
1
  module OS
2
2
 
3
+ class << self
4
+ attr_accessor :os
5
+ end
6
+
3
7
  def OS.windows?
4
8
  os == :windows
5
9
  end
@@ -17,21 +21,22 @@ module OS
17
21
  end
18
22
 
19
23
  def OS.os
20
- @os ||= (
21
- host_os = RbConfig::CONFIG['host_os']
22
- case host_os
23
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc|emx/
24
- :windows
25
- when /darwin|mac os/
26
- :mac
27
- when /linux/
28
- :linux
29
- when /solaris|bsd/
30
- :unix
31
- else
32
- raise Error::WebDriverError, "unknown os: #{host_os.inspect}"
33
- end
34
- )
24
+ @os ||= OS.host_os
25
+ end
26
+
27
+ def OS.host_os
28
+ case RbConfig::CONFIG['host_os']
29
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc|emx/
30
+ :windows
31
+ when /darwin|mac os/
32
+ :mac
33
+ when /linux/
34
+ :linux
35
+ when /solaris|bsd/
36
+ :unix
37
+ else
38
+ raise Error::WebDriverError, "unknown os: #{RbConfig::CONFIG['host_os'].inspect}"
39
+ end
35
40
  end
36
41
 
37
42
  end
@@ -1,5 +1,3 @@
1
-
2
- require 'ffi'
3
1
  require 'pry'
4
2
  require 'os/os'
5
3
 
@@ -7,10 +5,10 @@ module Sound
7
5
 
8
6
  @verbose = false
9
7
  @no_device = false
10
- @platform_supported = false
8
+ @platform_supported = true
11
9
 
12
10
  class << self
13
- attr_accessor :verbose, :no_device, :platform_supported
11
+ attr_accessor :verbose, :no_device, :platform_supported, :device_library, :format_library
14
12
  end
15
13
 
16
14
  class NoDeviceError < RuntimeError; end
@@ -19,29 +17,29 @@ module Sound
19
17
  end
20
18
 
21
19
  if OS.windows?
22
- require 'sound/win32'
23
- module Sound
24
- class Device
25
- include Win32
26
- end
27
- end
28
- Sound.platform_supported = true
20
+ require 'sound/device_library/mmlib'
21
+ require 'sound/format_library/mmlib'
22
+ Sound.device_library = Sound::DeviceLibrary::MMLib
23
+ Sound.format_library = Sound::FormatLibrary::MMLib
29
24
  elsif OS.linux?
30
25
  libasound_present = !(`which aplay`.eql? "")
31
- unless libasound_present
26
+ if libasound_present
27
+ require 'sound/device_library/alsa'
28
+ require 'sound/format_library/alsa'
29
+ Sound.device_library = Sound::DeviceLibrary::ALSA
30
+ Sound.format_library = Sound::FormatLibrary::ALSA
31
+ else
32
32
  warn("warning: sound output requires libasound2, libasound2-dev, and alsa-utils packages")
33
33
  end
34
- require 'sound/alsa'
35
- module Sound
36
- class Device
37
- include ALSA
38
- end
39
- end
40
- Sound.platform_supported = true
41
34
  else
35
+ Sound.device_library = Sound::DeviceLibrary::Base
36
+ Sound.format_library = Sound::FormatLibrary::Base
42
37
  warn("warning: Sound output not yet implemented for this platform: #{OS.os}")
38
+ Sound.platform_supported = false
43
39
  end
44
40
 
41
+ require 'sound/device_library'
42
+ require 'sound/format_library'
45
43
  require 'sound/device'
46
44
  require 'sound/data'
47
45
  require 'sound/format'
@@ -7,9 +7,6 @@ module Sound
7
7
  @format = format
8
8
  @pcm_data = []
9
9
  end
10
- def to_s
11
- puts "#<Sound::Data:#{object_id}>"
12
- end
13
10
  def generate_sine_wave(freq, duration, volume)
14
11
  @pcm_data = []
15
12
  @duration = duration
@@ -2,8 +2,14 @@
2
2
  module Sound
3
3
 
4
4
  class Device
5
+ include DeviceLibrary
5
6
 
6
- class Buffer < Array; end
7
+ class Buffer < Array
8
+ attr_accessor :force
9
+ def new_block
10
+ self.force || self.empty? || self.last.kind_of?(Thread)
11
+ end
12
+ end
7
13
 
8
14
  attr_reader :status, :id
9
15
 
@@ -12,7 +18,7 @@ module Sound
12
18
  # if a block is passed, it executes the code in the block, passing
13
19
  # the newly created device, and then closes the device.
14
20
  #
15
- def initialize(direction = "w", id = DEFAULT_DEVICE_ID, &block)
21
+ def initialize(direction = "w", id = DeviceLibrary::DEFAULT_DEVICE_ID, &block)
16
22
 
17
23
  @id = id
18
24
  @status = :open
@@ -87,7 +93,7 @@ module Sound
87
93
  #
88
94
  def write(data = Sound::Data.new)
89
95
  if closed?
90
- puts "cannot write to a closed device"
96
+ warn("warning: cannot write to a closed device")
91
97
  else
92
98
  @mutex.lock
93
99
  @queue << Thread.new do
@@ -104,42 +110,49 @@ module Sound
104
110
  # starts up data block threads that get played back at the same time. Need
105
111
  # to make all threads wait until others are finished preparing the buffer.
106
112
  #
107
- def write_async(data = Sound::Data.new, new_queue_elem = false)
113
+ def write_async(data = Sound::Data.new, force_new = false)
108
114
  if closed?
109
- puts "cannot write to a closed device"
115
+ warn("warning: cannot write to a closed device")
110
116
  else
111
117
  @mutex.lock
112
- if new_queue_elem || @queue.empty? || @queue.last.kind_of?(Thread)
113
- threads = []
114
- threads << Thread.new do
115
- Thread.current[:async] = true
116
- Thread.current[:data] = data
117
- write_thread
118
- end
119
- @queue << threads
118
+ @queue.force = force_new
119
+ if @queue.new_block
120
+ @queue << [new_async_thread_for(data)]
120
121
  else
121
- @queue.last << Thread.new do
122
- Thread.current[:async] = true
123
- Thread.current[:data] = data
124
- write_thread
125
- end
122
+ @queue.last << new_async_thread_for(data)
126
123
  end
127
124
  @mutex.unlock
128
125
  puts "writing async to queue of device '#{id}': #{data}" if Sound.verbose
129
126
  end
127
+ self
130
128
  end
131
129
 
132
- # should make a close! method that ignores any pending queue data blocks,
133
- # but still safely closes the device as quickly as possible.
130
+ # flushes any pending queue data blocks, waits for them to finish playing,
131
+ # and then closes the device.
134
132
  #
135
133
  def close
136
134
  if closed?
137
- puts "cannot close a closed device"
135
+ warn("warning: device is already closed")
138
136
  else
139
137
  flush
140
138
  puts "device '#{id}' is closing now" if Sound.verbose
141
139
  @status = :closed
142
140
  end
141
+ self
142
+ end
143
+
144
+ # closes the device as quickly as possible without flushing the
145
+ # data buffer.
146
+ #
147
+ def close!
148
+ if closed?
149
+ warn("warning: device is already closed")
150
+ else
151
+ flush!
152
+ puts "device '#{id}' is closing immediately now" if Sound.verbose
153
+ @status = :closed
154
+ end
155
+ self
143
156
  end
144
157
 
145
158
  # flushes each block after previous finishes. Should make other options,
@@ -149,36 +162,62 @@ module Sound
149
162
  until @queue.empty?
150
163
  output = @queue.shift
151
164
  if output.kind_of? Thread
152
- output[:stop] = false
153
- puts "writing to device '#{id}': #{output[:data].class}" if Sound.verbose #this may be NilClass if parent thread is too fast
154
- output.run.join
165
+ finish_up(output).join
155
166
  else
156
167
  output.each do |thread|
157
- thread[:stop] = false
158
- puts "writing to device '#{id}': #{thread[:data].class}" if Sound.verbose
159
- thread.run
168
+ finish_up(thread)
160
169
  end
161
170
  output.last.join if output.last.alive?
162
171
  end
163
172
  end
164
173
  end
165
174
 
175
+ # works like #flush, but empties the buffer without playing any sounds and
176
+ # closes the physical device as quickly as possible for its platform.
177
+ #
178
+ def flush!
179
+ @queue = Device::Buffer.new
180
+ self
181
+ end
182
+
166
183
  private
167
184
 
168
185
  def write_thread
169
186
  Thread.current[:stop] = true if Thread.current[:stop].nil?
170
187
  if Sound.platform_supported
171
- open_device
172
- prepare_buffer
173
- Thread.stop if Thread.current[:stop]
174
- Thread.pass if Thread.current[:async]
188
+ set_up
175
189
  write_to_device
176
- unprepare_buffer
177
- close_device
190
+ tear_down
178
191
  else
179
192
  warn("warning: playback is not yet supported on this platform")
180
193
  end
181
194
  end
195
+
196
+ def set_up
197
+ open_device(self)
198
+ prepare_buffer
199
+ Thread.stop if Thread.current[:stop]
200
+ Thread.pass if Thread.current[:async]
201
+ end
202
+
203
+ def tear_down
204
+ unprepare_buffer
205
+ close_device
206
+ end
207
+
208
+ def new_async_thread_for(data)
209
+ Thread.new do
210
+ Thread.current[:async] = true
211
+ Thread.current[:data] = data
212
+ write_thread
213
+ end
214
+ end
215
+
216
+ def finish_up(thread)
217
+ thread[:stop] = false
218
+ puts "writing to device '#{id}': #{thread[:data].class}" if Sound.verbose #this may be NilClass if parent thread is too fast
219
+ thread.run
220
+ end
182
221
  end
183
222
 
184
223
  end
@@ -0,0 +1,19 @@
1
+ require 'forwardable'
2
+
3
+ module Sound
4
+ module DeviceLibrary
5
+ extend Forwardable
6
+ DEFAULT_DEVICE_ID = Sound.device_library::DEFAULT_DEVICE_ID
7
+ duties = [
8
+ :open_device,
9
+ :prepare_buffer,
10
+ :write_to_device,
11
+ :unprepare_buffer,
12
+ :close_device
13
+ ]
14
+ duties.each do |duty|
15
+ delegate duty => Sound.device_library
16
+ private duty
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,240 @@
1
+ require 'ffi'
2
+
3
+ module Sound
4
+ module DeviceLibrary
5
+ module ALSA
6
+ extend self
7
+
8
+ class Handle
9
+ def initialize
10
+ @handle = FFI::MemoryPointer.new(:pointer)
11
+ end
12
+ def pointer
13
+ @handle
14
+ end
15
+ def id
16
+ @handle.read_pointer
17
+ end
18
+ end
19
+
20
+ SND_PCM_STREAM_PLAYBACK = 0
21
+ SND_PCM_STREAM_CAPTURE = 1
22
+ DEFAULT_DEVICE_ID = "default"
23
+
24
+ extend FFI::Library
25
+ ffi_lib 'asound'
26
+ ffi_convention :stdcall
27
+
28
+ attach_function :snd_pcm_open, [:pointer, :string, :int, :int], :int
29
+ attach_function :snd_pcm_close, [:pointer], :int
30
+ attach_function :snd_pcm_drain, [:pointer], :int
31
+ attach_function :snd_pcm_prepare, [:pointer], :int
32
+ attach_function :write_noninterleaved, :snd_pcm_writen, [:pointer, :pointer, :ulong], :long
33
+ attach_function :snd_pcm_writei, [:pointer, :pointer, :ulong], :long
34
+ attach_function :snd_pcm_hw_params_malloc, [:pointer], :int
35
+ attach_function :snd_pcm_hw_params_any, [:pointer, :pointer], :int
36
+ attach_function :snd_pcm_hw_params_set_access, [:pointer, :pointer, :int], :int
37
+ attach_function :snd_pcm_hw_params_set_format, [:pointer, :pointer, :int], :int
38
+ attach_function :snd_pcm_hw_params_set_rate, [:pointer, :pointer, :uint, :int], :int
39
+ attach_function :snd_pcm_hw_params_set_channels, [:pointer, :pointer, :int], :int
40
+ attach_function :snd_pcm_hw_params, [:pointer, :pointer], :int
41
+ attach_function :snd_pcm_hw_params_free, [:pointer], :void
42
+
43
+ def self.snd_pcm_open(*args)
44
+ output = `aplay -l 2>&1`
45
+ if output.match(/no soundcard/m)
46
+ raise NoDeviceError, "No sound devices present"
47
+ elsif output.match(/not found/m)
48
+ raise NoDependencyError,
49
+ "aplay is not present in your environment. Install alsa-utils package for audio playback."
50
+ else
51
+ snd_pcm_open(*args)
52
+ end
53
+ end
54
+
55
+ def open_device(device)
56
+ begin
57
+ self.snd_pcm_open(handle.pointer, device.id, 0, ASYNC)
58
+ rescue NoDeviceError
59
+ Sound.no_device = true
60
+ end
61
+ end
62
+
63
+ def prepare_buffer
64
+
65
+ unless Sound.no_device
66
+ buffer_length
67
+ set_params
68
+ snd_pcm_prepare(handle.id)
69
+ end
70
+
71
+ end
72
+
73
+ def write_to_device
74
+ snd_pcm_writei(handle.id, data_buffer, buffer_length) unless Sound.no_device
75
+ end
76
+
77
+ def unprepare_buffer
78
+ snd_pcm_drain(handle.id) unless Sound.no_device
79
+ end
80
+
81
+ def close_device
82
+ snd_pcm_close(handle.id) unless Sound.no_device
83
+ end
84
+
85
+ def params_handle
86
+ Thread.current[:params_handle] ||= Handle.new
87
+ end
88
+
89
+ def buffer_length
90
+ Thread.current[:buffer_length] ||= data_buffer.size/2
91
+ end
92
+
93
+ def handle
94
+ Thread.current[:handle] ||= Handle.new
95
+ end
96
+
97
+ def data
98
+ Thread.current[:data] ||= Sound::Data.new
99
+ end
100
+
101
+ def data_buffer
102
+ Thread.current[:data_buffer] ||= FFI::MemoryPointer.new(:int, data.pcm_data.size).write_array_of_int data.pcm_data
103
+ end
104
+
105
+ def set_params
106
+ allocate_param_memory
107
+ alter_allocated_param_memory
108
+ free_param_memory
109
+ end
110
+
111
+ def allocate_param_memory
112
+ snd_pcm_hw_params_malloc(params_handle.pointer)
113
+ end
114
+
115
+ def free_param_memory
116
+ snd_pcm_hw_params_free(params_handle.id)
117
+ end
118
+
119
+ def alter_allocated_param_memory
120
+ set_up_to_change_any_params
121
+ modify_desired_params
122
+ set_params_on_hw_buffer
123
+ end
124
+
125
+ def set_up_to_change_any_params
126
+ snd_pcm_hw_params_any(handle.id, params_handle.id)
127
+ end
128
+
129
+ def modify_desired_params
130
+ # I think these can happen in any order
131
+ snd_pcm_hw_params_set_access(handle.id, params_handle.id, SND_PCM_ACCESS_RW_INTERLEAVED)
132
+ snd_pcm_hw_params_set_format(handle.id, params_handle.id, SND_PCM_FORMAT_S16_LE)
133
+ # need to change this to set_rate_near at some point
134
+ snd_pcm_hw_params_set_rate(handle.id, params_handle.id, data.format.sample_rate, 0)
135
+ snd_pcm_hw_params_set_channels(handle.id, params_handle.id, data.format.channels)
136
+ end
137
+
138
+ def set_params_on_hw_buffer
139
+ snd_pcm_hw_params(handle.id, params_handle.id)
140
+ end
141
+
142
+ SND_PCM_ASYNC = 2
143
+ ASYNC = SND_PCM_ASYNC
144
+ #snd_pcm formats
145
+ # Unknown
146
+ SND_PCM_FORMAT_UNKNOWN = -1
147
+ # Signed 8 bit
148
+ SND_PCM_FORMAT_S8 = 0
149
+ # Unsigned 8 bit
150
+ SND_PCM_FORMAT_U8 = 1
151
+ # Signed 16 bit Little Endian
152
+ SND_PCM_FORMAT_S16_LE = 2
153
+ # Signed 16 bit Big Endian
154
+ SND_PCM_FORMAT_S16_BE = 3
155
+ # Unsigned 16 bit Little Endian
156
+ SND_PCM_FORMAT_U16_LE = 4
157
+ # Unsigned 16 bit Big Endian
158
+ SND_PCM_FORMAT_U16_BE = 5
159
+ # Signed 24 bit Little Endian using low three bytes in 32-bit word
160
+ SND_PCM_FORMAT_S24_LE = 6
161
+ # Signed 24 bit Big Endian using low three bytes in 32-bit word
162
+ SND_PCM_FORMAT_S24_BE = 7
163
+ # Unsigned 24 bit Little Endian using low three bytes in 32-bit word
164
+ SND_PCM_FORMAT_U24_LE = 8
165
+ # Unsigned 24 bit Big Endian using low three bytes in 32-bit word
166
+ SND_PCM_FORMAT_U24_BE = 9
167
+ # Signed 32 bit Little Endian
168
+ SND_PCM_FORMAT_S32_LE = 10
169
+ # Signed 32 bit Big Endian
170
+ SND_PCM_FORMAT_S32_BE = 11
171
+ # Unsigned 32 bit Little Endian
172
+ SND_PCM_FORMAT_U32_LE = 12
173
+ # Unsigned 32 bit Big Endian
174
+ SND_PCM_FORMAT_U32_BE = 13
175
+ # Float 32 bit Little Endian, Range -1.0 to 1.0
176
+ SND_PCM_FORMAT_FLOAT_LE = 14
177
+ # Float 32 bit Big Endian, Range -1.0 to 1.0
178
+ SND_PCM_FORMAT_FLOAT_BE = 15
179
+ # Float 64 bit Little Endian, Range -1.0 to 1.0
180
+ SND_PCM_FORMAT_FLOAT64_LE = 16
181
+ # Float 64 bit Big Endian, Range -1.0 to 1.0
182
+ SND_PCM_FORMAT_FLOAT64_BE = 17
183
+ # IEC-958 Little Endian
184
+ SND_PCM_FORMAT_IEC958_SUBFRAME_LE = 18
185
+ # IEC-958 Big Endian
186
+ SND_PCM_FORMAT_IEC958_SUBFRAME_BE = 19
187
+ # Mu-Law
188
+ SND_PCM_FORMAT_MU_LAW = 20
189
+ # A-Law
190
+ SND_PCM_FORMAT_A_LAW = 21
191
+ # Ima-ADPCM
192
+ SND_PCM_FORMAT_IMA_ADPCM = 22
193
+ # MPEG
194
+ SND_PCM_FORMAT_MPEG = 23
195
+ # GSM
196
+ SND_PCM_FORMAT_GSM = 24
197
+ # Special
198
+ SND_PCM_FORMAT_SPECIAL = 31
199
+ # Signed 24bit Little Endian in 3bytes format
200
+ SND_PCM_FORMAT_S24_3LE = 32
201
+ # Signed 24bit Big Endian in 3bytes format
202
+ SND_PCM_FORMAT_S24_3BE = 33
203
+ # Unsigned 24bit Little Endian in 3bytes format
204
+ SND_PCM_FORMAT_U24_3LE = 34
205
+ # Unsigned 24bit Big Endian in 3bytes format
206
+ SND_PCM_FORMAT_U24_3BE = 35
207
+ # Signed 20bit Little Endian in 3bytes format
208
+ SND_PCM_FORMAT_S20_3LE = 36
209
+ # Signed 20bit Big Endian in 3bytes format
210
+ SND_PCM_FORMAT_S20_3BE = 37
211
+ # Unsigned 20bit Little Endian in 3bytes format
212
+ SND_PCM_FORMAT_U20_3LE = 38
213
+ # Unsigned 20bit Big Endian in 3bytes format
214
+ SND_PCM_FORMAT_U20_3BE = 39
215
+ # Signed 18bit Little Endian in 3bytes format
216
+ SND_PCM_FORMAT_S18_3LE = 40
217
+ # Signed 18bit Big Endian in 3bytes format
218
+ SND_PCM_FORMAT_S18_3BE = 41
219
+ # Unsigned 18bit Little Endian in 3bytes format
220
+ SND_PCM_FORMAT_U18_3LE = 42
221
+ # Unsigned 18bit Big Endian in 3bytes format
222
+ SND_PCM_FORMAT_U18_3BE = 43
223
+ SND_PCM_FORMAT_LAST = SND_PCM_FORMAT_U18_3BE
224
+
225
+ #snd_pcm access
226
+ # mmap access with simple interleaved channels
227
+ SND_PCM_ACCESS_MMAP_INTERLEAVED = 0
228
+ # mmap access with simple non interleaved channels
229
+ SND_PCM_ACCESS_MMAP_NONINTERLEAVED = 1
230
+ # mmap access with complex placement
231
+ SND_PCM_ACCESS_MMAP_COMPLEX = 2
232
+ # snd_pcm_readi/snd_pcm_writei access
233
+ SND_PCM_ACCESS_RW_INTERLEAVED = 3
234
+ # snd_pcm_readn/snd_pcm_writen access
235
+ SND_PCM_ACCESS_RW_NONINTERLEAVED = 4
236
+ SND_PCM_ACCESS_LAST = SND_PCM_ACCESS_RW_NONINTERLEAVED
237
+
238
+ end
239
+ end
240
+ end