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