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