native_audio 0.3.0 → 0.5.0
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/LICENSE +21 -0
- data/README.md +152 -0
- data/ext/audio/audio.c +541 -43
- data/ext/audio/audio.h +34 -0
- data/ext/audio/delay_node.c +185 -0
- data/ext/audio/delay_node.h +51 -0
- data/ext/audio/extconf.rb +12 -110
- data/ext/audio/miniaudio.h +95844 -0
- data/ext/audio/reverb_node.c +224 -0
- data/ext/audio/reverb_node.h +63 -0
- data/lib/dummy_audio.rb +94 -0
- data/lib/native_audio.rb +78 -7
- metadata +12 -132
- data/assets/include/SDL2/SDL.h +0 -233
- data/assets/include/SDL2/SDL_assert.h +0 -326
- data/assets/include/SDL2/SDL_atomic.h +0 -415
- data/assets/include/SDL2/SDL_audio.h +0 -1500
- data/assets/include/SDL2/SDL_bits.h +0 -126
- data/assets/include/SDL2/SDL_blendmode.h +0 -198
- data/assets/include/SDL2/SDL_clipboard.h +0 -141
- data/assets/include/SDL2/SDL_config.h +0 -61
- data/assets/include/SDL2/SDL_config_android.h +0 -194
- data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
- data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
- data/assets/include/SDL2/SDL_config_macosx.h +0 -277
- data/assets/include/SDL2/SDL_config_minimal.h +0 -95
- data/assets/include/SDL2/SDL_config_ngage.h +0 -89
- data/assets/include/SDL2/SDL_config_os2.h +0 -207
- data/assets/include/SDL2/SDL_config_pandora.h +0 -141
- data/assets/include/SDL2/SDL_config_windows.h +0 -331
- data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
- data/assets/include/SDL2/SDL_config_winrt.h +0 -220
- data/assets/include/SDL2/SDL_config_xbox.h +0 -235
- data/assets/include/SDL2/SDL_copying.h +0 -20
- data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
- data/assets/include/SDL2/SDL_egl.h +0 -2352
- data/assets/include/SDL2/SDL_endian.h +0 -348
- data/assets/include/SDL2/SDL_error.h +0 -163
- data/assets/include/SDL2/SDL_events.h +0 -1166
- data/assets/include/SDL2/SDL_filesystem.h +0 -149
- data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
- data/assets/include/SDL2/SDL_gesture.h +0 -117
- data/assets/include/SDL2/SDL_guid.h +0 -100
- data/assets/include/SDL2/SDL_haptic.h +0 -1341
- data/assets/include/SDL2/SDL_hidapi.h +0 -451
- data/assets/include/SDL2/SDL_hints.h +0 -2569
- data/assets/include/SDL2/SDL_image.h +0 -2173
- data/assets/include/SDL2/SDL_joystick.h +0 -1066
- data/assets/include/SDL2/SDL_keyboard.h +0 -353
- data/assets/include/SDL2/SDL_keycode.h +0 -358
- data/assets/include/SDL2/SDL_loadso.h +0 -115
- data/assets/include/SDL2/SDL_locale.h +0 -103
- data/assets/include/SDL2/SDL_log.h +0 -404
- data/assets/include/SDL2/SDL_main.h +0 -275
- data/assets/include/SDL2/SDL_messagebox.h +0 -193
- data/assets/include/SDL2/SDL_metal.h +0 -113
- data/assets/include/SDL2/SDL_misc.h +0 -79
- data/assets/include/SDL2/SDL_mixer.h +0 -2784
- data/assets/include/SDL2/SDL_mouse.h +0 -465
- data/assets/include/SDL2/SDL_mutex.h +0 -471
- data/assets/include/SDL2/SDL_name.h +0 -33
- data/assets/include/SDL2/SDL_opengl.h +0 -2132
- data/assets/include/SDL2/SDL_opengl_glext.h +0 -13209
- data/assets/include/SDL2/SDL_opengles.h +0 -39
- data/assets/include/SDL2/SDL_opengles2.h +0 -52
- data/assets/include/SDL2/SDL_opengles2_gl2.h +0 -656
- data/assets/include/SDL2/SDL_opengles2_gl2ext.h +0 -4033
- data/assets/include/SDL2/SDL_opengles2_gl2platform.h +0 -27
- data/assets/include/SDL2/SDL_opengles2_khrplatform.h +0 -311
- data/assets/include/SDL2/SDL_pixels.h +0 -644
- data/assets/include/SDL2/SDL_platform.h +0 -261
- data/assets/include/SDL2/SDL_power.h +0 -88
- data/assets/include/SDL2/SDL_quit.h +0 -58
- data/assets/include/SDL2/SDL_rect.h +0 -376
- data/assets/include/SDL2/SDL_render.h +0 -1919
- data/assets/include/SDL2/SDL_revision.h +0 -6
- data/assets/include/SDL2/SDL_rwops.h +0 -841
- data/assets/include/SDL2/SDL_scancode.h +0 -438
- data/assets/include/SDL2/SDL_sensor.h +0 -322
- data/assets/include/SDL2/SDL_shape.h +0 -155
- data/assets/include/SDL2/SDL_stdinc.h +0 -830
- data/assets/include/SDL2/SDL_surface.h +0 -997
- data/assets/include/SDL2/SDL_system.h +0 -623
- data/assets/include/SDL2/SDL_syswm.h +0 -386
- data/assets/include/SDL2/SDL_test.h +0 -69
- data/assets/include/SDL2/SDL_test_assert.h +0 -105
- data/assets/include/SDL2/SDL_test_common.h +0 -236
- data/assets/include/SDL2/SDL_test_compare.h +0 -69
- data/assets/include/SDL2/SDL_test_crc32.h +0 -124
- data/assets/include/SDL2/SDL_test_font.h +0 -168
- data/assets/include/SDL2/SDL_test_fuzzer.h +0 -386
- data/assets/include/SDL2/SDL_test_harness.h +0 -134
- data/assets/include/SDL2/SDL_test_images.h +0 -78
- data/assets/include/SDL2/SDL_test_log.h +0 -67
- data/assets/include/SDL2/SDL_test_md5.h +0 -129
- data/assets/include/SDL2/SDL_test_memory.h +0 -63
- data/assets/include/SDL2/SDL_test_random.h +0 -115
- data/assets/include/SDL2/SDL_thread.h +0 -464
- data/assets/include/SDL2/SDL_timer.h +0 -222
- data/assets/include/SDL2/SDL_touch.h +0 -150
- data/assets/include/SDL2/SDL_ttf.h +0 -2316
- data/assets/include/SDL2/SDL_types.h +0 -29
- data/assets/include/SDL2/SDL_version.h +0 -204
- data/assets/include/SDL2/SDL_video.h +0 -2150
- data/assets/include/SDL2/SDL_vulkan.h +0 -215
- data/assets/include/SDL2/begin_code.h +0 -187
- data/assets/include/SDL2/close_code.h +0 -40
- data/assets/macos/universal/lib/libFLAC.a +0 -0
- data/assets/macos/universal/lib/libSDL2.a +0 -0
- data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
- data/assets/macos/universal/lib/libmodplug.a +0 -0
- data/assets/macos/universal/lib/libmpg123.a +0 -0
- data/assets/macos/universal/lib/libogg.a +0 -0
- data/assets/macos/universal/lib/libvorbis.a +0 -0
- data/assets/macos/universal/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
- data/ext/audio/extconf.h +0 -3
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// reverb_node.c - Schroeder reverb node implementation
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
#include <string.h>
|
|
7
|
+
#include "reverb_node.h"
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Delay Line Helpers
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
// Base delay times in seconds (Schroeder-style, prime-ish ratios)
|
|
14
|
+
static const float COMB_DELAYS[NUM_COMBS] = { 0.0297f, 0.0371f, 0.0411f, 0.0437f };
|
|
15
|
+
static const float ALLPASS_DELAYS[NUM_ALLPASSES] = { 0.005f, 0.0017f };
|
|
16
|
+
|
|
17
|
+
static void delay_line_init(delay_line *dl, ma_uint32 size)
|
|
18
|
+
{
|
|
19
|
+
dl->size = size;
|
|
20
|
+
dl->pos = 0;
|
|
21
|
+
dl->buffer = (float *)calloc(size, sizeof(float));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static void delay_line_free(delay_line *dl)
|
|
25
|
+
{
|
|
26
|
+
if (dl->buffer) {
|
|
27
|
+
free(dl->buffer);
|
|
28
|
+
dl->buffer = NULL;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static inline float delay_line_read(delay_line *dl)
|
|
33
|
+
{
|
|
34
|
+
return dl->buffer[dl->pos];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static inline void delay_line_write(delay_line *dl, float value)
|
|
38
|
+
{
|
|
39
|
+
dl->buffer[dl->pos] = value;
|
|
40
|
+
dl->pos = (dl->pos + 1) % dl->size;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Filter Processing
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
// Comb filter: output = buffer[pos], then write input + feedback * output (with damping)
|
|
48
|
+
static inline float comb_process(delay_line *dl, float input, float feedback,
|
|
49
|
+
float damp, float *damp_prev)
|
|
50
|
+
{
|
|
51
|
+
float output = delay_line_read(dl);
|
|
52
|
+
// Low-pass filter on feedback for damping (high freq decay faster)
|
|
53
|
+
*damp_prev = output * (1.0f - damp) + (*damp_prev) * damp;
|
|
54
|
+
delay_line_write(dl, input + feedback * (*damp_prev));
|
|
55
|
+
return output;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Allpass filter: output = -g*input + buffer[pos], write input + g*buffer[pos]
|
|
59
|
+
static inline float allpass_process(delay_line *dl, float input, float feedback)
|
|
60
|
+
{
|
|
61
|
+
float buffered = delay_line_read(dl);
|
|
62
|
+
float output = buffered - feedback * input;
|
|
63
|
+
delay_line_write(dl, input + feedback * buffered);
|
|
64
|
+
return output;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// DSP Callback
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
static void reverb_process(ma_node *pNode, const float **ppFramesIn,
|
|
72
|
+
ma_uint32 *pFrameCountIn, float **ppFramesOut,
|
|
73
|
+
ma_uint32 *pFrameCountOut)
|
|
74
|
+
{
|
|
75
|
+
reverb_node *node = (reverb_node *)pNode;
|
|
76
|
+
const float *pFramesIn = ppFramesIn[0];
|
|
77
|
+
float *pFramesOut = ppFramesOut[0];
|
|
78
|
+
ma_uint32 frameCount = *pFrameCountOut;
|
|
79
|
+
ma_uint32 numChannels = node->channels;
|
|
80
|
+
|
|
81
|
+
if (!node->enabled) {
|
|
82
|
+
// Bypass: copy input to output
|
|
83
|
+
memcpy(pFramesOut, pFramesIn, frameCount * numChannels * sizeof(float));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for (ma_uint32 iFrame = 0; iFrame < frameCount; iFrame++) {
|
|
88
|
+
for (ma_uint32 iChannel = 0; iChannel < numChannels && iChannel < 2; iChannel++) {
|
|
89
|
+
ma_uint32 sampleIndex = iFrame * numChannels + iChannel;
|
|
90
|
+
float input = pFramesIn[sampleIndex];
|
|
91
|
+
|
|
92
|
+
// Sum of parallel comb filters
|
|
93
|
+
float combSum = 0.0f;
|
|
94
|
+
for (int c = 0; c < NUM_COMBS; c++) {
|
|
95
|
+
combSum += comb_process(&node->combs[iChannel][c], input,
|
|
96
|
+
node->comb_feedback, node->comb_damp,
|
|
97
|
+
&node->comb_damp_prev[iChannel][c]);
|
|
98
|
+
}
|
|
99
|
+
combSum *= 0.25f; // Average the 4 combs
|
|
100
|
+
|
|
101
|
+
// Series allpass filters
|
|
102
|
+
float allpassOut = combSum;
|
|
103
|
+
for (int a = 0; a < NUM_ALLPASSES; a++) {
|
|
104
|
+
allpassOut = allpass_process(&node->allpasses[iChannel][a],
|
|
105
|
+
allpassOut, node->allpass_feedback);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Mix dry and wet
|
|
109
|
+
pFramesOut[sampleIndex] = input * node->dry + allpassOut * node->wet;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Handle mono->stereo or more channels by copying
|
|
113
|
+
for (ma_uint32 iChannel = 2; iChannel < numChannels; iChannel++) {
|
|
114
|
+
ma_uint32 sampleIndex = iFrame * numChannels + iChannel;
|
|
115
|
+
pFramesOut[sampleIndex] = pFramesIn[sampleIndex];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static ma_node_vtable g_reverb_vtable = {
|
|
121
|
+
reverb_process,
|
|
122
|
+
NULL,
|
|
123
|
+
1,
|
|
124
|
+
1,
|
|
125
|
+
0
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// Lifecycle
|
|
130
|
+
// ============================================================================
|
|
131
|
+
|
|
132
|
+
ma_result reverb_init(reverb_node *pNode, ma_node_graph *pNodeGraph,
|
|
133
|
+
ma_uint32 sampleRate, ma_uint32 numChannels)
|
|
134
|
+
{
|
|
135
|
+
if (pNode == NULL) {
|
|
136
|
+
return MA_INVALID_ARGS;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
memset(pNode, 0, sizeof(*pNode));
|
|
140
|
+
pNode->sample_rate = sampleRate;
|
|
141
|
+
pNode->channels = numChannels;
|
|
142
|
+
pNode->enabled = MA_FALSE;
|
|
143
|
+
|
|
144
|
+
// Default parameters
|
|
145
|
+
pNode->room_size = 0.5f;
|
|
146
|
+
pNode->comb_feedback = 0.7f;
|
|
147
|
+
pNode->comb_damp = 0.3f;
|
|
148
|
+
pNode->allpass_feedback = 0.5f;
|
|
149
|
+
pNode->wet = 0.3f;
|
|
150
|
+
pNode->dry = 1.0f;
|
|
151
|
+
|
|
152
|
+
// Initialize delay lines for up to 2 audio channels
|
|
153
|
+
ma_uint32 chans = numChannels < 2 ? numChannels : 2;
|
|
154
|
+
for (ma_uint32 ch = 0; ch < chans; ch++) {
|
|
155
|
+
for (int c = 0; c < NUM_COMBS; c++) {
|
|
156
|
+
ma_uint32 delaySize = (ma_uint32)(COMB_DELAYS[c] * pNode->room_size * 2.0f * sampleRate);
|
|
157
|
+
if (delaySize < 1) delaySize = 1;
|
|
158
|
+
delay_line_init(&pNode->combs[ch][c], delaySize);
|
|
159
|
+
}
|
|
160
|
+
for (int a = 0; a < NUM_ALLPASSES; a++) {
|
|
161
|
+
ma_uint32 delaySize = (ma_uint32)(ALLPASS_DELAYS[a] * sampleRate);
|
|
162
|
+
if (delaySize < 1) delaySize = 1;
|
|
163
|
+
delay_line_init(&pNode->allpasses[ch][a], delaySize);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Set up node
|
|
168
|
+
ma_uint32 channelsArray[1] = { numChannels };
|
|
169
|
+
ma_node_config nodeConfig = ma_node_config_init();
|
|
170
|
+
nodeConfig.vtable = &g_reverb_vtable;
|
|
171
|
+
nodeConfig.pInputChannels = channelsArray;
|
|
172
|
+
nodeConfig.pOutputChannels = channelsArray;
|
|
173
|
+
|
|
174
|
+
return ma_node_init(pNodeGraph, &nodeConfig, NULL, &pNode->base);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
void reverb_uninit(reverb_node *pNode)
|
|
178
|
+
{
|
|
179
|
+
if (pNode == NULL) return;
|
|
180
|
+
|
|
181
|
+
ma_node_uninit(&pNode->base, NULL);
|
|
182
|
+
|
|
183
|
+
for (int ch = 0; ch < 2; ch++) {
|
|
184
|
+
for (int c = 0; c < NUM_COMBS; c++) {
|
|
185
|
+
delay_line_free(&pNode->combs[ch][c]);
|
|
186
|
+
}
|
|
187
|
+
for (int a = 0; a < NUM_ALLPASSES; a++) {
|
|
188
|
+
delay_line_free(&pNode->allpasses[ch][a]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// Parameter Control
|
|
195
|
+
// ============================================================================
|
|
196
|
+
|
|
197
|
+
void reverb_set_enabled(reverb_node *pNode, ma_bool32 enabled)
|
|
198
|
+
{
|
|
199
|
+
if (pNode) pNode->enabled = enabled;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
void reverb_set_room_size(reverb_node *pNode, float size)
|
|
203
|
+
{
|
|
204
|
+
if (pNode == NULL) return;
|
|
205
|
+
pNode->room_size = size;
|
|
206
|
+
// Note: changing room_size after init would require reallocating buffers
|
|
207
|
+
// For now, this affects feedback calculation
|
|
208
|
+
pNode->comb_feedback = 0.6f + size * 0.35f; // 0.6 to 0.95
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
void reverb_set_damping(reverb_node *pNode, float damp)
|
|
212
|
+
{
|
|
213
|
+
if (pNode) pNode->comb_damp = damp;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
void reverb_set_wet(reverb_node *pNode, float wet)
|
|
217
|
+
{
|
|
218
|
+
if (pNode) pNode->wet = wet;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
void reverb_set_dry(reverb_node *pNode, float dry)
|
|
222
|
+
{
|
|
223
|
+
if (pNode) pNode->dry = dry;
|
|
224
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// reverb_node.h - Schroeder reverb node for native_audio
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
#ifndef REVERB_NODE_H
|
|
6
|
+
#define REVERB_NODE_H
|
|
7
|
+
|
|
8
|
+
#include "miniaudio.h"
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Constants
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
#define NUM_COMBS 4
|
|
15
|
+
#define NUM_ALLPASSES 2
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Types
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
typedef struct {
|
|
22
|
+
float *buffer;
|
|
23
|
+
ma_uint32 size;
|
|
24
|
+
ma_uint32 pos;
|
|
25
|
+
} delay_line;
|
|
26
|
+
|
|
27
|
+
typedef struct {
|
|
28
|
+
ma_node_base base;
|
|
29
|
+
ma_uint32 channels;
|
|
30
|
+
ma_uint32 sample_rate;
|
|
31
|
+
|
|
32
|
+
// 4 parallel comb filters per audio channel
|
|
33
|
+
delay_line combs[2][NUM_COMBS]; // [audio_channel][comb_index]
|
|
34
|
+
float comb_feedback;
|
|
35
|
+
float comb_damp;
|
|
36
|
+
float comb_damp_prev[2][NUM_COMBS];
|
|
37
|
+
|
|
38
|
+
// 2 series allpass filters per audio channel
|
|
39
|
+
delay_line allpasses[2][NUM_ALLPASSES];
|
|
40
|
+
float allpass_feedback;
|
|
41
|
+
|
|
42
|
+
// Mix control
|
|
43
|
+
float wet;
|
|
44
|
+
float dry;
|
|
45
|
+
float room_size;
|
|
46
|
+
ma_bool32 enabled;
|
|
47
|
+
} reverb_node;
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Public API
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
ma_result reverb_init(reverb_node *pNode, ma_node_graph *pNodeGraph,
|
|
54
|
+
ma_uint32 sampleRate, ma_uint32 numChannels);
|
|
55
|
+
void reverb_uninit(reverb_node *pNode);
|
|
56
|
+
|
|
57
|
+
void reverb_set_enabled(reverb_node *pNode, ma_bool32 enabled);
|
|
58
|
+
void reverb_set_room_size(reverb_node *pNode, float size);
|
|
59
|
+
void reverb_set_damping(reverb_node *pNode, float damp);
|
|
60
|
+
void reverb_set_wet(reverb_node *pNode, float wet);
|
|
61
|
+
void reverb_set_dry(reverb_node *pNode, float dry);
|
|
62
|
+
|
|
63
|
+
#endif // REVERB_NODE_H
|
data/lib/dummy_audio.rb
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Dummy audio backend for CI/testing environments without audio hardware.
|
|
4
|
+
# Has the same interface as the Audio C extension but does nothing.
|
|
5
|
+
module DummyAudio
|
|
6
|
+
@sound_count = 0
|
|
7
|
+
@tap_counts = {}
|
|
8
|
+
|
|
9
|
+
def self.init
|
|
10
|
+
nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.load(path)
|
|
14
|
+
id = @sound_count
|
|
15
|
+
@sound_count += 1
|
|
16
|
+
id
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.duration(clip)
|
|
20
|
+
5.0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.play(channel, clip)
|
|
24
|
+
@tap_counts[channel] = 0
|
|
25
|
+
channel
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.stop(channel)
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.pause(channel)
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.resume(channel)
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.set_volume(channel, volume)
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.set_pitch(channel, pitch)
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.set_pos(channel, angle, distance)
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.set_looping(channel, looping)
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.add_delay_tap(channel, time_ms, volume)
|
|
57
|
+
@tap_counts[channel] ||= 0
|
|
58
|
+
tap_id = @tap_counts[channel]
|
|
59
|
+
@tap_counts[channel] += 1
|
|
60
|
+
tap_id
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.remove_delay_tap(channel, tap_id)
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.set_delay_tap_volume(channel, tap_id, volume)
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.set_delay_tap_time(channel, tap_id, time_ms)
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.enable_reverb(channel, enabled)
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.set_reverb_room_size(channel, size)
|
|
80
|
+
nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.set_reverb_damping(channel, damp)
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.set_reverb_wet(channel, wet)
|
|
88
|
+
nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.set_reverb_dry(channel, dry)
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
end
|
data/lib/native_audio.rb
CHANGED
|
@@ -1,46 +1,117 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative './audio'
|
|
4
|
+
require_relative './dummy_audio'
|
|
5
|
+
|
|
6
|
+
Audio.init unless ENV['DUMMY_AUDIO_BACKEND'] == 'true'
|
|
4
7
|
|
|
5
8
|
module NativeAudio
|
|
9
|
+
def self.audio_driver
|
|
10
|
+
ENV['DUMMY_AUDIO_BACKEND'] == 'true' ? DummyAudio : Audio
|
|
11
|
+
end
|
|
12
|
+
|
|
6
13
|
class Clip
|
|
7
14
|
attr_reader :clip
|
|
8
15
|
|
|
9
16
|
def initialize(path)
|
|
10
17
|
@path = path
|
|
11
|
-
@clip =
|
|
18
|
+
@clip = NativeAudio.audio_driver.load(path)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def duration
|
|
22
|
+
NativeAudio.audio_driver.duration(@clip)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class DelayTap
|
|
27
|
+
attr_reader :id, :audio_source, :time_ms, :volume
|
|
28
|
+
|
|
29
|
+
def initialize(audio_source, id, time_ms, volume)
|
|
30
|
+
@audio_source = audio_source
|
|
31
|
+
@id = id
|
|
32
|
+
@time_ms = time_ms
|
|
33
|
+
@volume = volume
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def volume=(val)
|
|
37
|
+
NativeAudio.audio_driver.set_delay_tap_volume(@audio_source.channel, @id, val)
|
|
38
|
+
@volume = val
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def time_ms=(val)
|
|
42
|
+
NativeAudio.audio_driver.set_delay_tap_time(@audio_source.channel, @id, val)
|
|
43
|
+
@time_ms = val
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def remove
|
|
47
|
+
NativeAudio.audio_driver.remove_delay_tap(@audio_source.channel, @id)
|
|
48
|
+
@audio_source.delay_taps.delete(self)
|
|
12
49
|
end
|
|
13
50
|
end
|
|
14
51
|
|
|
15
52
|
class AudioSource
|
|
53
|
+
attr_reader :channel
|
|
54
|
+
|
|
16
55
|
def initialize(clip)
|
|
17
56
|
@clip = clip
|
|
18
57
|
@channel = AudioSource.channels.count
|
|
58
|
+
@delay_taps = []
|
|
19
59
|
AudioSource.channels << self
|
|
20
60
|
end
|
|
21
61
|
|
|
22
62
|
def play
|
|
23
|
-
|
|
63
|
+
NativeAudio.audio_driver.play(@channel, @clip.clip)
|
|
24
64
|
end
|
|
25
65
|
|
|
26
66
|
def stop
|
|
27
|
-
|
|
67
|
+
NativeAudio.audio_driver.stop(@channel)
|
|
28
68
|
end
|
|
29
69
|
|
|
30
70
|
def pause
|
|
31
|
-
|
|
71
|
+
NativeAudio.audio_driver.pause(@channel)
|
|
32
72
|
end
|
|
33
73
|
|
|
34
74
|
def resume
|
|
35
|
-
|
|
75
|
+
NativeAudio.audio_driver.resume(@channel)
|
|
36
76
|
end
|
|
37
77
|
|
|
38
78
|
def set_pos(angle, distance)
|
|
39
|
-
|
|
79
|
+
NativeAudio.audio_driver.set_pos(@channel, angle, distance)
|
|
40
80
|
end
|
|
41
81
|
|
|
42
82
|
def set_volume(volume)
|
|
43
|
-
|
|
83
|
+
NativeAudio.audio_driver.set_volume(@channel, volume)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def set_pitch(pitch)
|
|
87
|
+
NativeAudio.audio_driver.set_pitch(@channel, pitch)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def set_looping(looping)
|
|
91
|
+
NativeAudio.audio_driver.set_looping(@channel, looping)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def add_delay_tap(time_ms:, volume:)
|
|
95
|
+
tap_id = NativeAudio.audio_driver.add_delay_tap(@channel, time_ms, volume)
|
|
96
|
+
tap = DelayTap.new(self, tap_id, time_ms, volume)
|
|
97
|
+
@delay_taps << tap
|
|
98
|
+
tap
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def enable_reverb(enabled = true)
|
|
102
|
+
NativeAudio.audio_driver.enable_reverb(@channel, enabled)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def set_reverb(room_size: 0.5, damping: 0.3, wet: 0.3, dry: 1.0)
|
|
106
|
+
NativeAudio.audio_driver.enable_reverb(@channel, true)
|
|
107
|
+
NativeAudio.audio_driver.set_reverb_room_size(@channel, room_size)
|
|
108
|
+
NativeAudio.audio_driver.set_reverb_damping(@channel, damping)
|
|
109
|
+
NativeAudio.audio_driver.set_reverb_wet(@channel, wet)
|
|
110
|
+
NativeAudio.audio_driver.set_reverb_dry(@channel, dry)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def delay_taps
|
|
114
|
+
@delay_taps
|
|
44
115
|
end
|
|
45
116
|
|
|
46
117
|
def self.channels
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: native_audio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Max Hatfull
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
description: A simple audio library for Ruby
|
|
13
13
|
email:
|
|
@@ -17,137 +17,17 @@ extensions:
|
|
|
17
17
|
- ext/audio/extconf.rb
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- assets/include/SDL2/SDL_atomic.h
|
|
23
|
-
- assets/include/SDL2/SDL_audio.h
|
|
24
|
-
- assets/include/SDL2/SDL_bits.h
|
|
25
|
-
- assets/include/SDL2/SDL_blendmode.h
|
|
26
|
-
- assets/include/SDL2/SDL_clipboard.h
|
|
27
|
-
- assets/include/SDL2/SDL_config.h
|
|
28
|
-
- assets/include/SDL2/SDL_config_android.h
|
|
29
|
-
- assets/include/SDL2/SDL_config_emscripten.h
|
|
30
|
-
- assets/include/SDL2/SDL_config_iphoneos.h
|
|
31
|
-
- assets/include/SDL2/SDL_config_macosx.h
|
|
32
|
-
- assets/include/SDL2/SDL_config_minimal.h
|
|
33
|
-
- assets/include/SDL2/SDL_config_ngage.h
|
|
34
|
-
- assets/include/SDL2/SDL_config_os2.h
|
|
35
|
-
- assets/include/SDL2/SDL_config_pandora.h
|
|
36
|
-
- assets/include/SDL2/SDL_config_windows.h
|
|
37
|
-
- assets/include/SDL2/SDL_config_wingdk.h
|
|
38
|
-
- assets/include/SDL2/SDL_config_winrt.h
|
|
39
|
-
- assets/include/SDL2/SDL_config_xbox.h
|
|
40
|
-
- assets/include/SDL2/SDL_copying.h
|
|
41
|
-
- assets/include/SDL2/SDL_cpuinfo.h
|
|
42
|
-
- assets/include/SDL2/SDL_egl.h
|
|
43
|
-
- assets/include/SDL2/SDL_endian.h
|
|
44
|
-
- assets/include/SDL2/SDL_error.h
|
|
45
|
-
- assets/include/SDL2/SDL_events.h
|
|
46
|
-
- assets/include/SDL2/SDL_filesystem.h
|
|
47
|
-
- assets/include/SDL2/SDL_gamecontroller.h
|
|
48
|
-
- assets/include/SDL2/SDL_gesture.h
|
|
49
|
-
- assets/include/SDL2/SDL_guid.h
|
|
50
|
-
- assets/include/SDL2/SDL_haptic.h
|
|
51
|
-
- assets/include/SDL2/SDL_hidapi.h
|
|
52
|
-
- assets/include/SDL2/SDL_hints.h
|
|
53
|
-
- assets/include/SDL2/SDL_image.h
|
|
54
|
-
- assets/include/SDL2/SDL_joystick.h
|
|
55
|
-
- assets/include/SDL2/SDL_keyboard.h
|
|
56
|
-
- assets/include/SDL2/SDL_keycode.h
|
|
57
|
-
- assets/include/SDL2/SDL_loadso.h
|
|
58
|
-
- assets/include/SDL2/SDL_locale.h
|
|
59
|
-
- assets/include/SDL2/SDL_log.h
|
|
60
|
-
- assets/include/SDL2/SDL_main.h
|
|
61
|
-
- assets/include/SDL2/SDL_messagebox.h
|
|
62
|
-
- assets/include/SDL2/SDL_metal.h
|
|
63
|
-
- assets/include/SDL2/SDL_misc.h
|
|
64
|
-
- assets/include/SDL2/SDL_mixer.h
|
|
65
|
-
- assets/include/SDL2/SDL_mouse.h
|
|
66
|
-
- assets/include/SDL2/SDL_mutex.h
|
|
67
|
-
- assets/include/SDL2/SDL_name.h
|
|
68
|
-
- assets/include/SDL2/SDL_opengl.h
|
|
69
|
-
- assets/include/SDL2/SDL_opengl_glext.h
|
|
70
|
-
- assets/include/SDL2/SDL_opengles.h
|
|
71
|
-
- assets/include/SDL2/SDL_opengles2.h
|
|
72
|
-
- assets/include/SDL2/SDL_opengles2_gl2.h
|
|
73
|
-
- assets/include/SDL2/SDL_opengles2_gl2ext.h
|
|
74
|
-
- assets/include/SDL2/SDL_opengles2_gl2platform.h
|
|
75
|
-
- assets/include/SDL2/SDL_opengles2_khrplatform.h
|
|
76
|
-
- assets/include/SDL2/SDL_pixels.h
|
|
77
|
-
- assets/include/SDL2/SDL_platform.h
|
|
78
|
-
- assets/include/SDL2/SDL_power.h
|
|
79
|
-
- assets/include/SDL2/SDL_quit.h
|
|
80
|
-
- assets/include/SDL2/SDL_rect.h
|
|
81
|
-
- assets/include/SDL2/SDL_render.h
|
|
82
|
-
- assets/include/SDL2/SDL_revision.h
|
|
83
|
-
- assets/include/SDL2/SDL_rwops.h
|
|
84
|
-
- assets/include/SDL2/SDL_scancode.h
|
|
85
|
-
- assets/include/SDL2/SDL_sensor.h
|
|
86
|
-
- assets/include/SDL2/SDL_shape.h
|
|
87
|
-
- assets/include/SDL2/SDL_stdinc.h
|
|
88
|
-
- assets/include/SDL2/SDL_surface.h
|
|
89
|
-
- assets/include/SDL2/SDL_system.h
|
|
90
|
-
- assets/include/SDL2/SDL_syswm.h
|
|
91
|
-
- assets/include/SDL2/SDL_test.h
|
|
92
|
-
- assets/include/SDL2/SDL_test_assert.h
|
|
93
|
-
- assets/include/SDL2/SDL_test_common.h
|
|
94
|
-
- assets/include/SDL2/SDL_test_compare.h
|
|
95
|
-
- assets/include/SDL2/SDL_test_crc32.h
|
|
96
|
-
- assets/include/SDL2/SDL_test_font.h
|
|
97
|
-
- assets/include/SDL2/SDL_test_fuzzer.h
|
|
98
|
-
- assets/include/SDL2/SDL_test_harness.h
|
|
99
|
-
- assets/include/SDL2/SDL_test_images.h
|
|
100
|
-
- assets/include/SDL2/SDL_test_log.h
|
|
101
|
-
- assets/include/SDL2/SDL_test_md5.h
|
|
102
|
-
- assets/include/SDL2/SDL_test_memory.h
|
|
103
|
-
- assets/include/SDL2/SDL_test_random.h
|
|
104
|
-
- assets/include/SDL2/SDL_thread.h
|
|
105
|
-
- assets/include/SDL2/SDL_timer.h
|
|
106
|
-
- assets/include/SDL2/SDL_touch.h
|
|
107
|
-
- assets/include/SDL2/SDL_ttf.h
|
|
108
|
-
- assets/include/SDL2/SDL_types.h
|
|
109
|
-
- assets/include/SDL2/SDL_version.h
|
|
110
|
-
- assets/include/SDL2/SDL_video.h
|
|
111
|
-
- assets/include/SDL2/SDL_vulkan.h
|
|
112
|
-
- assets/include/SDL2/begin_code.h
|
|
113
|
-
- assets/include/SDL2/close_code.h
|
|
114
|
-
- assets/macos/universal/lib/libFLAC.a
|
|
115
|
-
- assets/macos/universal/lib/libSDL2.a
|
|
116
|
-
- assets/macos/universal/lib/libSDL2_mixer.a
|
|
117
|
-
- assets/macos/universal/lib/libmodplug.a
|
|
118
|
-
- assets/macos/universal/lib/libmpg123.a
|
|
119
|
-
- assets/macos/universal/lib/libogg.a
|
|
120
|
-
- assets/macos/universal/lib/libvorbis.a
|
|
121
|
-
- assets/macos/universal/lib/libvorbisfile.a
|
|
122
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a
|
|
123
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a
|
|
124
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a
|
|
125
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a
|
|
126
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a
|
|
127
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a
|
|
128
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a
|
|
129
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a
|
|
130
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a
|
|
131
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a
|
|
132
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a
|
|
133
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a
|
|
134
|
-
- assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a
|
|
135
|
-
- assets/windows/mingw-w64-x86_64/lib/libFLAC.a
|
|
136
|
-
- assets/windows/mingw-w64-x86_64/lib/libSDL2.a
|
|
137
|
-
- assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a
|
|
138
|
-
- assets/windows/mingw-w64-x86_64/lib/libmodplug.a
|
|
139
|
-
- assets/windows/mingw-w64-x86_64/lib/libmpg123.a
|
|
140
|
-
- assets/windows/mingw-w64-x86_64/lib/libogg.a
|
|
141
|
-
- assets/windows/mingw-w64-x86_64/lib/libopus.a
|
|
142
|
-
- assets/windows/mingw-w64-x86_64/lib/libopusfile.a
|
|
143
|
-
- assets/windows/mingw-w64-x86_64/lib/libsndfile.a
|
|
144
|
-
- assets/windows/mingw-w64-x86_64/lib/libstdc++.a
|
|
145
|
-
- assets/windows/mingw-w64-x86_64/lib/libvorbis.a
|
|
146
|
-
- assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a
|
|
147
|
-
- assets/windows/mingw-w64-x86_64/lib/libz.a
|
|
20
|
+
- LICENSE
|
|
21
|
+
- README.md
|
|
148
22
|
- ext/audio/audio.c
|
|
149
|
-
- ext/audio/
|
|
23
|
+
- ext/audio/audio.h
|
|
24
|
+
- ext/audio/delay_node.c
|
|
25
|
+
- ext/audio/delay_node.h
|
|
150
26
|
- ext/audio/extconf.rb
|
|
27
|
+
- ext/audio/miniaudio.h
|
|
28
|
+
- ext/audio/reverb_node.c
|
|
29
|
+
- ext/audio/reverb_node.h
|
|
30
|
+
- lib/dummy_audio.rb
|
|
151
31
|
- lib/native_audio.rb
|
|
152
32
|
homepage: https://github.com/rubyrpg/native_audio
|
|
153
33
|
licenses:
|
|
@@ -167,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
167
47
|
- !ruby/object:Gem::Version
|
|
168
48
|
version: '0'
|
|
169
49
|
requirements: []
|
|
170
|
-
rubygems_version:
|
|
50
|
+
rubygems_version: 4.0.3
|
|
171
51
|
specification_version: 4
|
|
172
52
|
summary: A simple audio library for Ruby
|
|
173
53
|
test_files: []
|