fiddle_fluidsynth 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.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.standard.yml +3 -0
  3. data/CHANGELOG.md +5 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +138 -0
  6. data/Rakefile +14 -0
  7. data/examples/enum.rb +30 -0
  8. data/examples/example.sf2 +0 -0
  9. data/examples/ffs_arpeggio.rb +252 -0
  10. data/examples/ffs_example.rb +47 -0
  11. data/examples/ffs_fx.rb +200 -0
  12. data/examples/ffs_metronome.rb +260 -0
  13. data/examples/ffs_midiplay.rb +122 -0
  14. data/examples/ffs_simple.rb +45 -0
  15. data/examples/ffs_test1.rb +41 -0
  16. data/examples/ffs_test3.rb +50 -0
  17. data/examples/fiddle-pointer.rb +18 -0
  18. data/examples/presets-each.rb +66 -0
  19. data/examples/presets-full_scan.rb +59 -0
  20. data/examples/settings-each.rb +106 -0
  21. data/exe/ffs_midiplay.rb +122 -0
  22. data/lib/fiddle_fluidsynth/audio_output/driver.rb +104 -0
  23. data/lib/fiddle_fluidsynth/audio_output/file_renderer.rb +84 -0
  24. data/lib/fiddle_fluidsynth/audio_output.rb +7 -0
  25. data/lib/fiddle_fluidsynth/command_interface/command_interface.rb +90 -0
  26. data/lib/fiddle_fluidsynth/command_interface/handler.rb +95 -0
  27. data/lib/fiddle_fluidsynth/command_interface/server.rb +79 -0
  28. data/lib/fiddle_fluidsynth/command_interface/shell.rb +76 -0
  29. data/lib/fiddle_fluidsynth/command_interface.rb +9 -0
  30. data/lib/fiddle_fluidsynth/core_ext/fiddle.rb +142 -0
  31. data/lib/fiddle_fluidsynth/core_ext/module.rb +123 -0
  32. data/lib/fiddle_fluidsynth/fiddle_fluidsynth.rb +172 -0
  33. data/lib/fiddle_fluidsynth/logging/logging.rb +82 -0
  34. data/lib/fiddle_fluidsynth/logging.rb +6 -0
  35. data/lib/fiddle_fluidsynth/midi_input/driver.rb +77 -0
  36. data/lib/fiddle_fluidsynth/midi_input/events.rb +255 -0
  37. data/lib/fiddle_fluidsynth/midi_input/midi_input.rb +70 -0
  38. data/lib/fiddle_fluidsynth/midi_input/player.rb +289 -0
  39. data/lib/fiddle_fluidsynth/midi_input/router.rb +225 -0
  40. data/lib/fiddle_fluidsynth/midi_input.rb +11 -0
  41. data/lib/fiddle_fluidsynth/misc/misc.rb +162 -0
  42. data/lib/fiddle_fluidsynth/misc.rb +6 -0
  43. data/lib/fiddle_fluidsynth/sequencer/events.rb +679 -0
  44. data/lib/fiddle_fluidsynth/sequencer/sequencer.rb +384 -0
  45. data/lib/fiddle_fluidsynth/sequencer.rb +7 -0
  46. data/lib/fiddle_fluidsynth/settings/settings.rb +465 -0
  47. data/lib/fiddle_fluidsynth/settings.rb +6 -0
  48. data/lib/fiddle_fluidsynth/soundfonts/generators.rb +128 -0
  49. data/lib/fiddle_fluidsynth/soundfonts/loader.rb +506 -0
  50. data/lib/fiddle_fluidsynth/soundfonts/modulators.rb +247 -0
  51. data/lib/fiddle_fluidsynth/soundfonts/soundfonts.rb +64 -0
  52. data/lib/fiddle_fluidsynth/soundfonts/voices.rb +178 -0
  53. data/lib/fiddle_fluidsynth/soundfonts.rb +11 -0
  54. data/lib/fiddle_fluidsynth/synth/audio_rendering.rb +100 -0
  55. data/lib/fiddle_fluidsynth/synth/effect/chorus.rb +269 -0
  56. data/lib/fiddle_fluidsynth/synth/effect/iir_filter.rb +81 -0
  57. data/lib/fiddle_fluidsynth/synth/effect/ladspa.rb +172 -0
  58. data/lib/fiddle_fluidsynth/synth/effect/reverb.rb +207 -0
  59. data/lib/fiddle_fluidsynth/synth/effect.rb +10 -0
  60. data/lib/fiddle_fluidsynth/synth/midi/messages.rb +292 -0
  61. data/lib/fiddle_fluidsynth/synth/midi/setup.rb +235 -0
  62. data/lib/fiddle_fluidsynth/synth/midi/tuning.rb +128 -0
  63. data/lib/fiddle_fluidsynth/synth/midi.rb +9 -0
  64. data/lib/fiddle_fluidsynth/synth/params/params.rb +200 -0
  65. data/lib/fiddle_fluidsynth/synth/params.rb +8 -0
  66. data/lib/fiddle_fluidsynth/synth/soundfont_management.rb +210 -0
  67. data/lib/fiddle_fluidsynth/synth/synth.rb +114 -0
  68. data/lib/fiddle_fluidsynth/synth/voice_control.rb +94 -0
  69. data/lib/fiddle_fluidsynth/synth.rb +18 -0
  70. data/lib/fiddle_fluidsynth/types/types.rb +131 -0
  71. data/lib/fiddle_fluidsynth/types.rb +10 -0
  72. data/lib/fiddle_fluidsynth/util/callback.rb +585 -0
  73. data/lib/fiddle_fluidsynth/util/interface/settings.rb +689 -0
  74. data/lib/fiddle_fluidsynth/util/interface/soundfont.rb +115 -0
  75. data/lib/fiddle_fluidsynth/util/interface/soundfont_preset.rb +69 -0
  76. data/lib/fiddle_fluidsynth/util/interface/soundfont_sample.rb +61 -0
  77. data/lib/fiddle_fluidsynth/util/interface.rb +11 -0
  78. data/lib/fiddle_fluidsynth/util/module_hier.rb +403 -0
  79. data/lib/fiddle_fluidsynth/util/util.rb +467 -0
  80. data/lib/fiddle_fluidsynth/util-after.rb +12 -0
  81. data/lib/fiddle_fluidsynth/util.rb +37 -0
  82. data/lib/fiddle_fluidsynth/version.rb +10 -0
  83. data/lib/fiddle_fluidsynth.rb +57 -0
  84. data/sig/fiddle_fluidsynth.rbs +4 -0
  85. metadata +128 -0
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+
5
+ # Original comments:
6
+ # FluidSynth FX - An example of using effects with fluidsynth
7
+ #
8
+ # This code is in the public domain.
9
+ #
10
+ # To compile:
11
+ # gcc -g -O -o fluidsynth_fx fluidsynth_fx.c -lfluidsynth
12
+ #
13
+ # To run
14
+ # fluidsynth_fx soundfont gain
15
+ #
16
+ # [Peter Hanappe]
17
+ #
18
+
19
+ # fiddle_fluidsynth comments:
20
+ # `ffs_fx.rb` is fiddle_fluidsynth version of `fluidsynth_fx.c`.
21
+ # This code is also in the public domain.
22
+ #
23
+ # [YAMAMOTO, Masayuki]
24
+
25
+ #
26
+ require_relative "../lib/fiddle_fluidsynth"
27
+ #require "fiddle_fluidsynth"
28
+
29
+
30
+ #
31
+ # if ARGV.size != 2
32
+ unless (1..2).cover? ARGV.size
33
+ $stderr.puts "ARGV (#{ARGV.size}): #{ARGV}"
34
+ $stderr.puts "#{__FILE__} [SOUNDFONT] <GAIN>"
35
+ exit 1
36
+ end
37
+ opt_idx = 0
38
+ $stderr.puts "ARGV (#{ARGV.size}): #{ARGV}"
39
+ if File.exist? ARGV[opt_idx]
40
+ opt_idx += 1
41
+ end
42
+ gain = ARGV[opt_idx].to_f
43
+
44
+
45
+ # Original comments:
46
+ # This function implements the callback function of the audio driver
47
+ # (see new_fluid_audio_driver2 below). The data argument is a pointer
48
+ # to your private data structure. 'len' is the number of audio frames
49
+ # in the buffers. 'nfx' and 'nout' are the number of input and output
50
+ # audio buffers. 'fx' and 'out' are arrays of float buffers containing
51
+ # the audio. The audio driver fills zero-initializes those buffers.
52
+ # You are responsible for filling up those buffers, as the result will
53
+ # be sent to the sound card. This is usually done by asking the synth
54
+ # to fill those buffers appropriately using fluid_synth_process()
55
+ #
56
+ # NOTE: The API was designed to be generic. Audio driver may fill the
57
+ # buffers with audio input from the soundcard, rather than zeros.
58
+ FFS = FiddleFluidSynth
59
+ fs = nil # define later (FFS instance).
60
+ cb_ptr = FFS.define_audio_func{|data, len, nfx, fx, nout, outbuf|
61
+
62
+ # FiddleFluidSynth comments:
63
+ # BE CAREFUL! all variables in the arguments (esp. the pointers)
64
+ # are in FFI, not in Fiddle!!!
65
+ #
66
+
67
+ usr_data = data
68
+ # $stderr.puts "gain: #{gain}"
69
+
70
+ #
71
+ $stderr.puts "len: #{len}, nfx: #{nfx}, fx: #{fx.inspect}," +
72
+ " nout: #{nout}, outbuf: #{outbuf.inspect}"
73
+
74
+ if fx.null?
75
+ # Original comments:
76
+ # Note that some audio drivers may not provide buffers for effects like
77
+ # reverb and chorus. In this case it's your decision what to do. If you
78
+ # had called fluid_synth_process() like in the else branch below, no
79
+ # effects would have been rendered. Instead, you may mix the effects
80
+ # directly into the out buffers.
81
+
82
+ $stderr.puts "fx is nil."
83
+ $stderr.puts "#audio_channels: #{fs.synth_count_audio_channels(fs.synth)}"
84
+ $stderr.puts "#audio_groups: #{fs.synth_count_audio_groups(fs.synth)}"
85
+ $stderr.puts "#effects_groups: #{fs.synth_count_effects_groups(fs.synth)}"
86
+
87
+ fx_ptr = Fiddle::Pointer.new(fx.address)
88
+ outbuf_ptr = Fiddle::Pointer.new(outbuf.address)
89
+ if fs.synth_process(fs.synth, len: len,
90
+ nfx: nfx, fx: fx_ptr, nout: nout, outbuf: outbuf_ptr) !=
91
+ FiddleFluidSynth::FLUID_OK
92
+ $stderr.puts "(1) synth_process() is failed."
93
+ return FiddleFluidSynth::FLUID_FAILED
94
+ else
95
+ $stderr.puts "(1) synth_process() is succeeded."
96
+ end
97
+ else
98
+ # Original comments:
99
+ # Call the synthesizer to fill the output buffers with its
100
+ # audio output.
101
+
102
+ # FiddleFluidSynth comments:
103
+ # FiddleFluidSynth#synth_process() is wrapped by Fiddle, so we have to
104
+ # use Fiddle::Pointer instead of FFI::Pointer...
105
+ #
106
+
107
+ #
108
+ fx_ptr = Fiddle::Pointer.new(fx.address)
109
+ outbuf_ptr = Fiddle::Pointer.new(outbuf.address)
110
+ if fs.synth_process(fs.synth, len: len,
111
+ nfx: nfx, fx: fx_ptr, nout: nout, outbuf: outbuf_ptr) !=
112
+ FiddleFluidSynth::FLUID_OK
113
+ $stderr.puts "(2) synth_process() is failed."
114
+ return FiddleFluidSynth::FLUID_FAILED
115
+ else
116
+ $stderr.puts "(2) synth_process() is succeeded."
117
+ end
118
+ end
119
+
120
+ #
121
+ # $stderr.puts "effector: start."
122
+ ptr_size = FFI.type_size(:pointer)
123
+ float_size = FFI.type_size(:float)
124
+ # raise SyntaxError, "test."
125
+
126
+ out_ptr = outbuf
127
+ fx_ptr = fx
128
+
129
+ # Original comments:
130
+ # Apply your effects here. In this example, the gain is
131
+ # applied to all the dry-audio output buffers.
132
+
133
+ # for outbuf.
134
+ # $stderr.puts "effector: out."
135
+ nout.times do |_i|
136
+ ch_ptr = out_ptr.get_pointer(_i * ptr_size)
137
+
138
+ len.times do |_j|
139
+ v = ch_ptr.get_float(_j * float_size)
140
+ nv = v*gain
141
+ ch_ptr.put_float(_j*float_size, nv)
142
+ # $stderr.puts "#{_j}: #{v} =>#{nv} (gain: #{gain})"
143
+ end
144
+ end
145
+
146
+
147
+ # Original comments:
148
+ # Apply the same effect to all available effect buffer.
149
+ #
150
+
151
+ # for fx.
152
+ # $stderr.puts "effector: fx."
153
+ nfx.times do |_i|
154
+ ch_ptr = fx_ptr.get_pointer(_i * ptr_size)
155
+
156
+ len.times do |_j|
157
+ v = ch_ptr.get_float(_j * float_size)
158
+ ch_ptr.put_float(_j*float_size, v*gain)
159
+ end
160
+ end
161
+
162
+ #return FiddleFluidSynth::FLUID_OK # LongJumpError.
163
+ FiddleFluidSynth::FLUID_OK
164
+ }
165
+
166
+
167
+ # Original comments:
168
+ # Create the audio driver. As soon as the audio driver is
169
+ # created, the synthesizer can be played.
170
+
171
+ # FiddleFluidSynth comments:
172
+ # Create the audio driver in the initializer of FFS.
173
+ #
174
+ fs = if ARGV.size == 2
175
+ FiddleFluidSynth.new(
176
+ soundfont_full_path: ARGV[0],
177
+ player_f: false,
178
+ # audio_driver_new2_f: true,
179
+ audio_driver_callback: cb_ptr)
180
+ else
181
+ FiddleFluidSynth.new(
182
+ player_f: false,
183
+ audio_driver_callback: cb_ptr)
184
+ end
185
+
186
+ # Original comments:
187
+ # play a note.
188
+ #
189
+ fs.noteon(0, 60, 100)
190
+
191
+ #
192
+ print 'Press "Enter" to stop: '
193
+ $stdin.getc
194
+ fs.raise_error_in_callback
195
+ puts "done."
196
+
197
+ #
198
+ fs.delete
199
+
200
+ #### end.
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+
5
+ # Original comments:
6
+ # FluidSynth Metronome - Sequencer API example
7
+ #
8
+ # This code is in the public domain.
9
+ #
10
+ # To compile:
11
+ # gcc -o fluidsynth_metronome -lfluidsynth fluidsynth_metronome.c
12
+ #
13
+ # To run:
14
+ # fluidsynth_metronome soundfont [beats [tempo]]
15
+ #
16
+ # [Pedro Lopez-Cabanillas <plcl@users.sf.net>]
17
+
18
+ # fiddle_fluidsynth comments:
19
+ # `ffs_metronome.rb` is FiddleFluidSynth version of `fluidsynth_metronome.c`.
20
+ # This code is also in the public domain.
21
+ #
22
+ # [YAMAMOTO, Masayuki, ]
23
+
24
+ #
25
+ require_relative '../lib/fiddle_fluidsynth'
26
+ # require 'fiddle_fluidsynth'
27
+
28
+
29
+ #
30
+ # @audiodriver = nil
31
+ @seq = nil
32
+
33
+ #
34
+ @synth_dest, @client_dest = nil, nil
35
+ @time_marker = nil
36
+
37
+ # default tempo, beats per minute.
38
+ TEMPO = 120
39
+ tempo = TEMPO
40
+ @note_duration = 60000 / TEMPO
41
+
42
+ # metronome click/bell.
43
+ @weak_note = 33 # click sound.
44
+ @strong_note = 34 # click+bell sound.
45
+
46
+ # number of notes in one pattern (beats).
47
+ @pattern_size = 4
48
+
49
+
50
+ # schedule a note on message.
51
+ #
52
+ #
53
+ FFS = FiddleFluidSynth
54
+ def schedule_noteon( ch, key, ticks )
55
+
56
+ # ev = FFS.event_new
57
+ # ev.set_type(:noteon, ch: ch, key: key, vel: 127)
58
+ # :
59
+ # FFS.event_delete(ev)
60
+ FFS.seq_event(:noteon, ch: ch, key: key, vel: 127){|ev|
61
+ ev.source = -1
62
+ ev.dest = @synth_dest
63
+
64
+ #
65
+ if @seq.send_at(event: ev, time: ticks, absolute: 1) == \
66
+ FFS::FLUID_FAILED
67
+ $stderr.puts "(**) {#{__method__}} seq. send_at() failed."
68
+ end
69
+ # if FFS::FLUID_FAILED == _tmp
70
+ # $stderr.puts "(**) {#{__method__}} seq. send_at() failed (#{_tmp})."
71
+ # else
72
+ # $stderr.puts "(**) {#{__method__}} seq. send_at() succeeded (#{_tmp})."
73
+ # end
74
+ }
75
+
76
+ end
77
+
78
+
79
+ # schedule a timer event (shall trigger the callback).
80
+ #
81
+ #
82
+ def schedule_timer_event
83
+
84
+ # $stderr.puts "{#{__method__}} Scheduling timer event at #{@time_marker}"
85
+ # $stderr.puts " Current tick: #{@seq.tick}"
86
+
87
+ #ev = FFS.event_new
88
+ # FFS.event_set_src(ev, src: -1)
89
+ # FFS.event_set_dest(ev, dest: @client_dest)
90
+ # FFS.event_timer(ev, data: nil)
91
+ #ev.set_type(:timer, data: nil)
92
+ # :
93
+ #FFS.event_delete(ev)
94
+ FFS.seq_event(:timer, data: nil){|ev|
95
+ ev.source = -1
96
+ ev.dest = @client_dest
97
+ # $stderr.puts "{#{__method__}} set as a timer event for #{ev.inspect}"
98
+
99
+ if @seq.send_at(event: ev, time: @time_marker, absolute: 1) == \
100
+ FFS::FLUID_FAILED
101
+ $stderr.puts "(**) {#{__method__}} seq. send_at() failed."
102
+ end
103
+ # if FFS::FLUID_FAILED == _tmp
104
+ # $stderr.puts "(**) {#{__method__}} seq. send_at() failed (#{_tmp})."
105
+ # else
106
+ # $stderr.puts "(**) {#{__method__}} seq. send_at() succeeded (#{_tmp})."
107
+ # end
108
+ }
109
+
110
+ end
111
+
112
+
113
+ # schedule the metronome pattern.
114
+ #
115
+ #
116
+ def schedule_pattern
117
+ # $stderr.puts "{#{__method__}} Scheduling pattern events at #{@time_marker}"
118
+ # $stderr.puts " Current tick: #{@seq.tick}"
119
+
120
+ #
121
+ note_time = @time_marker
122
+
123
+ #
124
+ # @pattern_size.times do |_i|
125
+ (0...@pattern_size).each do |_i|
126
+ # 0 is also true in Ruby... so we have to change the logic.
127
+ _note = !(_i.zero?) ? @weak_note : @strong_note
128
+ $stderr.puts " #{_note}, scheduled at note_time: #{note_time}" if \
129
+ ARGV.size == 4
130
+
131
+ schedule_noteon(9, _note, note_time)
132
+ note_time += @note_duration
133
+ end
134
+
135
+ @time_marker = note_time
136
+ # $stderr.puts "{#{__method__}} Next time marker: #{@time_marker}"
137
+ end
138
+
139
+ #
140
+ @seq_cb_ptr = FFS.define_event_callback{|time, ev, seq, data|
141
+ # $stderr.puts "{#{Time.now}} on callback."
142
+ schedule_timer_event()
143
+ schedule_pattern()
144
+ }
145
+
146
+ #
147
+ def usage( prog_name = __FILE__ )
148
+ puts "Usage: #{prog_name} [soundfont] [beats [tempo]]"
149
+ puts " or #{prog_name} -h"
150
+ puts "\tsoundfont [optional]: soundfont file name (in full path)," +
151
+ " default #{FFS.obtain_full_path_for_soundfont}."
152
+ puts "\tbeats [optional]: number of pattern beats, default #{@pattern_size}"
153
+ puts "\ttempo [optional]: BPM (Beats Per Minute), default #{TEMPO}"
154
+ end
155
+
156
+
157
+ ### main.
158
+
159
+ if ARGV[0] == '-h' || ARGV[0] == '--help'
160
+ usage()
161
+ exit 1
162
+ end
163
+
164
+ #
165
+ opt_idx = 0
166
+ fs = if File.exist?("#{ARGV[opt_idx]}")
167
+ tmp = FiddleFluidSynth.new(
168
+ soundfont_full_path: "#{ARGV[opt_idx]}", player_f: false)
169
+ opt_idx += 1
170
+ $stderr.puts "(1) opt_idx: #{opt_idx}"
171
+ tmp
172
+ else
173
+ $stderr.puts "(2) opt_idx: #{opt_idx}"
174
+ FiddleFluidSynth.new(player_f: false)
175
+ end
176
+ $stderr.puts "opt_idx: #{opt_idx}"
177
+
178
+ #
179
+ # @seq = fs.sequencer_new2(0)
180
+ @seq = fs.sequencer_new2
181
+ if @seq.null?
182
+ raise "Cannot prepare the sequencer!"
183
+ end
184
+ puts "seq. clients: #{@seq.count_clients}"
185
+
186
+
187
+ # register the synthesizer (automatically destination)
188
+ # to the sequencer.
189
+ #
190
+ @synth_dest = @seq.register_fluidsynth(fs.synth)
191
+ if FFS::FLUID_FAILED == @synth_dest
192
+ raise "Client (synth) registsteration failed."
193
+ end
194
+ puts "seq_id: #{@synth_dest}, seq. clients: #{@seq.count_clients}"
195
+
196
+
197
+ # register the sequencer client.
198
+ #
199
+ #
200
+ @client_dest = @seq.register_client(
201
+ name: 'ffs_metronome',
202
+ event_callback: @seq_cb_ptr, data: nil)
203
+ if FFS::FLUID_FAILED == @client_dest
204
+ raise "Client registsteration failed."
205
+ end
206
+ puts "seq_id: #{@client_dest}, seq. clients: #{@seq.count_clients}"
207
+
208
+
209
+ # If we prepare the audio driver twice, note_duration become half.
210
+ # I dont know why...
211
+ #
212
+ # @audiodriver = fs.audio_driver_prepare
213
+
214
+ #
215
+ #if ARGV.size >= 2 && ARGV[opt_idx]
216
+ if ARGV.size >= 1 && ARGV[opt_idx]
217
+ $stderr.puts "(**) beats setting (#ARGV: #{ARGV.size}, opt_idx: #{opt_idx})."
218
+ beats = ARGV[opt_idx].to_i
219
+ opt_idx += 1
220
+ $stderr.puts "(**) beats is set to: #{beats}."
221
+ @pattern_size = beats if beats > 0
222
+ end
223
+
224
+ #
225
+ if ARGV.size >= 2 && ARGV[opt_idx]
226
+ $stderr.puts "(**) tempo setting (#ARGV: #{ARGV.size}, opt_idx: #{opt_idx})."
227
+ tempo = ARGV[opt_idx].to_i
228
+ opt_idx += 1
229
+ @note_duration = 60000/tempo if tempo > 0
230
+ $stderr.puts "(**) tempo is set to #{tempo}."
231
+ end
232
+
233
+ # get the current time in ticks.
234
+ #
235
+ #
236
+ # @time_marker = fs.sequencer_get_tick(@seq)
237
+ @time_marker = @seq.tick
238
+
239
+ # schedule patterns.
240
+ schedule_pattern()
241
+ schedule_timer_event()
242
+ schedule_pattern()
243
+
244
+ # wait for user input.
245
+ #
246
+ #
247
+ puts "beats: #{@pattern_size}/tempo: #{tempo}" +
248
+ " =>note_duration: #{@note_duration} [ms]"
249
+ print 'Press "Enter" to stop: '
250
+ $stdin.getc
251
+ fs.raise_error_in_callback
252
+ puts "done."
253
+
254
+ #
255
+ puts "Cleaning up..."
256
+ fs.delete
257
+ puts "fs.deleted."
258
+
259
+ puts "Done. Exiting program."
260
+ #### end.
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+ #
5
+
6
+ # ffs_midiplay.rb - fiddle_fluidsynth MIDI file player (tick callback
7
+ # example).
8
+ # This code is in the public domain.
9
+ #
10
+ # [YAMAMOTO, Masayuki]
11
+ #
12
+
13
+ #
14
+ require_relative '../lib/fiddle_fluidsynth'
15
+ #require 'fiddle_fluidsynth'
16
+
17
+
18
+ #
19
+ DEFAULT_SF2_NAME = "default.sf2"
20
+ f_1 = ARGV[0]
21
+ f_2 = ARGV[1]
22
+
23
+ f_midi = f_2 || f_1
24
+ f_sf2 = (f_2.nil?)? DEFAULT_SF2_NAME : f_1
25
+ puts "SoundFont: #{f_sf2}, MIDI file #{f_midi}"
26
+
27
+ if f_midi.nil?
28
+ $stderr.puts "Help: #{File.basename(__FILE__)} [SoundFont] MIDI-file"
29
+ raise "Specify a MIDI file you want to play at least."
30
+ end
31
+
32
+ #
33
+ #
34
+ #
35
+ fs = if File.exist?(f_sf2)
36
+ FiddleFluidSynth.new(soundfont_full_path: f_sf2)
37
+ else
38
+ FiddleFluidSynth.new(soundfont_name: f_sf2)
39
+ end
40
+ fs.start
41
+
42
+ #
43
+ #
44
+ #
45
+ is_midi = fs.is_midifile(f_midi)
46
+ raise "MIDI file is strange (#{is_midi}): #{f_midi}" \
47
+ unless fs.is_midifile?(f_midi)
48
+
49
+ ver_s = fs.fluidsynth_version_str
50
+ ver_ary = fs.fluidsynth_version
51
+
52
+ puts "MIDI file (#{is_midi}): #{f_midi}"
53
+ puts "fluidsynth version_str: #{ver_s} (by version: #{ver_ary})"
54
+ puts
55
+
56
+ #
57
+ #
58
+ #
59
+ fs.player_file(f_midi)
60
+ time_start = Time.now
61
+ puts "#{time_start}: Playing #{f_midi}"
62
+
63
+
64
+ #
65
+ # we can pass user_data via handler_data as follows, but this is completely
66
+ # meaningless in FiddleFluidSynth.
67
+ #
68
+ # because we use the closure to define the callback function, i.e.,
69
+ # we can use any variables in the callback freely.
70
+ #
71
+ # ```
72
+ # str_ptr = FFI::MemoryPointer.from_string("this is a test.")
73
+ # fdl_ptr = Fiddle::Pointer.new(str_ptr.address)
74
+ #
75
+ # fs.player_set_tick_callback(handler_data: fdl_ptr_ary){|user_data, cur_tick|
76
+ # :
77
+ # puts "#{user_data}/#{user_data.read_string}" # user_data is FFI::Pointer.
78
+ # :
79
+ # }
80
+ # ```
81
+ #
82
+ fs.player_set_tick_callback{|user_data, cur_tick|
83
+ #
84
+ total_ticks = fs.player_get_total_ticks
85
+
86
+ #
87
+ status = fs.player_status
88
+ bpm = fs.player_bpm
89
+
90
+ #
91
+ # puts "#{user_data}/#{user_data.address}"
92
+ # puts "#{user_data}/#{user_data.read_string}"
93
+ puts "#{Time.now}: player status: #{status}/bpm: #{bpm}"
94
+
95
+ #
96
+ if cur_tick <= total_ticks
97
+ puts "Tick: %4d / %4d" % [cur_tick, total_ticks]
98
+ else
99
+ puts "(**) All events in the MIDI file are executed" +
100
+ " (Tick: %4d / %4d)" % [cur_tick, total_ticks]
101
+ end
102
+ }
103
+
104
+
105
+ #
106
+ #
107
+ #
108
+ until fs.player_is_done?
109
+ sleep(1.0)
110
+ end
111
+
112
+
113
+ #
114
+ #
115
+ #
116
+ fs.raise_error_in_callback
117
+ fs.delete
118
+ time_end = Time.now
119
+ puts "#{time_end}: Finished (in #{time_end-time_start} [sec])."
120
+
121
+
122
+ #### end.
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+ #
5
+
6
+ # Original comments:
7
+ # FluidSynth Simple - An example of using fluidsynth
8
+ #
9
+ # This code is in the public domain.
10
+ #
11
+ # To compile:
12
+ # gcc -g -O -o fluidsynth_simple fluidsynth_simple.c -lfluidsynth
13
+ #
14
+ # To run
15
+ # fluidsynth_simple soundfont
16
+ #
17
+ # [Peter Hanappe]
18
+ #
19
+ #
20
+
21
+
22
+ # `ffs_simple.rb` is the fiddle_fluidsynth version of `fluidsynth_simple.c`
23
+ # This code is in the public domain.
24
+ #
25
+ # [YAMAMOTO, Masayuki]
26
+
27
+ #
28
+ require_relative '../lib/fiddle_fluidsynth'
29
+ #require 'fiddle_fluidsynth'
30
+
31
+ #
32
+ fs = FiddleFluidSynth.new(player_f: false)
33
+
34
+ #
35
+ fs.noteon(0, 60, 100)
36
+ print 'Press "Enter" to stop: '
37
+ $stdin.getc
38
+ puts "done."
39
+
40
+
41
+ fs.raise_error_in_callback
42
+ fs.delete
43
+
44
+
45
+ #### end.
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+
5
+ # `ffs_test1.rb` is the fiddle_fluidsynth version of `test1.rb` in
6
+ # ruby-fluidsynth.gem.
7
+ #
8
+ # This is from `ruby-fluidsynth.gem` by Daniel W. Steinbrook (2011).
9
+ # (https://github.com/steinbro/ruby-fluidsynth)
10
+ #
11
+
12
+ require_relative '../lib/fiddle_fluidsynth'
13
+ #require 'fiddle_fluidsynth'
14
+
15
+
16
+ # fs = FiddleFluidSynth.new(soundfont_name: nil)
17
+ fs = FiddleFluidSynth.new
18
+ fs.start
19
+
20
+ sfid = fs.synth_sfload(filename: "#{__dir__}/example.sf2", reset_presets: 0,
21
+ verbose_f: true)
22
+ fs.program_select(ch: 0, sfid: sfid, bknum: 0, prenum: 0)
23
+
24
+ fs.noteon(0, 60, 30)
25
+ fs.noteon(0, 67, 30)
26
+ fs.noteon(0, 76, 30)
27
+
28
+ sleep(1.0)
29
+
30
+ fs.noteoff(0, 60)
31
+ fs.noteoff(0, 67)
32
+ fs.noteoff(0, 76)
33
+
34
+ sleep(1.0)
35
+
36
+
37
+ fs.raise_error_in_callback
38
+ fs.delete
39
+
40
+
41
+ #### end.
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ #
4
+ #
5
+
6
+ # `ffs_test3.rb` is the fiddle_fluidsynth version of `test3.rb` in
7
+ # ruby-fluidsynth.gem.
8
+ #
9
+ # This is from `ruby-fluidsynth.gem` by Daniel W.Steinbrook (2011).
10
+ # (https://github.com/steinbro/ruby-fluidsynth)
11
+ #
12
+
13
+ #
14
+ require_relative '../lib/fiddle_fluidsynth'
15
+ #require 'fiddle_fluidsynth'
16
+
17
+
18
+ #
19
+ fs = FiddleFluidSynth.new(soundfont_name: nil)
20
+ fs.start
21
+
22
+ sfid = fs.synth_sfload(filename: "#{__dir__}/example.sf2", reset_presets: 0,
23
+ verbose_f: true)
24
+ sfont = fs.synth_get_sfont_by_id(id: sfid)
25
+ sfont_name = fs.sfont_get_name(sfont)
26
+
27
+ puts "sfont_name: #{sfont_name}"
28
+
29
+ fs.program_select(ch: 0, sfid: sfid, bknum: 0, prenum: 0)
30
+
31
+ fs.noteon(0, 60, 30)
32
+ sleep(0.3)
33
+
34
+ 10.times do |i|
35
+ fs.cc(0, 93, 127)
36
+ fs.pitch_bend(0, i * 512)
37
+ sleep(0.1)
38
+ end
39
+
40
+ fs.noteoff(0, 60)
41
+
42
+ sleep(1.0)
43
+
44
+
45
+ #
46
+ fs.raise_error_in_callback
47
+ fs.delete
48
+
49
+
50
+ #### end.