libsamplerate 0.0.1

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