native_audio 0.5.0 → 0.5.2
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.
- checksums.yaml +4 -4
- data/ext/audio/audio.c +53 -1
- data/ext/audio/audio.h +2 -0
- data/lib/native_audio.rb +33 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d7a019f96cab6e7939d9c7cd4ab6c238712dd7e973b9a5ded1ad565a6156af7
|
|
4
|
+
data.tar.gz: 6e5c823010843c54a0225433a1cd59e7980739e16ff5d607e23395da04316941
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d9b89059a4f4668c9a230f3cf543f281fa2930fee6773ab09790995deb22b454125ba50e81fec46edea5c19e61571b46f5589ffd45730e3ad0ecf12e092ff7aa
|
|
7
|
+
data.tar.gz: b2819672ad24fc89fccef79131eaee9711148d5b0ce608a681671d872706ef144d51053d04059e7fe523e5fdb3e0fc93815527e574161da8f8fd78c3bed3d893
|
data/ext/audio/audio.c
CHANGED
|
@@ -21,6 +21,7 @@ ma_sound *sounds[MAX_SOUNDS];
|
|
|
21
21
|
ma_sound *channels[MAX_CHANNELS];
|
|
22
22
|
multi_tap_delay_node *delay_nodes[MAX_CHANNELS];
|
|
23
23
|
reverb_node *reverb_nodes[MAX_CHANNELS];
|
|
24
|
+
ma_uint64 drain_until_frame[MAX_CHANNELS];
|
|
24
25
|
int sound_count = 0;
|
|
25
26
|
int engine_initialized = 0;
|
|
26
27
|
int context_initialized = 0;
|
|
@@ -180,6 +181,40 @@ VALUE audio_duration(VALUE self, VALUE clip)
|
|
|
180
181
|
// Playback Controls
|
|
181
182
|
// ============================================================================
|
|
182
183
|
|
|
184
|
+
static void cleanup_finished_channels(void)
|
|
185
|
+
{
|
|
186
|
+
ma_uint64 now = ma_engine_get_time_in_pcm_frames(&engine);
|
|
187
|
+
ma_uint32 sample_rate = ma_engine_get_sample_rate(&engine);
|
|
188
|
+
ma_uint64 drain_frames = (ma_uint64)(REVERB_DRAIN_SECONDS * sample_rate);
|
|
189
|
+
|
|
190
|
+
for (int i = 0; i < MAX_CHANNELS; i++) {
|
|
191
|
+
// Phase 1: sound finished - uninit the sound, start drain timer
|
|
192
|
+
if (channels[i] != NULL && ma_sound_at_end(channels[i])) {
|
|
193
|
+
ma_sound_uninit(channels[i]);
|
|
194
|
+
free(channels[i]);
|
|
195
|
+
channels[i] = NULL;
|
|
196
|
+
drain_until_frame[i] = now + drain_frames;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Phase 2: drain timer expired - uninit delay and reverb nodes
|
|
200
|
+
if (drain_until_frame[i] != 0 && now >= drain_until_frame[i]) {
|
|
201
|
+
if (delay_nodes[i] != NULL) {
|
|
202
|
+
multi_tap_delay_uninit(delay_nodes[i]);
|
|
203
|
+
free(delay_nodes[i]);
|
|
204
|
+
delay_nodes[i] = NULL;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (reverb_nodes[i] != NULL) {
|
|
208
|
+
reverb_uninit(reverb_nodes[i]);
|
|
209
|
+
free(reverb_nodes[i]);
|
|
210
|
+
reverb_nodes[i] = NULL;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
drain_until_frame[i] = 0;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
183
218
|
VALUE audio_play(VALUE self, VALUE channel_id, VALUE clip)
|
|
184
219
|
{
|
|
185
220
|
int channel = NUM2INT(channel_id);
|
|
@@ -195,6 +230,8 @@ VALUE audio_play(VALUE self, VALUE channel_id, VALUE clip)
|
|
|
195
230
|
return Qnil;
|
|
196
231
|
}
|
|
197
232
|
|
|
233
|
+
cleanup_finished_channels();
|
|
234
|
+
|
|
198
235
|
// Clean up existing resources on this channel
|
|
199
236
|
if (channels[channel] != NULL) {
|
|
200
237
|
ma_sound_stop(channels[channel]);
|
|
@@ -295,7 +332,21 @@ VALUE audio_stop(VALUE self, VALUE channel_id)
|
|
|
295
332
|
}
|
|
296
333
|
|
|
297
334
|
ma_sound_stop(channels[channel]);
|
|
298
|
-
|
|
335
|
+
ma_sound_uninit(channels[channel]);
|
|
336
|
+
free(channels[channel]);
|
|
337
|
+
channels[channel] = NULL;
|
|
338
|
+
|
|
339
|
+
if (delay_nodes[channel] != NULL) {
|
|
340
|
+
multi_tap_delay_uninit(delay_nodes[channel]);
|
|
341
|
+
free(delay_nodes[channel]);
|
|
342
|
+
delay_nodes[channel] = NULL;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (reverb_nodes[channel] != NULL) {
|
|
346
|
+
reverb_uninit(reverb_nodes[channel]);
|
|
347
|
+
free(reverb_nodes[channel]);
|
|
348
|
+
reverb_nodes[channel] = NULL;
|
|
349
|
+
}
|
|
299
350
|
|
|
300
351
|
return Qnil;
|
|
301
352
|
}
|
|
@@ -540,6 +591,7 @@ void Init_audio(void)
|
|
|
540
591
|
channels[i] = NULL;
|
|
541
592
|
delay_nodes[i] = NULL;
|
|
542
593
|
reverb_nodes[i] = NULL;
|
|
594
|
+
drain_until_frame[i] = 0;
|
|
543
595
|
}
|
|
544
596
|
|
|
545
597
|
VALUE mAudio = rb_define_module("Audio");
|
data/ext/audio/audio.h
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
#define MAX_SOUNDS 1024
|
|
17
17
|
#define MAX_CHANNELS 1024
|
|
18
|
+
#define REVERB_DRAIN_SECONDS 3.0f
|
|
18
19
|
|
|
19
20
|
// ============================================================================
|
|
20
21
|
// Globals (defined in audio.c)
|
|
@@ -26,6 +27,7 @@ extern ma_sound *sounds[MAX_SOUNDS];
|
|
|
26
27
|
extern ma_sound *channels[MAX_CHANNELS];
|
|
27
28
|
extern multi_tap_delay_node *delay_nodes[MAX_CHANNELS];
|
|
28
29
|
extern reverb_node *reverb_nodes[MAX_CHANNELS];
|
|
30
|
+
extern ma_uint64 drain_until_frame[MAX_CHANNELS];
|
|
29
31
|
extern int sound_count;
|
|
30
32
|
extern int engine_initialized;
|
|
31
33
|
extern int context_initialized;
|
data/lib/native_audio.rb
CHANGED
|
@@ -25,6 +25,7 @@ module NativeAudio
|
|
|
25
25
|
|
|
26
26
|
class DelayTap
|
|
27
27
|
attr_reader :id, :audio_source, :time_ms, :volume
|
|
28
|
+
attr_writer :id
|
|
28
29
|
|
|
29
30
|
def initialize(audio_source, id, time_ms, volume)
|
|
30
31
|
@audio_source = audio_source
|
|
@@ -56,11 +57,13 @@ module NativeAudio
|
|
|
56
57
|
@clip = clip
|
|
57
58
|
@channel = AudioSource.channels.count
|
|
58
59
|
@delay_taps = []
|
|
60
|
+
@params = {}
|
|
59
61
|
AudioSource.channels << self
|
|
60
62
|
end
|
|
61
63
|
|
|
62
64
|
def play
|
|
63
65
|
NativeAudio.audio_driver.play(@channel, @clip.clip)
|
|
66
|
+
apply_params
|
|
64
67
|
end
|
|
65
68
|
|
|
66
69
|
def stop
|
|
@@ -76,18 +79,22 @@ module NativeAudio
|
|
|
76
79
|
end
|
|
77
80
|
|
|
78
81
|
def set_pos(angle, distance)
|
|
82
|
+
@params[:pos] = [angle, distance]
|
|
79
83
|
NativeAudio.audio_driver.set_pos(@channel, angle, distance)
|
|
80
84
|
end
|
|
81
85
|
|
|
82
86
|
def set_volume(volume)
|
|
87
|
+
@params[:volume] = volume
|
|
83
88
|
NativeAudio.audio_driver.set_volume(@channel, volume)
|
|
84
89
|
end
|
|
85
90
|
|
|
86
91
|
def set_pitch(pitch)
|
|
92
|
+
@params[:pitch] = pitch
|
|
87
93
|
NativeAudio.audio_driver.set_pitch(@channel, pitch)
|
|
88
94
|
end
|
|
89
95
|
|
|
90
96
|
def set_looping(looping)
|
|
97
|
+
@params[:looping] = looping
|
|
91
98
|
NativeAudio.audio_driver.set_looping(@channel, looping)
|
|
92
99
|
end
|
|
93
100
|
|
|
@@ -99,10 +106,12 @@ module NativeAudio
|
|
|
99
106
|
end
|
|
100
107
|
|
|
101
108
|
def enable_reverb(enabled = true)
|
|
109
|
+
@params[:reverb_enabled] = enabled
|
|
102
110
|
NativeAudio.audio_driver.enable_reverb(@channel, enabled)
|
|
103
111
|
end
|
|
104
112
|
|
|
105
113
|
def set_reverb(room_size: 0.5, damping: 0.3, wet: 0.3, dry: 1.0)
|
|
114
|
+
@params[:reverb] = { room_size: room_size, damping: damping, wet: wet, dry: dry }
|
|
106
115
|
NativeAudio.audio_driver.enable_reverb(@channel, true)
|
|
107
116
|
NativeAudio.audio_driver.set_reverb_room_size(@channel, room_size)
|
|
108
117
|
NativeAudio.audio_driver.set_reverb_damping(@channel, damping)
|
|
@@ -117,5 +126,29 @@ module NativeAudio
|
|
|
117
126
|
def self.channels
|
|
118
127
|
@channels ||= []
|
|
119
128
|
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
def apply_params
|
|
133
|
+
NativeAudio.audio_driver.set_volume(@channel, @params[:volume]) if @params.key?(:volume)
|
|
134
|
+
NativeAudio.audio_driver.set_pitch(@channel, @params[:pitch]) if @params.key?(:pitch)
|
|
135
|
+
NativeAudio.audio_driver.set_looping(@channel, @params[:looping]) if @params.key?(:looping)
|
|
136
|
+
NativeAudio.audio_driver.set_pos(@channel, *@params[:pos]) if @params.key?(:pos)
|
|
137
|
+
|
|
138
|
+
if @params.key?(:reverb)
|
|
139
|
+
r = @params[:reverb]
|
|
140
|
+
NativeAudio.audio_driver.enable_reverb(@channel, true)
|
|
141
|
+
NativeAudio.audio_driver.set_reverb_room_size(@channel, r[:room_size])
|
|
142
|
+
NativeAudio.audio_driver.set_reverb_damping(@channel, r[:damping])
|
|
143
|
+
NativeAudio.audio_driver.set_reverb_wet(@channel, r[:wet])
|
|
144
|
+
NativeAudio.audio_driver.set_reverb_dry(@channel, r[:dry])
|
|
145
|
+
elsif @params.key?(:reverb_enabled)
|
|
146
|
+
NativeAudio.audio_driver.enable_reverb(@channel, @params[:reverb_enabled])
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
@delay_taps.each do |tap|
|
|
150
|
+
tap.id = NativeAudio.audio_driver.add_delay_tap(@channel, tap.time_ms, tap.volume)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
120
153
|
end
|
|
121
154
|
end
|