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.
@@ -1,211 +0,0 @@
1
- require 'ffi'
2
-
3
- module Sound
4
- module ALSA
5
-
6
- class Handle
7
- def initialize
8
- @handle = FFI::MemoryPointer.new(:pointer)
9
- end
10
- def pointer
11
- @handle
12
- end
13
- def id
14
- @handle.read_pointer
15
- end
16
- end
17
-
18
- SND_PCM_STREAM_PLAYBACK = 0
19
- SND_PCM_STREAM_CAPTURE = 1
20
- DEFAULT_DEVICE_ID = "default"
21
-
22
- extend FFI::Library
23
- ffi_lib 'asound'
24
- ffi_convention :stdcall
25
-
26
- attach_function :snd_pcm_open, [:pointer, :string, :int, :int], :int
27
- attach_function :snd_pcm_close, [:pointer], :int
28
- attach_function :snd_pcm_drain, [:pointer], :int
29
- attach_function :snd_pcm_prepare, [:pointer], :int
30
- attach_function :write_noninterleaved, :snd_pcm_writen, [:pointer, :pointer, :ulong], :long
31
- attach_function :snd_pcm_writei, [:pointer, :pointer, :ulong], :long
32
- attach_function :snd_pcm_hw_params_malloc, [:pointer], :int
33
- attach_function :snd_pcm_hw_params_any, [:pointer, :pointer], :int
34
- attach_function :snd_pcm_hw_params_set_access, [:pointer, :pointer, :int], :int
35
- attach_function :snd_pcm_hw_params_set_format, [:pointer, :pointer, :int], :int
36
- attach_function :snd_pcm_hw_params_set_rate, [:pointer, :pointer, :uint, :int], :int
37
- attach_function :snd_pcm_hw_params_set_channels, [:pointer, :pointer, :int], :int
38
- attach_function :snd_pcm_hw_params, [:pointer, :pointer], :int
39
- attach_function :snd_pcm_hw_params_free, [:pointer], :void
40
-
41
- def snd_pcm_open(*args)
42
- output = `aplay -l 2>&1`
43
- if output.match(/no soundcard/m)
44
- raise NoDeviceError, "No sound devices present"
45
- elsif output.match(/not found/m)
46
- raise NoDependencyError, "aplay is not present in your environment. Install alsa-utils package for audio playback."
47
- else
48
- snd_pcm_open(*args)
49
- end
50
- end
51
-
52
- def open_device
53
- begin
54
- snd_pcm_open(handle.pointer, id, 0, ASYNC)
55
- rescue NoDeviceError
56
- Sound.no_device = true
57
- end
58
- end
59
-
60
- def prepare_buffer
61
-
62
- unless Sound.no_device
63
- buffer_length
64
-
65
- snd_pcm_hw_params_malloc(params_handle.pointer)
66
- snd_pcm_hw_params_any(handle.id, params_handle.id)
67
-
68
- snd_pcm_hw_params_set_access(handle.id, params_handle.id, SND_PCM_ACCESS_RW_INTERLEAVED)
69
- set_formsnd_pcm_hw_params_set_formatat(handle.id, params_handle.id, SND_PCM_FORMAT_S16_LE)
70
- # need to change this to set_rate_near at some point
71
- snd_pcm_hw_params_set_rate(handle.id, params_handle.id, data.format.sample_rate, 0)
72
- snd_pcm_hw_params_set_channels(handle.id, params_handle.id, 1)
73
-
74
- snd_pcm_hw_params(handle.id, params_handle.id)
75
- snd_pcm_hw_params_free(params_handle.id)
76
-
77
- snd_pcm_prepare(handle.id)
78
- end
79
-
80
- end
81
-
82
- def write_to_device
83
- snd_pcm_writei(handle.id, data_buffer, buffer_length) unless Sound.no_device
84
- end
85
-
86
- def unprepare_buffer
87
- snd_pcm_drain(handle.id) unless Sound.no_device
88
- end
89
-
90
- def close_device
91
- snd_pcm_close(handle.id) unless Sound.no_device
92
- end
93
-
94
- def handle
95
- Thread.current[:handle] ||= Handle.new
96
- end
97
-
98
- def params_handle
99
- Thread.current[:params_handle] ||= Handle.new
100
- end
101
-
102
- def data
103
- Thread.current[:data]
104
- end
105
-
106
- def data_buffer
107
- Thread.current[:data_buffer] ||= FFI::MemoryPointer.new(:int, data.pcm_data.size).write_array_of_int data.pcm_data
108
- end
109
-
110
- def buffer_length
111
- Thread.current[:buffer_length] ||= data_buffer.size/2
112
- end
113
-
114
- SND_PCM_ASYNC = 2
115
- ASYNC = SND_PCM_ASYNC
116
- #snd_pcm formats
117
- # Unknown
118
- SND_PCM_FORMAT_UNKNOWN = -1
119
- # Signed 8 bit
120
- SND_PCM_FORMAT_S8 = 0
121
- # Unsigned 8 bit
122
- SND_PCM_FORMAT_U8 = 1
123
- # Signed 16 bit Little Endian
124
- SND_PCM_FORMAT_S16_LE = 2
125
- # Signed 16 bit Big Endian
126
- SND_PCM_FORMAT_S16_BE = 3
127
- # Unsigned 16 bit Little Endian
128
- SND_PCM_FORMAT_U16_LE = 4
129
- # Unsigned 16 bit Big Endian
130
- SND_PCM_FORMAT_U16_BE = 5
131
- # Signed 24 bit Little Endian using low three bytes in 32-bit word
132
- SND_PCM_FORMAT_S24_LE = 6
133
- # Signed 24 bit Big Endian using low three bytes in 32-bit word
134
- SND_PCM_FORMAT_S24_BE = 7
135
- # Unsigned 24 bit Little Endian using low three bytes in 32-bit word
136
- SND_PCM_FORMAT_U24_LE = 8
137
- # Unsigned 24 bit Big Endian using low three bytes in 32-bit word
138
- SND_PCM_FORMAT_U24_BE = 9
139
- # Signed 32 bit Little Endian
140
- SND_PCM_FORMAT_S32_LE = 10
141
- # Signed 32 bit Big Endian
142
- SND_PCM_FORMAT_S32_BE = 11
143
- # Unsigned 32 bit Little Endian
144
- SND_PCM_FORMAT_U32_LE = 12
145
- # Unsigned 32 bit Big Endian
146
- SND_PCM_FORMAT_U32_BE = 13
147
- # Float 32 bit Little Endian, Range -1.0 to 1.0
148
- SND_PCM_FORMAT_FLOAT_LE = 14
149
- # Float 32 bit Big Endian, Range -1.0 to 1.0
150
- SND_PCM_FORMAT_FLOAT_BE = 15
151
- # Float 64 bit Little Endian, Range -1.0 to 1.0
152
- SND_PCM_FORMAT_FLOAT64_LE = 16
153
- # Float 64 bit Big Endian, Range -1.0 to 1.0
154
- SND_PCM_FORMAT_FLOAT64_BE = 17
155
- # IEC-958 Little Endian
156
- SND_PCM_FORMAT_IEC958_SUBFRAME_LE = 18
157
- # IEC-958 Big Endian
158
- SND_PCM_FORMAT_IEC958_SUBFRAME_BE = 19
159
- # Mu-Law
160
- SND_PCM_FORMAT_MU_LAW = 20
161
- # A-Law
162
- SND_PCM_FORMAT_A_LAW = 21
163
- # Ima-ADPCM
164
- SND_PCM_FORMAT_IMA_ADPCM = 22
165
- # MPEG
166
- SND_PCM_FORMAT_MPEG = 23
167
- # GSM
168
- SND_PCM_FORMAT_GSM = 24
169
- # Special
170
- SND_PCM_FORMAT_SPECIAL = 31
171
- # Signed 24bit Little Endian in 3bytes format
172
- SND_PCM_FORMAT_S24_3LE = 32
173
- # Signed 24bit Big Endian in 3bytes format
174
- SND_PCM_FORMAT_S24_3BE = 33
175
- # Unsigned 24bit Little Endian in 3bytes format
176
- SND_PCM_FORMAT_U24_3LE = 34
177
- # Unsigned 24bit Big Endian in 3bytes format
178
- SND_PCM_FORMAT_U24_3BE = 35
179
- # Signed 20bit Little Endian in 3bytes format
180
- SND_PCM_FORMAT_S20_3LE = 36
181
- # Signed 20bit Big Endian in 3bytes format
182
- SND_PCM_FORMAT_S20_3BE = 37
183
- # Unsigned 20bit Little Endian in 3bytes format
184
- SND_PCM_FORMAT_U20_3LE = 38
185
- # Unsigned 20bit Big Endian in 3bytes format
186
- SND_PCM_FORMAT_U20_3BE = 39
187
- # Signed 18bit Little Endian in 3bytes format
188
- SND_PCM_FORMAT_S18_3LE = 40
189
- # Signed 18bit Big Endian in 3bytes format
190
- SND_PCM_FORMAT_S18_3BE = 41
191
- # Unsigned 18bit Little Endian in 3bytes format
192
- SND_PCM_FORMAT_U18_3LE = 42
193
- # Unsigned 18bit Big Endian in 3bytes format
194
- SND_PCM_FORMAT_U18_3BE = 43
195
- SND_PCM_FORMAT_LAST = SND_PCM_FORMAT_U18_3BE
196
-
197
- #snd_pcm access
198
- # mmap access with simple interleaved channels
199
- SND_PCM_ACCESS_MMAP_INTERLEAVED = 0
200
- # mmap access with simple non interleaved channels
201
- SND_PCM_ACCESS_MMAP_NONINTERLEAVED = 1
202
- # mmap access with complex placement
203
- SND_PCM_ACCESS_MMAP_COMPLEX = 2
204
- # snd_pcm_readi/snd_pcm_writei access
205
- SND_PCM_ACCESS_RW_INTERLEAVED = 3
206
- # snd_pcm_readn/snd_pcm_writen access
207
- SND_PCM_ACCESS_RW_NONINTERLEAVED = 4
208
- SND_PCM_ACCESS_LAST = SND_PCM_ACCESS_RW_NONINTERLEAVED
209
-
210
- end
211
- end
@@ -1,150 +0,0 @@
1
- require 'ffi'
2
-
3
- module Sound
4
- module Win32
5
-
6
- class Handle
7
- def initialize
8
- @handle = HWAVEOUT.new
9
- end
10
- def pointer
11
- @handle.pointer
12
- end
13
- def id
14
- @handle[:i]
15
- end
16
- end
17
-
18
- extend FFI::Library
19
-
20
- typedef :ulong, :dword
21
- typedef :uintptr_t, :hwaveout
22
- typedef :uint, :mmresult
23
-
24
- ffi_lib :winmm
25
-
26
- attach_function :waveOutOpen, [:pointer, :uint, :pointer, :dword, :dword, :dword], :mmresult
27
- attach_function :waveOutPrepareHeader, [:hwaveout, :pointer, :uint], :mmresult
28
- attach_function :waveOutWrite, [:hwaveout, :pointer, :uint], :mmresult
29
- attach_function :waveOutUnprepareHeader, [:hwaveout, :pointer, :uint], :mmresult
30
- attach_function :waveOutClose, [:hwaveout], :mmresult
31
-
32
- WAVE_FORMAT_PCM = 1
33
- WAVE_MAPPER = -1
34
- DEFAULT_DEVICE_ID = WAVE_MAPPER
35
-
36
- def open_device
37
- waveOutOpen(handle.pointer, id, data.format.pointer, 0, 0, 0)
38
- end
39
-
40
- def prepare_buffer
41
- waveOutPrepareHeader(handle.id, header.pointer, header.size)
42
- end
43
-
44
- def write_to_device
45
- waveOutWrite(handle.id, header.pointer, header.size)
46
- end
47
-
48
- def unprepare_buffer
49
- while waveOutUnprepareHeader(handle.id, header.pointer, header.size) == 33
50
- sleep 0.001
51
- end
52
- end
53
-
54
- def close_device
55
- waveOutClose(handle.id)
56
- end
57
-
58
- def handle
59
- Thread.current[:handle] ||= Handle.new
60
- end
61
-
62
- def data
63
- Thread.current[:data]
64
- end
65
-
66
- def header
67
- Thread.current[:header] ||= WAVEHDR.new(data_buffer, buffer_length)
68
- end
69
-
70
- def data_buffer
71
- Thread.current[:data_buffer] ||= FFI::MemoryPointer.new(:int, data.pcm_data.size).write_array_of_int data.pcm_data
72
- end
73
-
74
- def buffer_length
75
- Thread.current[:buffer_length] ||= data.format.avg_bps*data.duration/1000
76
- end
77
-
78
- # Define an HWAVEOUT struct for use by all the waveOut functions.
79
- # It is a handle to a waveOut stream, so starting up multiple
80
- # streams using different handles allows for simultaneous playback.
81
- # You never need to actually look at the struct, C takes care of
82
- # its value.
83
- #
84
- class HWAVEOUT < FFI::Struct
85
- layout :i, :int
86
- end
87
-
88
- # Define WAVEFORMATEX which defines the format (PCM in this case)
89
- # and various properties like sampling rate, number of channels, etc.
90
- #
91
- class WAVEFORMATEX < FFI::Struct
92
-
93
- # Initializes struct with sensible defaults for most commonly used
94
- # values. While setting these manually is possible, please be
95
- # sure you know what changes will result in, as an incorrectly
96
- # set struct will result in unpredictable behavior.
97
- #
98
- def initialize(nSamplesPerSec = 44100, wBitsPerSample = 16, nChannels = 1, cbSize = 0)
99
- self[:wFormatTag] = WAVE_FORMAT_PCM
100
- self[:nChannels] = nChannels
101
- self[:nSamplesPerSec] = nSamplesPerSec
102
- self[:wBitsPerSample] = wBitsPerSample
103
- self[:cbSize] = cbSize
104
- self[:nBlockAlign] = (self[:wBitsPerSample] >> 3) * self[:nChannels]
105
- self[:nAvgBytesPerSec] = self[:nBlockAlign] * self[:nSamplesPerSec]
106
- end
107
-
108
- layout(
109
- :wFormatTag, :ushort,
110
- :nChannels, :ushort,
111
- :nSamplesPerSec, :ulong,
112
- :nAvgBytesPerSec, :ulong,
113
- :nBlockAlign, :ushort,
114
- :wBitsPerSample, :ushort,
115
- :cbSize, :ushort
116
- )
117
- end
118
-
119
- #define WAVEHDR which is a header to a block of audio
120
- #lpData is a pointer to the block of native memory that,
121
- # in this case, is an integer array of PCM data
122
-
123
- class WAVEHDR < FFI::Struct
124
-
125
- # Initializes struct with sensible defaults for most commonly used
126
- # values. While setting these manually is possible, please be
127
- # sure you know what changes will result in, as an incorrectly
128
- # set struct will result in unpredictable behavior.
129
- #
130
- def initialize(lpData, dwBufferLength, dwFlags = 0, dwLoops = 1)
131
- self[:lpData] = lpData
132
- self[:dwBufferLength] = dwBufferLength
133
- self[:dwFlags] = dwFlags
134
- self[:dwLoops] = dwLoops
135
- end
136
-
137
- layout(
138
- :lpData, :pointer,
139
- :dwBufferLength, :ulong,
140
- :dwBytesRecorded, :ulong,
141
- :dwUser, :ulong,
142
- :dwFlags, :ulong,
143
- :dwLoops, :ulong,
144
- :lpNext, :pointer,
145
- :reserved, :ulong
146
- )
147
- end
148
-
149
- end
150
- end