sound 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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