bird
[vg.git] / vg_audio.h
1 /* Copyright (C) 2021-2023 Harry Godden (hgn) - All Rights Reserved */
2
3 #ifndef VG_AUDIO_H
4 #define VG_AUDIO_H
5
6 #define VG_GAME
7
8 #include "vg/vg.h"
9 #include "vg/vg_stdint.h"
10 #include "vg/vg_platform.h"
11 #include "vg/vg_io.h"
12 #include "vg/vg_m.h"
13 #include "vg/vg_ui.h"
14 #include "vg/vg_console.h"
15 #include "vg/vg_store.h"
16 #include "vg/vg_profiler.h"
17
18 #include <sys/time.h>
19 #include <math.h>
20
21 #ifdef __GNUC__
22 #ifndef __clang__
23 #pragma GCC push_options
24 #pragma GCC optimize ("O3")
25 #pragma GCC diagnostic push
26 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
27 #endif
28 #endif
29
30 #define STB_VORBIS_MAX_CHANNELS 2
31 #include "submodules/stb/stb_vorbis.c"
32 #undef L
33 #undef R
34 #undef C
35
36 #ifdef __GNUC__
37 #ifndef __clang__
38 #pragma GCC pop_options
39 #pragma GCC diagnostic pop
40 #endif
41 #endif
42
43 #define AUDIO_FRAME_SIZE 512
44 #define AUDIO_MIX_FRAME_SIZE 256
45
46 #define AUDIO_CHANNELS 32
47 #define AUDIO_LFOS 8
48 #define AUDIO_FILTERS 16
49 #define AUDIO_FLAG_LOOP 0x1
50 #define AUDIO_FLAG_SPACIAL_3D 0x4
51 #define AUDIO_FLAG_AUTO_START 0x8
52
53 /* Vorbis will ALWAYS use the maximum amount of channels it can */
54 //#define AUDIO_FLAG_MONO 0x100 NOTE: This is the default, so its not used
55 #define AUDIO_FLAG_STEREO 0x200
56 #define AUDIO_FLAG_VORBIS 0x400
57
58 #define AUDIO_DECODE_SIZE (1024*256) /* 256 kb decoding buffers */
59 #define AUDIO_MUTE_VOLUME 0.0f
60 #define AUDIO_BASE_VOLUME 1.0f
61
62 typedef struct audio_clip audio_clip;
63 typedef struct audio_channel audio_channel;
64 typedef struct audio_lfo audio_lfo;
65
66 struct audio_clip
67 {
68 const char *path;
69 u32 flags;
70
71 u32 size;
72 void *data;
73 };
74
75 static struct vg_audio_system
76 {
77 SDL_AudioDeviceID sdl_output_device;
78
79 void *audio_pool,
80 *decode_buffer;
81 u32 samples_last;
82
83 /* synchro */
84 int sync_locked;
85
86 SDL_mutex *mux_checker,
87 *mux_sync;
88
89 struct audio_lfo
90 {
91 u32 time, time_startframe;
92 float sqrt_polynomial_coefficient;
93
94 struct
95 {
96 enum lfo_wave_type
97 {
98 k_lfo_triangle,
99 k_lfo_square,
100 k_lfo_saw,
101 k_lfo_polynomial_bipolar
102 }
103 wave_type;
104
105 u32 period;
106 float polynomial_coefficient;
107 }
108 _, editable_state;
109 u32 editble_state_write_mask;
110 }
111 oscillators[ AUDIO_LFOS ];
112
113 struct audio_channel
114 {
115 int allocated;
116 char name[32]; /* only editable while allocated == 0 */
117 audio_clip *source; /* ... */
118 u32 flags; /* ... */
119 u32 colour; /* ... */
120
121 /* internal non-readable state
122 * -----------------------------*/
123 u32 cursor, source_length;
124
125 float volume_movement_start,
126 pan_movement_start;
127
128 u32 volume_movement,
129 pan_movement;
130
131 stb_vorbis *vorbis_handle;
132 stb_vorbis_alloc vorbis_alloc;
133
134 enum channel_activity
135 {
136 k_channel_activity_reset, /* will advance if allocated==1, to wake */
137 k_channel_activity_wake, /* will advance to either of next two */
138 k_channel_activity_alive,
139 k_channel_activity_end,
140 k_channel_activity_error
141 }
142 activity,
143 readable_activity;
144
145 /*
146 * editable structure, can be modified inside _lock and _unlock
147 * the edit mask tells which to copy into internal _, or to discard
148 * ----------------------------------------------------------------------
149 */
150 struct channel_state
151 {
152 int relinquished;
153
154 float volume, /* current volume */
155 volume_target, /* target volume */
156 pan,
157 pan_target,
158 sampling_rate;
159
160 u32 volume_rate,
161 pan_rate;
162
163 v4f spacial_falloff; /* xyz, range */
164
165 audio_lfo *lfo;
166 float lfo_amount;
167 }
168 _, editable_state;
169 u32 editble_state_write_mask;
170 }
171 channels[ AUDIO_CHANNELS ];
172
173 /* System queue, and access from thread 0 */
174 int debug_ui, debug_ui_3d;
175
176 v3f listener_pos,
177 listener_ears;
178
179 float volume,
180 volume_target,
181 volume_target_internal,
182 volume_console;
183 }
184 vg_audio = { .volume_console = 1.0f };
185
186 #include "vg/vg_audio_dsp.h"
187
188 static struct vg_profile
189 _vg_prof_audio_decode = {.mode = k_profile_mode_accum,
190 .name = "[T2] audio_decode()"},
191 _vg_prof_audio_mix = {.mode = k_profile_mode_accum,
192 .name = "[T2] audio_mix()"},
193 _vg_prof_dsp = {.mode = k_profile_mode_accum,
194 .name = "[T2] dsp_process()"},
195 vg_prof_audio_decode,
196 vg_prof_audio_mix,
197 vg_prof_audio_dsp;
198
199 /*
200 * These functions are called from the main thread and used to prevent bad
201 * access. TODO: They should be no-ops in release builds.
202 */
203 VG_STATIC int audio_lock_checker_load(void)
204 {
205 int value;
206 SDL_LockMutex( vg_audio.mux_checker );
207 value = vg_audio.sync_locked;
208 SDL_UnlockMutex( vg_audio.mux_checker );
209 return value;
210 }
211
212 VG_STATIC void audio_lock_checker_store( int value )
213 {
214 SDL_LockMutex( vg_audio.mux_checker );
215 vg_audio.sync_locked = value;
216 SDL_UnlockMutex( vg_audio.mux_checker );
217 }
218
219 VG_STATIC void audio_require_lock(void)
220 {
221 if( audio_lock_checker_load() )
222 return;
223
224 vg_error( "Modifying sound effects systems requires locking\n" );
225 abort();
226 }
227
228 VG_STATIC void audio_lock(void)
229 {
230 SDL_LockMutex( vg_audio.mux_sync );
231 audio_lock_checker_store(1);
232 }
233
234 VG_STATIC void audio_unlock(void)
235 {
236 audio_lock_checker_store(0);
237 SDL_UnlockMutex( vg_audio.mux_sync );
238 }
239
240 VG_STATIC void audio_mixer_callback( void *user, u8 *stream, int frame_count );
241 VG_STATIC void vg_audio_init(void)
242 {
243 vg_audio.mux_checker = SDL_CreateMutex();
244 vg_audio.mux_sync = SDL_CreateMutex();
245
246 /* TODO: Move here? */
247 vg_var_push( (struct vg_var){
248 .name = "debug_audio",
249 .data = &vg_audio.debug_ui,
250 .data_type = k_var_dtype_i32,
251 .opt_i32 = { .min=0, .max=1, .clamp=1 },
252 .persistent = 1
253 });
254
255 vg_var_push( (struct vg_var){
256 .name = "volume",
257 .data = &vg_audio.volume_console,
258 .data_type = k_var_dtype_f32,
259 .opt_f32 = { .min=0.0f, .max=2.0f, .clamp=1 },
260 .persistent = 1
261 });
262
263 /* allocate memory */
264
265 /* 32mb fixed */
266 vg_audio.audio_pool =
267 vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32,
268 VG_MEMORY_SYSTEM );
269
270 /* fixed */
271 u32 decode_size = AUDIO_DECODE_SIZE * AUDIO_CHANNELS;
272 vg_audio.decode_buffer = vg_linear_alloc( vg_mem.rtmemory, decode_size );
273
274 vg_dsp_init();
275
276 SDL_AudioSpec spec_desired, spec_got;
277 spec_desired.callback = audio_mixer_callback;
278 spec_desired.channels = 2;
279 spec_desired.format = AUDIO_F32;
280 spec_desired.freq = 44100;
281 spec_desired.padding = 0;
282 spec_desired.samples = AUDIO_FRAME_SIZE;
283 spec_desired.silence = 0;
284 spec_desired.size = 0;
285 spec_desired.userdata = NULL;
286
287 vg_audio.sdl_output_device =
288 SDL_OpenAudioDevice( NULL, 0, &spec_desired, &spec_got,0 );
289
290 if( vg_audio.sdl_output_device )
291 {
292 SDL_PauseAudioDevice( vg_audio.sdl_output_device, 0 );
293 }
294 else
295 {
296 vg_fatal_exit_loop(
297 "SDL_OpenAudioDevice failed. Your default audio device must support:\n"
298 " Frequency: 44100 hz\n"
299 " Buffer size: 512\n"
300 " Channels: 2\n"
301 " Format: s16 or f32\n" );
302 }
303
304 vg_success( "Ready\n" );
305 }
306
307 VG_STATIC void vg_audio_free(void)
308 {
309 vg_dsp_free();
310 SDL_CloseAudioDevice( vg_audio.sdl_output_device );
311 }
312
313 /*
314 * thread 1
315 */
316
317 #define AUDIO_EDIT_VOLUME_SLOPE 0x1
318 #define AUDIO_EDIT_VOLUME 0x2
319 #define AUDIO_EDIT_LFO_PERIOD 0x4
320 #define AUDIO_EDIT_LFO_WAVE 0x8
321 #define AUDIO_EDIT_LFO_ATTACHMENT 0x10
322 #define AUDIO_EDIT_SPACIAL 0x20
323 #define AUDIO_EDIT_OWNERSHIP 0x40
324 #define AUDIO_EDIT_SAMPLING_RATE 0x80
325
326 static audio_channel *audio_request_channel( audio_clip *clip, u32 flags )
327 {
328 for( int i=0; i<AUDIO_CHANNELS; i++ )
329 {
330 audio_channel *ch = &vg_audio.channels[i];
331
332 if( !ch->allocated )
333 {
334 ch->source = clip;
335 ch->flags = flags;
336 ch->colour = 0x00333333;
337 strcpy( ch->name, clip->path );
338
339 ch->allocated = 1;
340
341 ch->editable_state.relinquished = 0;
342 ch->editable_state.volume = 1.0f;
343 ch->editable_state.volume_target = 1.0f;
344 ch->editable_state.pan = 0.0f;
345 ch->editable_state.pan_target = 0.0f;
346 ch->editable_state.volume_rate = 0;
347 ch->editable_state.pan_rate = 0;
348 v4_copy((v4f){0.0f,0.0f,0.0f,1.0f},ch->editable_state.spacial_falloff);
349 ch->editable_state.lfo = NULL;
350 ch->editable_state.lfo_amount = 0.0f;
351 ch->editable_state.sampling_rate = 1.0f;
352 ch->editble_state_write_mask = 0x00;
353 return ch;
354 }
355 }
356
357 return NULL;
358 }
359
360 static int audio_channel_finished( audio_channel *ch )
361 {
362 if( ch->readable_activity == k_channel_activity_end )
363 return 1;
364 else
365 return 0;
366 }
367
368 static audio_channel *audio_relinquish_channel( audio_channel *ch )
369 {
370 ch->editable_state.relinquished = 1;
371 ch->editble_state_write_mask |= AUDIO_EDIT_OWNERSHIP;
372 return NULL;
373 }
374
375 static void audio_channel_slope_volume( audio_channel *ch, float length,
376 float new_volume )
377 {
378 ch->editable_state.volume_target = new_volume;
379 ch->editable_state.volume_rate = length * 44100.0f;
380 ch->editble_state_write_mask |= AUDIO_EDIT_VOLUME_SLOPE;
381 }
382
383 static void audio_channel_set_sampling_rate( audio_channel *ch, float rate )
384 {
385 ch->editable_state.sampling_rate = rate;
386 ch->editble_state_write_mask |= AUDIO_EDIT_SAMPLING_RATE;
387 }
388
389 static void audio_channel_edit_volume( audio_channel *ch,
390 float new_volume, int instant )
391 {
392 if( instant )
393 {
394 ch->editable_state.volume = new_volume;
395 ch->editble_state_write_mask |= AUDIO_EDIT_VOLUME;
396 }
397 else
398 {
399 audio_channel_slope_volume( ch, 0.05f, new_volume );
400 }
401 }
402
403 static audio_channel *audio_channel_fadeout( audio_channel *ch, float length )
404 {
405 audio_channel_slope_volume( ch, length, 0.0f );
406 return audio_relinquish_channel( ch );
407 }
408
409 static void audio_channel_fadein( audio_channel *ch, float length )
410 {
411 audio_channel_edit_volume( ch, 0.0f, 1 );
412 audio_channel_slope_volume( ch, length, 1.0f );
413 }
414
415 static audio_channel *audio_channel_crossfade( audio_channel *ch,
416 audio_clip *new_clip,
417 float length, u32 flags )
418 {
419 u32 cursor = 0;
420
421 if( ch )
422 ch = audio_channel_fadeout( ch, length );
423
424 audio_channel *replacement = audio_request_channel( new_clip, flags );
425
426 if( replacement )
427 audio_channel_fadein( replacement, length );
428
429 return replacement;
430 }
431
432 static void audio_channel_sidechain_lfo( audio_channel *ch, int lfo_id,
433 float amount )
434 {
435 ch->editable_state.lfo = &vg_audio.oscillators[ lfo_id ];
436 ch->editable_state.lfo_amount = amount;
437 ch->editble_state_write_mask |= AUDIO_EDIT_LFO_ATTACHMENT;
438 }
439
440 static void audio_channel_set_spacial( audio_channel *ch, v3f co, float range )
441 {
442 if( ch->flags & AUDIO_FLAG_SPACIAL_3D )
443 {
444 v3_copy( co, ch->editable_state.spacial_falloff );
445
446 if( range == 0.0f )
447 ch->editable_state.spacial_falloff[3] = 1.0f;
448 else
449 ch->editable_state.spacial_falloff[3] = 1.0f/range;
450
451 ch->editble_state_write_mask |= AUDIO_EDIT_SPACIAL;
452 }
453 else
454 {
455 vg_warn( "Tried to set spacialization paramaters for 2D channel (%s)\n",
456 ch->name );
457 }
458 }
459
460 static int audio_oneshot_3d( audio_clip *clip, v3f position,
461 float range, float volume )
462 {
463 audio_channel *ch = audio_request_channel( clip, AUDIO_FLAG_SPACIAL_3D );
464
465 if( ch )
466 {
467 audio_channel_set_spacial( ch, position, range );
468 audio_channel_edit_volume( ch, volume, 1 );
469 ch = audio_relinquish_channel( ch );
470
471 return 1;
472 }
473 else
474 return 0;
475 }
476
477 static int audio_oneshot( audio_clip *clip, float volume, float pan )
478 {
479 audio_channel *ch = audio_request_channel( clip, 0x00 );
480
481 if( ch )
482 {
483 audio_channel_edit_volume( ch, volume, 1 );
484 ch = audio_relinquish_channel( ch );
485
486 return 1;
487 }
488 else
489 return 0;
490 }
491
492 static void audio_set_lfo_wave( int id, enum lfo_wave_type type,
493 float coefficient )
494 {
495 audio_lfo *lfo = &vg_audio.oscillators[ id ];
496 lfo->editable_state.polynomial_coefficient = coefficient;
497 lfo->editable_state.wave_type = type;
498
499 lfo->editble_state_write_mask |= AUDIO_EDIT_LFO_WAVE;
500 }
501
502 static void audio_set_lfo_frequency( int id, float freq )
503 {
504 audio_lfo *lfo = &vg_audio.oscillators[ id ];
505 lfo->editable_state.period = 44100.0f / freq;
506 lfo->editble_state_write_mask |= AUDIO_EDIT_LFO_PERIOD;
507 }
508
509 /*
510 * Committers
511 * -----------------------------------------------------------------------------
512 */
513 static int audio_channel_load_source( audio_channel *ch )
514 {
515 if( ch->source->flags & AUDIO_FLAG_VORBIS )
516 {
517 /* Setup vorbis decoder */
518 u32 index = ch - vg_audio.channels;
519
520 u8 *buf = (u8*)vg_audio.decode_buffer,
521 *loc = &buf[AUDIO_DECODE_SIZE*index];
522
523 stb_vorbis_alloc alloc = {
524 .alloc_buffer = (char *)loc,
525 .alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE
526 };
527
528 int err;
529 stb_vorbis *decoder = stb_vorbis_open_memory(
530 ch->source->data,
531 ch->source->size, &err, &alloc );
532
533 if( !decoder )
534 {
535 vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n",
536 ch->source->path, err );
537 return 0;
538 }
539 else
540 {
541 ch->source_length = stb_vorbis_stream_length_in_samples( decoder );
542 ch->vorbis_handle = decoder;
543 }
544 }
545 else if( ch->source->flags & AUDIO_FLAG_STEREO )
546 {
547 ch->source_length = ch->source->size / 2;
548 }
549 else
550 {
551 ch->source_length = ch->source->size;
552 }
553
554 return 1;
555 }
556
557 VG_STATIC void audio_decode_uncompressed_mono( i16 *src, u32 count, float *dst )
558 {
559 for( u32 i=0; i<count; i++ )
560 {
561 dst[ i*2 + 0 ] = ((float)src[i]) * (1.0f/32767.0f);
562 dst[ i*2 + 1 ] = ((float)src[i]) * (1.0f/32767.0f);
563 }
564 }
565
566 /*
567 * adapted from stb_vorbis.h, since the original does not handle mono->stereo
568 */
569 VG_STATIC int
570 stb_vorbis_get_samples_float_interleaved_stereo( stb_vorbis *f, float *buffer,
571 int len )
572 {
573 int n = 0,
574 c = VG_MIN( 1, f->channels - 1 );
575
576 while( n < len )
577 {
578 int k = f->channel_buffer_end - f->channel_buffer_start;
579
580 if( n+k >= len )
581 k = len - n;
582
583 for( int j=0; j < k; ++j )
584 {
585 *buffer++ = f->channel_buffers[ 0 ][f->channel_buffer_start+j];
586 *buffer++ = f->channel_buffers[ c ][f->channel_buffer_start+j];
587 }
588
589 n += k;
590 f->channel_buffer_start += k;
591
592 if( n == len )
593 break;
594
595 if( !stb_vorbis_get_frame_float( f, NULL, NULL ))
596 break;
597 }
598
599 return n;
600 }
601
602 /*
603 * ........ more wrecked code sorry!
604 */
605 VG_STATIC int
606 stb_vorbis_get_samples_i16_downmixed( stb_vorbis *f, i16 *buffer, int len )
607 {
608 int n = 0,
609 c = VG_MIN( 1, f->channels - 1 );
610
611 while( n < len )
612 {
613 int k = f->channel_buffer_end - f->channel_buffer_start;
614
615 if( n+k >= len )
616 k = len - n;
617
618 for( int j=0; j < k; ++j )
619 {
620 float sl = f->channel_buffers[ 0 ][f->channel_buffer_start+j],
621 sr = f->channel_buffers[ c ][f->channel_buffer_start+j];
622
623 *buffer++ = vg_clampf( 0.5f*(sl+sr), -1.0f, 1.0f ) * 32767.0f;
624 //*buffer++ = vg_clampf( sr, -1.0f, 1.0f ) * 32767.0f;
625 }
626
627 n += k;
628 f->channel_buffer_start += k;
629
630 if( n == len )
631 break;
632
633 if( !stb_vorbis_get_frame_float( f, NULL, NULL ))
634 break;
635 }
636
637 return n;
638 }
639
640 static inline float audio_lfo_pull_sample( audio_lfo *lfo )
641 {
642 lfo->time ++;
643
644 if( lfo->time >= lfo->_.period )
645 lfo->time = 0;
646
647 float t = lfo->time;
648 t /= (float)lfo->_.period;
649
650 if( lfo->_.wave_type == k_lfo_polynomial_bipolar )
651 {
652 /*
653 * #
654 * # #
655 * # #
656 * # #
657 * ### # ###
658 * ## #
659 * # #
660 * # #
661 * ##
662 */
663
664 t *= 2.0f;
665 t -= 1.0f;
666
667 return (( 2.0f * lfo->sqrt_polynomial_coefficient * t ) /
668 /* --------------------------------------- */
669 ( 1.0f + lfo->_.polynomial_coefficient * t*t )
670
671 ) * (1.0f-fabsf(t));
672 }
673 else
674 {
675 return 0.0f;
676 }
677 }
678
679 static void audio_channel_get_samples( audio_channel *ch,
680 u32 count, float *buf )
681 {
682 vg_profile_begin( &_vg_prof_audio_decode );
683
684 u32 remaining = count;
685 u32 buffer_pos = 0;
686
687 while( remaining )
688 {
689 u32 samples_this_run = VG_MIN( remaining, ch->source_length -ch->cursor );
690 remaining -= samples_this_run;
691
692 float *dst = &buf[ buffer_pos * 2 ];
693
694 if( ch->source->flags & AUDIO_FLAG_STEREO )
695 {
696 for( int i=0;i<samples_this_run; i++ )
697 {
698 dst[i*2+0] = 0.0f;
699 dst[i*2+1] = 0.0f;
700 }
701 }
702 else if( ch->source->flags & AUDIO_FLAG_VORBIS )
703 {
704 int read_samples = stb_vorbis_get_samples_float_interleaved_stereo(
705 ch->vorbis_handle,
706 dst,
707 samples_this_run );
708
709 if( read_samples != samples_this_run )
710 {
711 vg_warn( "Invalid samples read (%s)\n", ch->source->path );
712
713 for( int i=0; i<samples_this_run; i++ )
714 {
715 dst[i*2+0] = 0.0f;
716 dst[i*2+1] = 0.0f;
717 }
718 }
719 }
720 else
721 {
722 i16 *src_buffer = ch->source->data,
723 *src = &src_buffer[ch->cursor];
724
725 audio_decode_uncompressed_mono( src, samples_this_run, dst );
726 }
727
728 ch->cursor += samples_this_run;
729 buffer_pos += samples_this_run;
730
731 if( (ch->flags & AUDIO_FLAG_LOOP) && remaining )
732 {
733 if( ch->source->flags & AUDIO_FLAG_VORBIS )
734 stb_vorbis_seek_start( ch->vorbis_handle );
735
736 ch->cursor = 0;
737 continue;
738 }
739 else
740 break;
741 }
742
743 while( remaining )
744 {
745 buf[ buffer_pos*2 + 0 ] = 0.0f;
746 buf[ buffer_pos*2 + 1 ] = 0.0f;
747 buffer_pos ++;
748
749 remaining --;
750 }
751
752 vg_profile_end( &_vg_prof_audio_decode );
753 }
754
755 static void audio_channel_mix( audio_channel *ch, float *buffer )
756 {
757 u32 buffer_length = AUDIO_MIX_FRAME_SIZE;
758 if( ch->_.sampling_rate != 1.0f )
759 {
760 float l = ceilf( (float)(AUDIO_MIX_FRAME_SIZE) * ch->_.sampling_rate );
761 buffer_length = l+1;
762 }
763
764 float pcf[ AUDIO_MIX_FRAME_SIZE * 2 * 2 ];
765
766 audio_channel_get_samples( ch, buffer_length, pcf );
767
768 float framevol_l = 1.0f,
769 framevol_r = 1.0f;
770
771 if( ch->flags & AUDIO_FLAG_SPACIAL_3D )
772 {
773 if( !vg_validf(vg_audio.listener_pos[0]) ||
774 !vg_validf(vg_audio.listener_pos[1]) ||
775 !vg_validf(vg_audio.listener_pos[2]) ||
776 !vg_validf(ch->_.spacial_falloff[0]) ||
777 !vg_validf(ch->_.spacial_falloff[1]) ||
778 !vg_validf(ch->_.spacial_falloff[2]) )
779 {
780 vg_error( "NaN listener/world position (%s)\n", ch->name );
781
782 framevol_l = 0.0f;
783 framevol_r = 0.0f;
784 }
785
786 v3f delta;
787 v3_sub( ch->_.spacial_falloff, vg_audio.listener_pos, delta );
788
789 float dist = v3_length( delta ),
790 vol = vg_maxf( 0.0f, 1.0f - ch->_.spacial_falloff[3]*dist );
791
792 v3_muls( delta, 1.0f/dist, delta );
793 float pan = v3_dot( vg_audio.listener_ears, delta );
794 vol = powf( vol, 5.0f );
795
796 framevol_l *= (vol * 0.5f) * (1.0f - pan);
797 framevol_r *= (vol * 0.5f) * (1.0f + pan);
798 }
799
800 vg_profile_begin( &_vg_prof_audio_mix );
801
802 float volume_movement = ch->volume_movement;
803 float const fvolume_rate = vg_maxf( 1.0f, ch->_.volume_rate );
804 const float inv_volume_rate = 1.0f/fvolume_rate;
805
806 float volume = ch->_.volume;
807 const float volume_start = ch->volume_movement_start;
808 const float volume_target = ch->_.volume_target;
809
810 for( u32 j=0; j<AUDIO_MIX_FRAME_SIZE; j++ )
811 {
812 /*
813 * there is some REALLY weird behaviour with minss,
814 * i cannot begin to guess what the cause is, but the bahaviour when
815 * the second argument is not 1.0 would seemingly tripple or up to
816 * eight times this routine.
817 *
818 * the times it would happen are when moving from empty space into areas
819 * with geometry. in the bvh for skate rift.
820 *
821 * it should be completely unrelated to this, but somehow -- it is
822 * effecting the speed of minss. and severely at that too.
823 **/
824
825 volume_movement += 1.0f;
826 float movement_t = volume_movement * inv_volume_rate;
827 movement_t = vg_minf( volume_movement, 1.0f );
828 volume = vg_lerpf( volume_start, volume_target, movement_t );
829
830 float vol_norm = volume * volume;
831
832 if( ch->_.lfo )
833 vol_norm *= 1.0f + audio_lfo_pull_sample(ch->_.lfo) * ch->_.lfo_amount;
834
835 float vol_l = vol_norm * framevol_l,
836 vol_r = vol_norm * framevol_r,
837 sample_l,
838 sample_r;
839
840 if( ch->_.sampling_rate != 1.0f )
841 {
842 /* absolutely garbage resampling, but it will do
843 */
844
845 float sample_index = ch->_.sampling_rate * (float)j;
846 float t = vg_fractf( sample_index );
847
848 u32 i0 = floorf( sample_index ),
849 i1 = i0+1;
850
851 sample_l = pcf[ i0*2+0 ]*(1.0f-t) + pcf[ i1*2+0 ]*t;
852 sample_r = pcf[ i0*2+1 ]*(1.0f-t) + pcf[ i1*2+1 ]*t;
853 }
854 else
855 {
856 sample_l = pcf[ j*2+0 ];
857 sample_r = pcf[ j*2+1 ];
858 }
859
860 buffer[ j*2+0 ] += sample_l * vol_l;
861 buffer[ j*2+1 ] += sample_r * vol_r;
862 }
863
864 ch->volume_movement += AUDIO_MIX_FRAME_SIZE;
865 ch->volume_movement = VG_MIN( ch->volume_movement, ch->_.volume_rate );
866 ch->_.volume = volume;
867
868 vg_profile_end( &_vg_prof_audio_mix );
869 }
870
871 VG_STATIC void audio_mixer_callback( void *user, u8 *stream, int byte_count )
872 {
873 /*
874 * Copy data and move edit flags to commit flags
875 * ------------------------------------------------------------- */
876 audio_lock();
877 for( int i=0; i<AUDIO_CHANNELS; i++ )
878 {
879 audio_channel *ch = &vg_audio.channels[i];
880
881 if( !ch->allocated )
882 continue;
883
884 if( ch->activity == k_channel_activity_alive )
885 {
886 if( (ch->cursor >= ch->source_length) &&
887 !(ch->flags & AUDIO_FLAG_LOOP) )
888 {
889 ch->activity = k_channel_activity_end;
890 }
891 }
892
893 /* process relinquishments */
894 if( (ch->activity != k_channel_activity_reset) && ch->_.relinquished )
895 {
896 if( (ch->activity == k_channel_activity_end)
897 || (ch->_.volume == 0.0f)
898 || (ch->activity == k_channel_activity_error) )
899 {
900 ch->_.relinquished = 0;
901 ch->allocated = 0;
902 ch->activity = k_channel_activity_reset;
903 continue;
904 }
905 }
906
907 /* process new channels */
908 if( ch->activity == k_channel_activity_reset )
909 {
910 ch->_ = ch->editable_state;
911 ch->cursor = 0;
912 ch->source_length = 0;
913 ch->activity = k_channel_activity_wake;
914 }
915
916 if( ch->editble_state_write_mask & AUDIO_EDIT_OWNERSHIP )
917 ch->_.relinquished = ch->editable_state.relinquished;
918 else
919 ch->editable_state.relinquished = ch->_.relinquished;
920
921
922 if( ch->editble_state_write_mask & AUDIO_EDIT_VOLUME )
923 ch->_.volume = ch->editable_state.volume;
924 else
925 ch->editable_state.volume = ch->_.volume;
926
927
928 if( ch->editble_state_write_mask & AUDIO_EDIT_VOLUME_SLOPE )
929 {
930 ch->volume_movement_start = ch->_.volume;
931 ch->volume_movement = 0;
932
933 ch->_.volume_target = ch->editable_state.volume_target;
934 ch->_.volume_rate = ch->editable_state.volume_rate;
935 }
936 else
937 {
938 ch->editable_state.volume_target = ch->_.volume_target;
939 ch->editable_state.volume_rate = ch->_.volume_rate;
940 }
941
942
943 if( ch->editble_state_write_mask & AUDIO_EDIT_SAMPLING_RATE )
944 ch->_.sampling_rate = ch->editable_state.sampling_rate;
945 else
946 ch->editable_state.sampling_rate = ch->_.sampling_rate;
947
948
949 if( ch->editble_state_write_mask & AUDIO_EDIT_LFO_ATTACHMENT )
950 {
951 ch->_.lfo = ch->editable_state.lfo;
952 ch->_.lfo_amount = ch->editable_state.lfo_amount;
953 }
954 else
955 {
956 ch->editable_state.lfo = ch->_.lfo;
957 ch->editable_state.lfo_amount = ch->_.lfo_amount;
958 }
959
960
961 if( ch->editble_state_write_mask & AUDIO_EDIT_SPACIAL )
962 v4_copy( ch->editable_state.spacial_falloff,ch->_.spacial_falloff );
963 else
964 v4_copy( ch->_.spacial_falloff,ch->editable_state.spacial_falloff );
965
966
967 /* currently readonly, i guess */
968 ch->editable_state.pan_target = ch->_.pan_target;
969 ch->editable_state.pan = ch->_.pan;
970 ch->editble_state_write_mask = 0x00;
971 }
972
973 for( int i=0; i<AUDIO_LFOS; i++ )
974 {
975 audio_lfo *lfo = &vg_audio.oscillators[ i ];
976
977 if( lfo->editble_state_write_mask & AUDIO_EDIT_LFO_WAVE )
978 {
979 lfo->_.wave_type = lfo->editable_state.wave_type;
980
981 if( lfo->_.wave_type == k_lfo_polynomial_bipolar )
982 {
983 lfo->_.polynomial_coefficient =
984 lfo->editable_state.polynomial_coefficient;
985 lfo->sqrt_polynomial_coefficient =
986 sqrtf(lfo->_.polynomial_coefficient);
987 }
988 }
989
990 if( lfo->editble_state_write_mask & AUDIO_EDIT_LFO_PERIOD )
991 {
992 if( lfo->_.period )
993 {
994 float t = lfo->time;
995 t/= (float)lfo->_.period;
996
997 lfo->_.period = lfo->editable_state.period;
998 lfo->time = lfo->_.period * t;
999 }
1000 else
1001 {
1002 lfo->time = 0;
1003 lfo->_.period = lfo->editable_state.period;
1004 }
1005 }
1006
1007 lfo->editble_state_write_mask = 0x00;
1008 }
1009
1010 dsp_update_tunings();
1011 audio_unlock();
1012
1013 /*
1014 * Process spawns
1015 * ------------------------------------------------------------- */
1016 for( int i=0; i<AUDIO_CHANNELS; i++ )
1017 {
1018 audio_channel *ch = &vg_audio.channels[i];
1019
1020 if( ch->activity == k_channel_activity_wake )
1021 {
1022 if( audio_channel_load_source( ch ) )
1023 ch->activity = k_channel_activity_alive;
1024 else
1025 ch->activity = k_channel_activity_error;
1026 }
1027 }
1028
1029 /*
1030 * Mix everything
1031 * -------------------------------------------------------- */
1032 int frame_count = byte_count/(2*sizeof(float));
1033
1034 /* Clear buffer */
1035 float *pOut32F = (float *)stream;
1036 for( int i=0; i<frame_count*2; i ++ )
1037 pOut32F[i] = 0.0f;
1038
1039 for( int i=0; i<AUDIO_LFOS; i++ )
1040 {
1041 audio_lfo *lfo = &vg_audio.oscillators[i];
1042 lfo->time_startframe = lfo->time;
1043 }
1044
1045 for( int i=0; i<AUDIO_CHANNELS; i ++ )
1046 {
1047 audio_channel *ch = &vg_audio.channels[i];
1048
1049 if( ch->activity == k_channel_activity_alive )
1050 {
1051 if( ch->_.lfo )
1052 ch->_.lfo->time = ch->_.lfo->time_startframe;
1053
1054 u32 remaining = frame_count,
1055 subpos = 0;
1056
1057 while( remaining )
1058 {
1059 audio_channel_mix( ch, pOut32F+subpos );
1060 remaining -= AUDIO_MIX_FRAME_SIZE;
1061 subpos += AUDIO_MIX_FRAME_SIZE*2;
1062 }
1063 }
1064 }
1065
1066 vg_profile_begin( &_vg_prof_dsp );
1067
1068 for( int i=0; i<frame_count; i++ )
1069 vg_dsp_process( pOut32F + i*2, pOut32F + i*2 );
1070
1071 vg_profile_end( &_vg_prof_dsp );
1072
1073 audio_lock();
1074
1075 for( int i=0; i<AUDIO_CHANNELS; i ++ )
1076 {
1077 audio_channel *ch = &vg_audio.channels[i];
1078 ch->readable_activity = ch->activity;
1079 }
1080
1081 /* Profiling information
1082 * ----------------------------------------------- */
1083 vg_profile_increment( &_vg_prof_audio_decode );
1084 vg_profile_increment( &_vg_prof_audio_mix );
1085 vg_profile_increment( &_vg_prof_dsp );
1086
1087 vg_prof_audio_mix = _vg_prof_audio_mix;
1088 vg_prof_audio_decode = _vg_prof_audio_decode;
1089 vg_prof_audio_dsp = _vg_prof_dsp;
1090
1091 vg_audio.samples_last = frame_count;
1092
1093 if( vg_audio.debug_ui )
1094 {
1095 vg_dsp_update_texture();
1096 }
1097
1098 audio_unlock();
1099 }
1100
1101 VG_STATIC void audio_clip_load( audio_clip *clip, void *lin_alloc )
1102 {
1103 if( lin_alloc == NULL )
1104 lin_alloc = vg_audio.audio_pool;
1105
1106
1107 /* load in directly */
1108 if( clip->flags & AUDIO_FLAG_VORBIS )
1109 {
1110 audio_lock();
1111 clip->data = vg_file_read( lin_alloc, clip->path, &clip->size );
1112 audio_unlock();
1113
1114 if( !clip->data )
1115 vg_fatal_exit_loop( "Audio failed to load" );
1116
1117 float mb = (float)(clip->size) / (1024.0f*1024.0f);
1118 vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb );
1119 }
1120 else if( clip->flags & AUDIO_FLAG_STEREO )
1121 {
1122 vg_fatal_exit_loop( "Unsupported format (Stereo uncompressed)" );
1123 }
1124 else
1125 {
1126 vg_linear_clear( vg_mem.scratch );
1127 u32 fsize;
1128
1129 stb_vorbis_alloc alloc = {
1130 .alloc_buffer = vg_linear_alloc( vg_mem.scratch, AUDIO_DECODE_SIZE ),
1131 .alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE
1132 };
1133
1134 void *filedata = vg_file_read( vg_mem.scratch, clip->path, &fsize );
1135
1136 int err;
1137 stb_vorbis *decoder = stb_vorbis_open_memory(
1138 filedata, fsize, &err, &alloc );
1139
1140 if( !decoder )
1141 {
1142 vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n",
1143 clip->path, err );
1144 vg_fatal_exit_loop( "Vorbis decode error" );
1145 }
1146
1147 /* only mono is supported in uncompressed */
1148 u32 length_samples = stb_vorbis_stream_length_in_samples( decoder ),
1149 data_size = length_samples * sizeof(i16);
1150
1151 audio_lock();
1152 clip->data = vg_linear_alloc( lin_alloc, vg_align8(data_size) );
1153 clip->size = length_samples;
1154 audio_unlock();
1155
1156 int read_samples = stb_vorbis_get_samples_i16_downmixed(
1157 decoder, clip->data, length_samples );
1158
1159 if( read_samples != length_samples )
1160 vg_fatal_exit_loop( "Decode error" );
1161
1162 float mb = (float)(data_size) / (1024.0f*1024.0f);
1163 vg_info( "Loaded audio clip '%s' (%.1fmb) %u samples\n", clip->path, mb,
1164 length_samples );
1165 }
1166 }
1167
1168 VG_STATIC void audio_clip_loadn( audio_clip *arr, int count, void *lin_alloc )
1169 {
1170 for( int i=0; i<count; i++ )
1171 audio_clip_load( &arr[i], lin_alloc );
1172 }
1173
1174 VG_STATIC void audio_require_clip_loaded( audio_clip *clip )
1175 {
1176 if( clip->data && clip->size )
1177 return;
1178
1179 audio_unlock();
1180 vg_fatal_exit_loop( "Must load audio clip before playing! \n" );
1181 }
1182
1183 /*
1184 * Debugging
1185 */
1186
1187 VG_STATIC void audio_debug_ui( m4x4f mtx_pv )
1188 {
1189 if( !vg_audio.debug_ui )
1190 return;
1191
1192 audio_lock();
1193
1194 glBindTexture( GL_TEXTURE_2D, vg_dsp.view_texture );
1195 glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 256,
1196 GL_RGBA, GL_UNSIGNED_BYTE,
1197 vg_dsp.view_texture_buffer );
1198
1199 /*
1200 * Profiler
1201 * -----------------------------------------------------------------------
1202 */
1203
1204 float budget = ((double)vg_audio.samples_last / 44100.0) * 1000.0;
1205 vg_profile_drawn( (struct vg_profile *[]){ &vg_prof_audio_decode,
1206 &vg_prof_audio_mix,
1207 &vg_prof_audio_dsp}, 3,
1208 budget, (ui_rect){ 4, VG_PROFILE_SAMPLE_COUNT*2 + 8,
1209 512, 0 }, 3 );
1210
1211
1212 char perf[128];
1213
1214 /* Draw UI */
1215 vg_uictx.cursor[0] = 512 + 8;
1216 vg_uictx.cursor[1] = VG_PROFILE_SAMPLE_COUNT*2+8+24+12+12;
1217 vg_uictx.cursor[2] = 150;
1218 vg_uictx.cursor[3] = 12;
1219
1220 ui_rect view_thing = { 4, vg.window_y-512-4, 512, 512 };
1221 ui_push_image( view_thing, vg_dsp.view_texture );
1222
1223 float mb1 = 1024.0f*1024.0f,
1224 usage = vg_linear_get_cur( vg_audio.audio_pool ) / mb1,
1225 total = vg_linear_get_capacity( vg_audio.audio_pool ) / mb1,
1226 percent = (usage/total) * 100.0f;
1227
1228 snprintf( perf, 127, "Mem: %.1f/%.1fmb (%.1f%%)\n", usage, total, percent );
1229
1230 ui_text( vg_uictx.cursor, perf, 1, 0 );
1231 vg_uictx.cursor[1] += 20;
1232
1233 ui_rect overlap_buffer[ AUDIO_CHANNELS ];
1234 u32 overlap_length = 0;
1235
1236 /* Draw audio stack */
1237 for( int i=0; i<AUDIO_CHANNELS; i ++ )
1238 {
1239 audio_channel *ch = &vg_audio.channels[i];
1240
1241 vg_uictx.cursor[2] = 400;
1242 vg_uictx.cursor[3] = 18;
1243
1244 ui_new_node();
1245
1246 if( !ch->allocated )
1247 {
1248 ui_fill_rect( vg_uictx.cursor, 0x50333333 );
1249
1250 ui_end_down();
1251 vg_uictx.cursor[1] += 1;
1252 continue;
1253 }
1254
1255 const char *formats[] =
1256 {
1257 "------",
1258 "Mono ",
1259 "Stereo",
1260 "Vorbis"
1261 };
1262
1263 const char *activties[] =
1264 {
1265 "reset",
1266 "wake ",
1267 "alive",
1268 "end ",
1269 "error"
1270 };
1271
1272 int format_index = 0;
1273
1274 if( ch->source->flags & AUDIO_FLAG_STEREO )
1275 format_index = 2;
1276 else if( ch->source->flags & AUDIO_FLAG_VORBIS )
1277 format_index = 3;
1278 else
1279 format_index = 1;
1280
1281 snprintf( perf, 127, "%02d %c%c%cD %s [%s] %4.2fv'%s'",
1282 i,
1283 (ch->editable_state.relinquished)? 'r': '_',
1284 0? 'r': '_',
1285 0? '3': '2',
1286 formats[format_index],
1287 activties[ch->readable_activity],
1288 ch->editable_state.volume,
1289 ch->name );
1290
1291 if( format_index == 0 )
1292 {
1293 ui_fill_rect( vg_uictx.cursor, 0xa00000ff );
1294 }
1295 else
1296 {
1297 ui_fill_rect( vg_uictx.cursor, 0xa0000000 | ch->colour );
1298 }
1299
1300 vg_uictx.cursor[0] += 2;
1301 vg_uictx.cursor[1] += 2;
1302 ui_text( vg_uictx.cursor, perf, 1, 0 );
1303
1304 ui_end_down();
1305 vg_uictx.cursor[1] += 1;
1306
1307 if( AUDIO_FLAG_SPACIAL_3D )
1308 {
1309 v4f wpos;
1310 v3_copy( ch->editable_state.spacial_falloff, wpos );
1311
1312 wpos[3] = 1.0f;
1313 m4x4_mulv( mtx_pv, wpos, wpos );
1314
1315 if( wpos[3] > 0.0f )
1316 {
1317 v2_muls( wpos, (1.0f/wpos[3]) * 0.5f, wpos );
1318 v2_add( wpos, (v2f){ 0.5f, 0.5f }, wpos );
1319
1320 ui_rect wr;
1321 wr[0] = wpos[0] * vg.window_x;
1322 wr[1] = (1.0f-wpos[1]) * vg.window_y;
1323 wr[2] = 100;
1324 wr[3] = 17;
1325
1326 for( int j=0; j<12; j++ )
1327 {
1328 int collide = 0;
1329 for( int k=0; k<overlap_length; k++ )
1330 {
1331 ui_px *wk = overlap_buffer[k];
1332 if( ((wr[0] <= wk[0]+wk[2]) && (wr[0]+wr[2] >= wk[0])) &&
1333 ((wr[1] <= wk[1]+wk[3]) && (wr[1]+wr[3] >= wk[1])) )
1334 {
1335 collide = 1;
1336 break;
1337 }
1338 }
1339
1340 if( !collide )
1341 break;
1342 else
1343 wr[1] += 18;
1344 }
1345
1346 ui_text( wr, perf, 1, 0 );
1347
1348 ui_rect_copy( wr, overlap_buffer[ overlap_length ++ ] );
1349 }
1350 }
1351 }
1352
1353 audio_unlock();
1354 }
1355
1356 #endif /* VG_AUDIO_H */