libsamplerate 0.0.1

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
+ SHA256:
3
+ metadata.gz: ee15d47be4e3b7cc4d7ed3e0655c1b7ca2fdcb6e48d93dd3ed80ad7778924595
4
+ data.tar.gz: '04119ee09a4fe0fbeb01cd67c311c88361973c4db495303b821c42020d948139'
5
+ SHA512:
6
+ metadata.gz: e7bb7f868cf5c609d79fa4a63e68611256cc636f9ae52ca2da7ddb99d771b338d120b84b34ea6bcfcab0c4845bf1954f2de454e00d8376c9283e131f4acb3ae8
7
+ data.tar.gz: '0940cac612bec8ed28aa55a0516af6ec42d8eeda90599f2075ade3cfdffb926fe032dd3fdaf8af2316ab3896529fd87129a2ca853a927d94eb61e726d789b72a'
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'libc', git: 'https://github.com/shamangeorge/libc.git', branch: 'master'
4
+ gemspec
@@ -0,0 +1,177 @@
1
+ Copyright (C) 2016 shamangeorge
2
+
3
+ This library is free software; you can redistribute it and/or
4
+ modify it under the terms of the GNU Lesser General Public
5
+ License as published by the Free Software Foundation; either
6
+ version 3.0 of the License, or (at your option) any later version.
7
+
8
+ This library is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ Lesser General Public License for more details.
12
+
13
+ GNU LESSER GENERAL PUBLIC LICENSE
14
+ Version 3, 29 June 2007
15
+
16
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
17
+ Everyone is permitted to copy and distribute verbatim copies
18
+ of this license document, but changing it is not allowed.
19
+
20
+
21
+ This version of the GNU Lesser General Public License incorporates
22
+ the terms and conditions of version 3 of the GNU General Public
23
+ License, supplemented by the additional permissions listed below.
24
+
25
+ 0. Additional Definitions.
26
+
27
+ As used herein, "this License" refers to version 3 of the GNU Lesser
28
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
29
+ General Public License.
30
+
31
+ "The Library" refers to a covered work governed by this License,
32
+ other than an Application or a Combined Work as defined below.
33
+
34
+ An "Application" is any work that makes use of an interface provided
35
+ by the Library, but which is not otherwise based on the Library.
36
+ Defining a subclass of a class defined by the Library is deemed a mode
37
+ of using an interface provided by the Library.
38
+
39
+ A "Combined Work" is a work produced by combining or linking an
40
+ Application with the Library. The particular version of the Library
41
+ with which the Combined Work was made is also called the "Linked
42
+ Version".
43
+
44
+ The "Minimal Corresponding Source" for a Combined Work means the
45
+ Corresponding Source for the Combined Work, excluding any source code
46
+ for portions of the Combined Work that, considered in isolation, are
47
+ based on the Application, and not on the Linked Version.
48
+
49
+ The "Corresponding Application Code" for a Combined Work means the
50
+ object code and/or source code for the Application, including any data
51
+ and utility programs needed for reproducing the Combined Work from the
52
+ Application, but excluding the System Libraries of the Combined Work.
53
+
54
+ 1. Exception to Section 3 of the GNU GPL.
55
+
56
+ You may convey a covered work under sections 3 and 4 of this License
57
+ without being bound by section 3 of the GNU GPL.
58
+
59
+ 2. Conveying Modified Versions.
60
+
61
+ If you modify a copy of the Library, and, in your modifications, a
62
+ facility refers to a function or data to be supplied by an Application
63
+ that uses the facility (other than as an argument passed when the
64
+ facility is invoked), then you may convey a copy of the modified
65
+ version:
66
+
67
+ a) under this License, provided that you make a good faith effort to
68
+ ensure that, in the event an Application does not supply the
69
+ function or data, the facility still operates, and performs
70
+ whatever part of its purpose remains meaningful, or
71
+
72
+ b) under the GNU GPL, with none of the additional permissions of
73
+ this License applicable to that copy.
74
+
75
+ 3. Object Code Incorporating Material from Library Header Files.
76
+
77
+ The object code form of an Application may incorporate material from
78
+ a header file that is part of the Library. You may convey such object
79
+ code under terms of your choice, provided that, if the incorporated
80
+ material is not limited to numerical parameters, data structure
81
+ layouts and accessors, or small macros, inline functions and templates
82
+ (ten or fewer lines in length), you do both of the following:
83
+
84
+ a) Give prominent notice with each copy of the object code that the
85
+ Library is used in it and that the Library and its use are
86
+ covered by this License.
87
+
88
+ b) Accompany the object code with a copy of the GNU GPL and this license
89
+ document.
90
+
91
+ 4. Combined Works.
92
+
93
+ You may convey a Combined Work under terms of your choice that,
94
+ taken together, effectively do not restrict modification of the
95
+ portions of the Library contained in the Combined Work and reverse
96
+ engineering for debugging such modifications, if you also do each of
97
+ the following:
98
+
99
+ a) Give prominent notice with each copy of the Combined Work that
100
+ the Library is used in it and that the Library and its use are
101
+ covered by this License.
102
+
103
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
104
+ document.
105
+
106
+ c) For a Combined Work that displays copyright notices during
107
+ execution, include the copyright notice for the Library among
108
+ these notices, as well as a reference directing the user to the
109
+ copies of the GNU GPL and this license document.
110
+
111
+ d) Do one of the following:
112
+
113
+ 0) Convey the Minimal Corresponding Source under the terms of this
114
+ License, and the Corresponding Application Code in a form
115
+ suitable for, and under terms that permit, the user to
116
+ recombine or relink the Application with a modified version of
117
+ the Linked Version to produce a modified Combined Work, in the
118
+ manner specified by section 6 of the GNU GPL for conveying
119
+ Corresponding Source.
120
+
121
+ 1) Use a suitable shared library mechanism for linking with the
122
+ Library. A suitable mechanism is one that (a) uses at run time
123
+ a copy of the Library already present on the user's computer
124
+ system, and (b) will operate properly with a modified version
125
+ of the Library that is interface-compatible with the Linked
126
+ Version.
127
+
128
+ e) Provide Installation Information, but only if you would otherwise
129
+ be required to provide such information under section 6 of the
130
+ GNU GPL, and only to the extent that such information is
131
+ necessary to install and execute a modified version of the
132
+ Combined Work produced by recombining or relinking the
133
+ Application with a modified version of the Linked Version. (If
134
+ you use option 4d0, the Installation Information must accompany
135
+ the Minimal Corresponding Source and Corresponding Application
136
+ Code. If you use option 4d1, you must provide the Installation
137
+ Information in the manner specified by section 6 of the GNU GPL
138
+ for conveying Corresponding Source.)
139
+
140
+ 5. Combined Libraries.
141
+
142
+ You may place library facilities that are a work based on the
143
+ Library side by side in a single library together with other library
144
+ facilities that are not Applications and are not covered by this
145
+ License, and convey such a combined library under terms of your
146
+ choice, if you do both of the following:
147
+
148
+ a) Accompany the combined library with a copy of the same work based
149
+ on the Library, uncombined with any other library facilities,
150
+ conveyed under the terms of this License.
151
+
152
+ b) Give prominent notice with the combined library that part of it
153
+ is a work based on the Library, and explaining where to find the
154
+ accompanying uncombined form of the same work.
155
+
156
+ 6. Revised Versions of the GNU Lesser General Public License.
157
+
158
+ The Free Software Foundation may publish revised and/or new versions
159
+ of the GNU Lesser General Public License from time to time. Such new
160
+ versions will be similar in spirit to the present version, but may
161
+ differ in detail to address new problems or concerns.
162
+
163
+ Each version is given a distinguishing version number. If the
164
+ Library as you received it specifies that a certain numbered version
165
+ of the GNU Lesser General Public License "or any later version"
166
+ applies to it, you have the option of following the terms and
167
+ conditions either of that published version or of any later version
168
+ published by the Free Software Foundation. If the Library as you
169
+ received it does not specify a version number of the GNU Lesser
170
+ General Public License, you may choose any version of the GNU Lesser
171
+ General Public License ever published by the Free Software Foundation.
172
+
173
+ If the Library as you received it specifies that a proxy can decide
174
+ whether future versions of the GNU Lesser General Public License shall
175
+ apply, that proxy's public statement of acceptance of any version is
176
+ permanent authorization for you to choose that version for the
177
+ Library.
@@ -0,0 +1,4 @@
1
+ # libsamplerate
2
+
3
+ [![pipeline status](https://damos.fruitopology.net/gems/libsamplerate/badges/master/pipeline.svg)](https://damos.fruitopology.net/gems/libsamplerate/commits/master)
4
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "libsamplerate"
5
+ require "pry"
6
+ Pry.start
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+ bundle install
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "ffi_gen"
4
+
5
+ # Install libsamplerate from meganerd.com
6
+ # and add it to you LD_LIBRARY_PATH
7
+
8
+ FFIGen.generate(
9
+ module_name: "Libsamplerate::FFI",
10
+ ffi_lib: "libsamplerate",
11
+ headers: ["samplerate.h"],
12
+ cflags: [],
13
+ prefixes: [],
14
+ output: "lib/libsamplerate/ffi.rb"
15
+ )
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "ruby-audio"
4
+ require "libsamplerate"
5
+
6
+ puts "================================="
7
+ puts "Version:"
8
+ puts Libsamplerate::FFI.src_get_version
9
+ puts "================================="
10
+ puts "Available Converters"
11
+ (0..4).each do |i|
12
+ puts "=-=-=-=-=-=-=-="
13
+ puts Libsamplerate::FFI.src_get_name(i)
14
+ puts Libsamplerate::FFI.src_get_description(i)
15
+ end
16
+ puts "================================="
17
+
18
+ out_dir = "."
19
+ out_dir = "/home/pikos/Dropbox"
20
+ file_name = "vagelis.wav"
21
+ file_path = "#{out_dir}/#{file_name}"
22
+ buffer = []
23
+ RubyAudio::Sound.open(file_path) do |snd|
24
+ snd.read(:float, snd.info.frames).each do |sample|
25
+ buffer.push((sample[0] + sample[1]) / 2)
26
+ end
27
+ end
28
+
29
+ error_ptr = FFI::MemoryPointer.new :int
30
+ converter = 0
31
+ channels = 1
32
+ src_state = Libsamplerate::FFI.src_new(
33
+ converter,
34
+ channels,
35
+ error_ptr
36
+ )
37
+
38
+ slice = 4096
39
+ all_data = []
40
+ buffer.each_slice(slice) do |input|
41
+ num_samples = input.size
42
+ in_ptr = FFI::MemoryPointer.new :float, input.size
43
+ in_ptr.write_array_of_float input
44
+ outbuffer = FFI::MemoryPointer.new :float, num_samples
45
+
46
+ src_data = Libsamplerate::FFI::SRCDATA.new
47
+ src_data[:data_in] = in_ptr
48
+ src_data[:input_frames] = num_samples
49
+ src_data[:data_out] = outbuffer
50
+ src_data[:output_frames] = num_samples / 2
51
+ src_data[:src_ratio] = 16000.0 / 44100.0
52
+
53
+ puts "State Error: #{Libsamplerate::FFI.src_strerror error_ptr.read_int}"
54
+ resampled = Libsamplerate::FFI.src_process(src_state, src_data)
55
+ #resampled = Libsamplerate::FFI.src_simple(src_data, converter, channels)
56
+ puts "resampled: #{Libsamplerate::FFI.src_strerror resampled}"
57
+ num_samples_out = src_data[:output_frames_gen]
58
+ num_samples_in = src_data[:input_frames_used]
59
+ puts "Number of used input frames: #{num_samples_in}"
60
+ puts "Number of generated output frames: #{num_samples_out}"
61
+ samples = src_data[:data_out].read_array_of_float(num_samples_out * channels)
62
+ all_data.concat(samples)
63
+ puts "done"
64
+ end
65
+ Libsamplerate::FFI.src_delete src_state
66
+ file_out = "#{out_dir}/vagelis-16k-out.mono.stream.wav"
67
+ channels = 1
68
+ samplerate = 16000
69
+ info = RubyAudio::SoundInfo.new(
70
+ :channels => channels,
71
+ :samplerate => samplerate,
72
+ :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
73
+ )
74
+ sound = RubyAudio::Sound.open(file_out, 'w', info)
75
+ buffer = RubyAudio::Buffer.float(all_data.length, channels)
76
+ all_data.each_with_index { |sample, index|
77
+ puts sample if index == 100
78
+ buffer[index] = sample
79
+ }
80
+ sound.write(buffer)
81
+ sound.close
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "libsamplerate"
4
+
5
+ out_dir = "/home/pikos/Dropbox/Public"
6
+ file_name = "vagelis.wav"
7
+ file_path = "#{out_dir}/#{file_name}"
8
+ resampler = Libsamplerate::StaticResampler.new file_path
9
+ puts resampler
@@ -0,0 +1,7 @@
1
+ require "libsamplerate/version"
2
+ require "libsamplerate/ffi"
3
+ require "utils"
4
+ require "libsamplerate/static_resampler"
5
+
6
+ module Libsamplerate
7
+ end
@@ -0,0 +1,266 @@
1
+ # Generated by ffi_gen. Please do not change this file by hand.
2
+
3
+ require 'ffi'
4
+
5
+ module Libsamplerate::FFI
6
+ extend FFI::Library
7
+ ffi_lib "libsamplerate"
8
+
9
+ def self.attach_function(name, *_)
10
+ begin; super; rescue FFI::NotFoundError => e
11
+ (class << self; self; end).class_eval { define_method(name) { |*_| raise e } }
12
+ end
13
+ end
14
+
15
+ # Opaque data type SRC_STATE.
16
+ class SRCSTATETag < FFI::Struct
17
+ layout :dummy, :char
18
+ end
19
+
20
+ # SRC_DATA is used to pass data to src_simple() and src_process().
21
+ #
22
+ # = Fields:
23
+ # :data_in ::
24
+ # (FFI::Pointer(*Float))
25
+ # :data_out ::
26
+ # (FFI::Pointer(*Float))
27
+ # :input_frames ::
28
+ # (Integer)
29
+ # :output_frames ::
30
+ # (Integer)
31
+ # :input_frames_used ::
32
+ # (Integer)
33
+ # :output_frames_gen ::
34
+ # (Integer)
35
+ # :end_of_input ::
36
+ # (Integer)
37
+ # :src_ratio ::
38
+ # (Float)
39
+ class SRCDATA < FFI::Struct
40
+ layout :data_in, :pointer,
41
+ :data_out, :pointer,
42
+ :input_frames, :long,
43
+ :output_frames, :long,
44
+ :input_frames_used, :long,
45
+ :output_frames_gen, :long,
46
+ :end_of_input, :int,
47
+ :src_ratio, :double
48
+ end
49
+
50
+ # SRC_CB_DATA is used with callback based API.
51
+ #
52
+ # = Fields:
53
+ # :frames ::
54
+ # (Integer)
55
+ # :data_in ::
56
+ # (FFI::Pointer(*Float))
57
+ class SRCCBDATA < FFI::Struct
58
+ layout :frames, :long,
59
+ :data_in, :pointer
60
+ end
61
+
62
+ # User supplied callback function type for use with src_callback_new()
63
+ # and src_callback_read(). First parameter is the same pointer that was
64
+ # passed into src_callback_new(). Second parameter is pointer to a
65
+ # pointer. The user supplied callback function must modify *data to
66
+ # point to the start of the user supplied float array. The user supplied
67
+ # function must return the number of frames that **data points to.
68
+ #
69
+ # <em>This entry is only for documentation and no real method.</em>
70
+ #
71
+ # @method _callback_src_callback_t_(cb_data, data)
72
+ # @param [FFI::Pointer(*Void)] cb_data
73
+ # @param [FFI::Pointer(**Float)] data
74
+ # @return [FFI::Pointer(*Void)]
75
+ # @scope class
76
+ callback :src_callback_t, [:pointer, :pointer], :pointer
77
+
78
+ # Standard initialisation function : return an anonymous pointer to the
79
+ # internal state of the converter. Choose a converter from the enums below.
80
+ # Error returned in *error.
81
+ #
82
+ # @method src_new(converter_type, channels, error)
83
+ # @param [Integer] converter_type
84
+ # @param [Integer] channels
85
+ # @param [FFI::Pointer(*Int)] error
86
+ # @return [SRCSTATETag]
87
+ # @scope class
88
+ attach_function :src_new, :src_new, [:int, :int, :pointer], SRCSTATETag
89
+
90
+ # Initilisation for callback based API : return an anonymous pointer to the
91
+ # internal state of the converter. Choose a converter from the enums below.
92
+ # The cb_data pointer can point to any data or be set to NULL. Whatever the
93
+ # value, when processing, user supplied function "func" gets called with
94
+ # cb_data as first parameter.
95
+ #
96
+ # @method src_callback_new(func, converter_type, channels, error, cb_data)
97
+ # @param [Proc(_callback_src_callback_t_)] func
98
+ # @param [Integer] converter_type
99
+ # @param [Integer] channels
100
+ # @param [FFI::Pointer(*Int)] error
101
+ # @param [FFI::Pointer(*Void)] cb_data
102
+ # @return [SRCSTATETag]
103
+ # @scope class
104
+ attach_function :src_callback_new, :src_callback_new, [:src_callback_t, :int, :int, :pointer, :pointer], SRCSTATETag
105
+
106
+ # Cleanup all internal allocations.
107
+ # Always returns NULL.
108
+ #
109
+ # @method src_delete(state)
110
+ # @param [SRCSTATETag] state
111
+ # @return [SRCSTATETag]
112
+ # @scope class
113
+ attach_function :src_delete, :src_delete, [SRCSTATETag], SRCSTATETag
114
+
115
+ # Standard processing function.
116
+ # Returns non zero on error.
117
+ #
118
+ # @method src_process(state, data)
119
+ # @param [SRCSTATETag] state
120
+ # @param [SRCDATA] data
121
+ # @return [Integer]
122
+ # @scope class
123
+ attach_function :src_process, :src_process, [SRCSTATETag, SRCDATA], :int
124
+
125
+ # Callback based processing function. Read up to frames worth of data from
126
+ # the converter int *data and return frames read or -1 on error.
127
+ #
128
+ # @method src_callback_read(state, src_ratio, frames, data)
129
+ # @param [SRCSTATETag] state
130
+ # @param [Float] src_ratio
131
+ # @param [Integer] frames
132
+ # @param [FFI::Pointer(*Float)] data
133
+ # @return [Integer]
134
+ # @scope class
135
+ attach_function :src_callback_read, :src_callback_read, [SRCSTATETag, :double, :long, :pointer], :long
136
+
137
+ # Simple interface for performing a single conversion from input buffer to
138
+ # output buffer at a fixed conversion ratio.
139
+ # Simple interface does not require initialisation as it can only operate on
140
+ # a single buffer worth of audio.
141
+ #
142
+ # @method src_simple(data, converter_type, channels)
143
+ # @param [SRCDATA] data
144
+ # @param [Integer] converter_type
145
+ # @param [Integer] channels
146
+ # @return [Integer]
147
+ # @scope class
148
+ attach_function :src_simple, :src_simple, [SRCDATA, :int, :int], :int
149
+
150
+ # This library contains a number of different sample rate converters,
151
+ # numbered 0 through N.
152
+ #
153
+ # Return a string giving either a name or a more full description of each
154
+ # sample rate converter or NULL if no sample rate converter exists for
155
+ # the given value. The converters are sequentially numbered from 0 to N.
156
+ #
157
+ # @method src_get_name(converter_type)
158
+ # @param [Integer] converter_type
159
+ # @return [String]
160
+ # @scope class
161
+ attach_function :src_get_name, :src_get_name, [:int], :string
162
+
163
+ # (Not documented)
164
+ #
165
+ # @method src_get_description(converter_type)
166
+ # @param [Integer] converter_type
167
+ # @return [String]
168
+ # @scope class
169
+ attach_function :src_get_description, :src_get_description, [:int], :string
170
+
171
+ # (Not documented)
172
+ #
173
+ # @method src_get_version()
174
+ # @return [String]
175
+ # @scope class
176
+ attach_function :src_get_version, :src_get_version, [], :string
177
+
178
+ # Set a new SRC ratio. This allows step responses
179
+ # in the conversion ratio.
180
+ # Returns non zero on error.
181
+ #
182
+ # @method src_set_ratio(state, new_ratio)
183
+ # @param [SRCSTATETag] state
184
+ # @param [Float] new_ratio
185
+ # @return [Integer]
186
+ # @scope class
187
+ attach_function :src_set_ratio, :src_set_ratio, [SRCSTATETag, :double], :int
188
+
189
+ # Reset the internal SRC state.
190
+ # Does not modify the quality settings.
191
+ # Does not free any memory allocations.
192
+ # Returns non zero on error.
193
+ #
194
+ # @method src_reset(state)
195
+ # @param [SRCSTATETag] state
196
+ # @return [Integer]
197
+ # @scope class
198
+ attach_function :src_reset, :src_reset, [SRCSTATETag], :int
199
+
200
+ # Return TRUE if ratio is a valid conversion ratio, FALSE
201
+ # otherwise.
202
+ #
203
+ # @method src_is_valid_ratio(ratio)
204
+ # @param [Float] ratio
205
+ # @return [Integer]
206
+ # @scope class
207
+ attach_function :src_is_valid_ratio, :src_is_valid_ratio, [:double], :int
208
+
209
+ # Return an error number.
210
+ #
211
+ # @method src_error(state)
212
+ # @param [SRCSTATETag] state
213
+ # @return [Integer]
214
+ # @scope class
215
+ attach_function :src_error, :src_error, [SRCSTATETag], :int
216
+
217
+ # Convert the error number into a string.
218
+ #
219
+ # @method src_strerror(error)
220
+ # @param [Integer] error
221
+ # @return [String]
222
+ # @scope class
223
+ attach_function :src_strerror, :src_strerror, [:int], :string
224
+
225
+ # Extra helper functions for converting from short to float and
226
+ # back again.
227
+ #
228
+ # @method src_short_to_float_array(in_, out, len)
229
+ # @param [FFI::Pointer(*Short)] in_
230
+ # @param [FFI::Pointer(*Float)] out
231
+ # @param [Integer] len
232
+ # @return [nil]
233
+ # @scope class
234
+ attach_function :src_short_to_float_array, :src_short_to_float_array, [:pointer, :pointer, :int], :void
235
+
236
+ # (Not documented)
237
+ #
238
+ # @method src_float_to_short_array(in_, out, len)
239
+ # @param [FFI::Pointer(*Float)] in_
240
+ # @param [FFI::Pointer(*Short)] out
241
+ # @param [Integer] len
242
+ # @return [nil]
243
+ # @scope class
244
+ attach_function :src_float_to_short_array, :src_float_to_short_array, [:pointer, :pointer, :int], :void
245
+
246
+ # (Not documented)
247
+ #
248
+ # @method src_int_to_float_array(in_, out, len)
249
+ # @param [FFI::Pointer(*Int)] in_
250
+ # @param [FFI::Pointer(*Float)] out
251
+ # @param [Integer] len
252
+ # @return [nil]
253
+ # @scope class
254
+ attach_function :src_int_to_float_array, :src_int_to_float_array, [:pointer, :pointer, :int], :void
255
+
256
+ # (Not documented)
257
+ #
258
+ # @method src_float_to_int_array(in_, out, len)
259
+ # @param [FFI::Pointer(*Float)] in_
260
+ # @param [FFI::Pointer(*Int)] out
261
+ # @param [Integer] len
262
+ # @return [nil]
263
+ # @scope class
264
+ attach_function :src_float_to_int_array, :src_float_to_int_array, [:pointer, :pointer, :int], :void
265
+
266
+ end
@@ -0,0 +1,85 @@
1
+ require 'ruby-audio'
2
+ module Libsamplerate
3
+ class StaticResampler
4
+ attr_reader :in, :out, :src_data
5
+ def initialize in_file, out
6
+ @in = {
7
+ path: in_file,
8
+ info: get_info(in_file)
9
+ }
10
+ @out = out
11
+ end
12
+
13
+ def in_info
14
+ @in[:info]
15
+ end
16
+
17
+ def out_info
18
+ @out[:info]
19
+ end
20
+
21
+ def get_info file
22
+ Libsamplerate.get_sound_file_info file
23
+ end
24
+
25
+ def setup_src_data in_ptr, num_samples_in, out_ptr, num_samples_out, src_ratio
26
+ src_data[:data_in] = in_ptr
27
+ src_data[:input_frames] = num_samples_in
28
+ src_data[:data_out] = out_ptr
29
+ src_data[:output_frames] = num_samples_out
30
+ src_data[:src_ratio] = src_ratio
31
+ end
32
+
33
+ def src_data
34
+ @src_data ||= Libsamplerate::FFI::SRCDATA.new
35
+ end
36
+
37
+ def write_out_file
38
+ num_samples_out = src_data[:output_frames_gen]
39
+ samples = src_data[:data_out].read_array_of_float(num_samples_out * out_info.channels)
40
+ sound = RubyAudio::Sound.open(@out[:path], 'w', out_info)
41
+ buffer = RubyAudio::Buffer.float(samples.length, out_info.channels)
42
+ samples.each_with_index { |sample, index|
43
+ buffer[index] = sample
44
+ }
45
+ sound.write(buffer)
46
+ sound.close
47
+ end
48
+
49
+ def prepare_buffer
50
+ if in_info.channels != 1
51
+ Libsamplerate.stereo_to_mono @in[:path]
52
+ else
53
+ Libsamplerate.get_float_buffer_from_mono_file @in[:path]
54
+ end
55
+ end
56
+
57
+ def resample
58
+ input = prepare_buffer
59
+ num_samples = input.size
60
+ in_ptr = create_audio_pointer_buffer_float input
61
+ tRate = out_info.samplerate.to_f
62
+ iRate = in_info.samplerate.to_f
63
+ outbuffer = allocate_audio_pointer_buffer_float num_samples
64
+ outsamples = num_samples / 2
65
+ src_ratio = tRate / iRate
66
+ converter = Libsamplerate::CONVERTERS[:src_sinc_best_quality]
67
+ setup_src_data(in_ptr, num_samples, outbuffer, outsamples, src_ratio)
68
+ resampled = Libsamplerate::FFI.src_simple(src_data, converter, out_info.channels)
69
+ error = Libsamplerate::FFI.src_strerror resampled
70
+ error.eql? "No Error." || raise(error)
71
+ write_out_file
72
+ self
73
+ end
74
+
75
+ def allocate_audio_pointer_buffer_float num_samples
76
+ ::FFI::MemoryPointer.new :float, num_samples
77
+ end
78
+
79
+ def create_audio_pointer_buffer_float samples
80
+ ptr = ::FFI::MemoryPointer.new :float, samples.size
81
+ ptr.write_array_of_float samples
82
+ ptr
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,3 @@
1
+ module Libsamplerate
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,39 @@
1
+ module Libsamplerate
2
+ def self.stereo_to_mono file_path
3
+ buffer = []
4
+ RubyAudio::Sound.open(file_path) do |snd|
5
+ snd.read(:float, snd.info.frames).each do |sample|
6
+ buffer.push(sample[0])
7
+ end
8
+ end
9
+ buffer
10
+ end
11
+
12
+ def self.get_float_buffer_from_mono_file file
13
+ raise "This is not a mono file" if get_sound_file_info(file).channels == 1
14
+ buffer = []
15
+ RubyAudio::Sound.open(file) do |snd|
16
+ snd.read(:float, snd.info.frames).each do |sample|
17
+ buffer.push(sample)
18
+ end
19
+ end
20
+ buffer
21
+ end
22
+
23
+ def self.get_sound_file_info file_path
24
+ info = nil
25
+ RubyAudio::Sound.open(file_path) do |snd|
26
+ info = snd.info
27
+ end
28
+ info
29
+ end
30
+
31
+ CONVERTERS =
32
+ {
33
+ src_sinc_best_quality: 0,
34
+ src_sinc_medium_quality: 1,
35
+ src_sinc_fastest: 2,
36
+ src_zero_order_hold: 3,
37
+ src_linear: 4
38
+ }
39
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'libsamplerate/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "libsamplerate"
8
+ spec.version = Libsamplerate::VERSION
9
+ spec.authors = ["shamangeorge"]
10
+ spec.email = ["shamangeorge@fruitopology.net"]
11
+
12
+ spec.summary = %q{ffi interface for libsamplerate}
13
+ spec.description = %q{Gem to interface with secret rabbit code}
14
+ spec.homepage = "https://github.com/shamangeorge/libsamplerate"
15
+ spec.license = "LGPL-3.0"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f|
18
+ f.match(%r{^(test|spec|features)/}) || File.basename(f).start_with?(".")
19
+ }
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.12"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "pry", "~> 0.10"
27
+ spec.add_development_dependency "rspec", "~> 3.5"
28
+ spec.add_development_dependency "ffi_gen", "~> 1.2"
29
+ spec.add_development_dependency "ruby-audio", "~> 1.6.1"
30
+ spec.add_dependency "ffi", "~> 1.9"
31
+ end
Binary file
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libsamplerate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - shamangeorge
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-02-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ffi_gen
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: ruby-audio
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.6.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.6.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: ffi
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.9'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.9'
111
+ description: Gem to interface with secret rabbit code
112
+ email:
113
+ - shamangeorge@fruitopology.net
114
+ executables:
115
+ - ffi_gen_libsamplerate
116
+ - resample-stream.rb
117
+ - resample.rb
118
+ extensions: []
119
+ extra_rdoc_files: []
120
+ files:
121
+ - Gemfile
122
+ - LICENSE.md
123
+ - README.md
124
+ - Rakefile
125
+ - bin/console
126
+ - bin/setup
127
+ - exe/ffi_gen_libsamplerate
128
+ - exe/resample-stream.rb
129
+ - exe/resample.rb
130
+ - lib/libsamplerate.rb
131
+ - lib/libsamplerate/ffi.rb
132
+ - lib/libsamplerate/static_resampler.rb
133
+ - lib/libsamplerate/version.rb
134
+ - lib/utils.rb
135
+ - libsamplerate.gemspec
136
+ - wavfiles/vagelis-16k-mono.ruby-libresample.wav
137
+ - wavfiles/vagelis.wav
138
+ homepage: https://github.com/shamangeorge/libsamplerate
139
+ licenses:
140
+ - LGPL-3.0
141
+ metadata: {}
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ requirements: []
157
+ rubyforge_project:
158
+ rubygems_version: 2.7.3
159
+ signing_key:
160
+ specification_version: 4
161
+ summary: ffi interface for libsamplerate
162
+ test_files: []