1 /* Copyright (C) 2021-2023 Harry Godden (hgn) - All Rights Reserved */
9 #include "vg/vg_stdint.h"
10 #include "vg/vg_platform.h"
13 #include "vg/vg_console.h"
14 #include "vg/vg_store.h"
15 #include "vg/vg_profiler.h"
16 #include "vg/vg_audio_synth_bird.h"
20 #pragma GCC push_options
21 #pragma GCC optimize ("O3")
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
27 #define STB_VORBIS_MAX_CHANNELS 2
28 #include "submodules/stb/stb_vorbis.c"
35 #pragma GCC pop_options
36 #pragma GCC diagnostic pop
40 #define AUDIO_FRAME_SIZE 512
41 #define AUDIO_MIX_FRAME_SIZE 256
43 #define AUDIO_CHANNELS 32
45 #define AUDIO_FILTERS 16
46 #define AUDIO_FLAG_LOOP 0x1
47 #define AUDIO_FLAG_NO_DOPPLER 0x2
48 #define AUDIO_FLAG_SPACIAL_3D 0x4
49 #define AUDIO_FLAG_AUTO_START 0x8
50 #define AUDIO_FLAG_FORMAT 0x1E00
54 k_audio_format_mono
= 0x000u
,
55 k_audio_format_stereo
= 0x200u
,
56 k_audio_format_vorbis
= 0x400u
,
57 k_audio_format_none0
= 0x600u
,
58 k_audio_format_none1
= 0x800u
,
59 k_audio_format_none2
= 0xA00u
,
60 k_audio_format_none3
= 0xC00u
,
61 k_audio_format_none4
= 0xE00u
,
63 k_audio_format_bird
= 0x1000u
,
64 k_audio_format_gen
= 0x1200u
,
65 k_audio_format_none6
= 0x1400u
,
66 k_audio_format_none7
= 0x1600u
,
67 k_audio_format_none8
= 0x1800u
,
68 k_audio_format_none9
= 0x1A00u
,
69 k_audio_format_none10
= 0x1C00u
,
70 k_audio_format_none11
= 0x1E00u
,
73 #define AUDIO_DECODE_SIZE (1024*256) /* 256 kb decoding buffers */
74 #define AUDIO_MUTE_VOLUME 0.0f
75 #define AUDIO_BASE_VOLUME 1.0f
77 typedef struct audio_clip audio_clip
;
78 typedef struct audio_channel audio_channel
;
79 typedef struct audio_lfo audio_lfo
;
82 union { /* TODO oof.. */
97 struct vg_audio_system
{
98 SDL_AudioDeviceID sdl_output_device
;
99 vg_str device_choice
; /* buffer is null? use default from OS */
108 SDL_SpinLock sl_checker
,
112 u32 time
, time_startframe
;
113 float sqrt_polynomial_coefficient
;
120 k_lfo_polynomial_bipolar
125 float polynomial_coefficient
;
128 u32 editble_state_write_mask
;
130 oscillators
[ AUDIO_LFOS
];
132 struct audio_channel
{
137 char name
[32]; /* only editable while allocated == 0 */
138 audio_clip
*source
; /* ... */
140 u32 colour
; /* ... */
142 /* internal non-readable state
143 * -----------------------------*/
144 u32 cursor
, source_length
;
146 float volume_movement_start
,
153 struct synth_bird
*bird_handle
;
154 stb_vorbis
*vorbis_handle
;
157 stb_vorbis_alloc vorbis_alloc
;
159 enum channel_activity
{
160 k_channel_activity_reset
, /* will advance if allocated==1, to wake */
161 k_channel_activity_wake
, /* will advance to either of next two */
162 k_channel_activity_alive
,
163 k_channel_activity_end
,
164 k_channel_activity_error
170 * editable structure, can be modified inside _lock and _unlock
171 * the edit mask tells which to copy into internal _, or to discard
172 * ----------------------------------------------------------------------
174 struct channel_state
{
177 float volume
, /* current volume */
178 volume_target
, /* target volume */
186 v4f spacial_falloff
; /* xyz, range */
192 u32 editble_state_write_mask
;
194 channels
[ AUDIO_CHANNELS
];
196 int debug_ui
, debug_ui_3d
, debug_dsp
, dsp_enabled
;
198 v3f internal_listener_pos
,
199 internal_listener_ears
,
200 internal_listener_velocity
,
202 external_listener_pos
,
203 external_listener_ears
,
204 external_lister_velocity
;
206 float internal_global_volume
,
207 external_global_volume
;
209 static vg_audio
= { .external_global_volume
= 1.0f
, .dsp_enabled
= 1 };
211 #include "vg/vg_audio_dsp.h"
213 static struct vg_profile
214 _vg_prof_audio_decode
= {.mode
= k_profile_mode_accum
,
215 .name
= "[T2] audio_decode()"},
216 _vg_prof_audio_mix
= {.mode
= k_profile_mode_accum
,
217 .name
= "[T2] audio_mix()"},
218 _vg_prof_dsp
= {.mode
= k_profile_mode_accum
,
219 .name
= "[T2] dsp_process()"},
220 vg_prof_audio_decode
,
225 * These functions are called from the main thread and used to prevent bad
226 * access. TODO: They should be no-ops in release builds.
228 static int audio_lock_checker_load(void)
231 SDL_AtomicLock( &vg_audio
.sl_checker
);
232 value
= vg_audio
.sync_locked
;
233 SDL_AtomicUnlock( &vg_audio
.sl_checker
);
237 static void audio_lock_checker_store( int value
)
239 SDL_AtomicLock( &vg_audio
.sl_checker
);
240 vg_audio
.sync_locked
= value
;
241 SDL_AtomicUnlock( &vg_audio
.sl_checker
);
244 static void audio_require_lock(void)
246 if( audio_lock_checker_load() )
249 vg_error( "Modifying sound effects systems requires locking\n" );
253 static void audio_lock(void)
255 SDL_AtomicLock( &vg_audio
.sl_sync
);
256 audio_lock_checker_store(1);
259 static void audio_unlock(void)
261 audio_lock_checker_store(0);
262 SDL_AtomicUnlock( &vg_audio
.sl_sync
);
264 static void audio_mixer_callback( void *user
, u8
*stream
, int frame_count
);
266 static void vg_audio_device_init(void){
267 SDL_AudioSpec spec_desired
, spec_got
;
268 spec_desired
.callback
= audio_mixer_callback
;
269 spec_desired
.channels
= 2;
270 spec_desired
.format
= AUDIO_F32
;
271 spec_desired
.freq
= 44100;
272 spec_desired
.padding
= 0;
273 spec_desired
.samples
= AUDIO_FRAME_SIZE
;
274 spec_desired
.silence
= 0;
275 spec_desired
.size
= 0;
276 spec_desired
.userdata
= NULL
;
278 vg_audio
.sdl_output_device
=
279 SDL_OpenAudioDevice( vg_audio
.device_choice
.buffer
, 0,
280 &spec_desired
, &spec_got
,0 );
282 vg_info( "Start audio device (%u, F32, %u) @%s\n",
285 vg_audio
.device_choice
.buffer
);
287 if( vg_audio
.sdl_output_device
){
288 SDL_PauseAudioDevice( vg_audio
.sdl_output_device
, 0 );
289 vg_success( "Unpaused device %d.\n", vg_audio
.sdl_output_device
);
293 "SDL_OpenAudioDevice failed. Your default audio device must support:\n"
294 " Frequency: 44100 hz\n"
295 " Buffer size: 512\n"
297 " Format: s16 or f32\n" );
301 static void vg_audio_register(void){
302 vg_console_reg_var( "debug_audio", &vg_audio
.debug_ui
,
303 k_var_dtype_i32
, VG_VAR_CHEAT
);
304 vg_console_reg_var( "debug_dsp", &vg_audio
.debug_dsp
,
305 k_var_dtype_i32
, VG_VAR_CHEAT
);
306 vg_console_reg_var( "volume", &vg_audio
.external_global_volume
,
307 k_var_dtype_f32
, VG_VAR_PERSISTENT
);
308 vg_console_reg_var( "vg_audio_device", &vg_audio
.device_choice
,
309 k_var_dtype_str
, VG_VAR_PERSISTENT
);
310 vg_console_reg_var( "vg_dsp", &vg_audio
.dsp_enabled
,
311 k_var_dtype_i32
, VG_VAR_PERSISTENT
);
314 static void vg_audio_init(void){
315 /* allocate memory */
317 vg_audio
.audio_pool
=
318 vg_create_linear_allocator( vg_mem
.rtmemory
, 1024*1024*32,
322 u32 decode_size
= AUDIO_DECODE_SIZE
* AUDIO_CHANNELS
;
323 vg_audio
.decode_buffer
= vg_linear_alloc( vg_mem
.rtmemory
, decode_size
);
326 vg_audio_device_init();
329 static void vg_audio_free(void)
332 SDL_CloseAudioDevice( vg_audio
.sdl_output_device
);
339 #define AUDIO_EDIT_VOLUME_SLOPE 0x1
340 #define AUDIO_EDIT_VOLUME 0x2
341 #define AUDIO_EDIT_LFO_PERIOD 0x4
342 #define AUDIO_EDIT_LFO_WAVE 0x8
343 #define AUDIO_EDIT_LFO_ATTACHMENT 0x10
344 #define AUDIO_EDIT_SPACIAL 0x20
345 #define AUDIO_EDIT_OWNERSHIP 0x40
346 #define AUDIO_EDIT_SAMPLING_RATE 0x80
348 static void audio_channel_init( audio_channel
*ch
, audio_clip
*clip
,
350 audio_require_lock();
355 ch
->colour
= 0x00333333;
357 if( (ch
->source
->flags
& AUDIO_FLAG_FORMAT
) == k_audio_format_bird
)
358 strcpy( ch
->name
, "[array]" );
359 else if( (ch
->source
->flags
& AUDIO_FLAG_FORMAT
) == k_audio_format_gen
)
360 strcpy( ch
->name
, "[program]" );
362 vg_strncpy( clip
->path
, ch
->name
, 32, k_strncpy_always_add_null
);
366 ch
->editable_state
.relinquished
= 0;
367 ch
->editable_state
.volume
= 1.0f
;
368 ch
->editable_state
.volume_target
= 1.0f
;
369 ch
->editable_state
.pan
= 0.0f
;
370 ch
->editable_state
.pan_target
= 0.0f
;
371 ch
->editable_state
.volume_rate
= 0;
372 ch
->editable_state
.pan_rate
= 0;
373 v4_copy((v4f
){0.0f
,0.0f
,0.0f
,1.0f
},ch
->editable_state
.spacial_falloff
);
374 ch
->editable_state
.lfo
= NULL
;
375 ch
->editable_state
.lfo_amount
= 0.0f
;
376 ch
->editable_state
.sampling_rate
= 1.0f
;
377 ch
->editble_state_write_mask
= 0x00;
380 static void audio_channel_group( audio_channel
*ch
, u16 group
)
382 audio_require_lock();
384 ch
->colour
= (((u32
)group
* 29986577) & 0x00ffffff) | 0xff000000;
387 static void audio_channel_world( audio_channel
*ch
, u8 world_id
)
389 audio_require_lock();
390 ch
->world_id
= world_id
;
393 static audio_channel
*audio_get_first_idle_channel(void)
395 audio_require_lock();
396 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
397 audio_channel
*ch
= &vg_audio
.channels
[i
];
399 if( !ch
->allocated
){
407 static audio_channel
*audio_get_group_idle_channel( u16 group
, u32 max_count
)
409 audio_require_lock();
411 audio_channel
*dest
= NULL
;
413 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
414 audio_channel
*ch
= &vg_audio
.channels
[i
];
417 if( ch
->group
== group
){
427 if( dest
&& (count
< max_count
) ){
434 static audio_channel
*audio_get_group_first_active_channel( u16 group
)
436 audio_require_lock();
437 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
438 audio_channel
*ch
= &vg_audio
.channels
[i
];
439 if( ch
->allocated
&& (ch
->group
== group
) )
445 static int audio_channel_finished( audio_channel
*ch
)
447 audio_require_lock();
448 if( ch
->readable_activity
== k_channel_activity_end
)
454 static audio_channel
*audio_relinquish_channel( audio_channel
*ch
)
456 audio_require_lock();
457 ch
->editable_state
.relinquished
= 1;
458 ch
->editble_state_write_mask
|= AUDIO_EDIT_OWNERSHIP
;
462 static void audio_channel_slope_volume( audio_channel
*ch
, float length
,
465 audio_require_lock();
466 ch
->editable_state
.volume_target
= new_volume
;
467 ch
->editable_state
.volume_rate
= length
* 44100.0f
;
468 ch
->editble_state_write_mask
|= AUDIO_EDIT_VOLUME_SLOPE
;
471 static void audio_channel_set_sampling_rate( audio_channel
*ch
, float rate
)
473 audio_require_lock();
474 ch
->editable_state
.sampling_rate
= rate
;
475 ch
->editble_state_write_mask
|= AUDIO_EDIT_SAMPLING_RATE
;
478 static void audio_channel_edit_volume( audio_channel
*ch
,
479 float new_volume
, int instant
)
481 audio_require_lock();
483 ch
->editable_state
.volume
= new_volume
;
484 ch
->editble_state_write_mask
|= AUDIO_EDIT_VOLUME
;
487 audio_channel_slope_volume( ch
, 0.05f
, new_volume
);
491 static audio_channel
*audio_channel_fadeout( audio_channel
*ch
, float length
)
493 audio_require_lock();
494 audio_channel_slope_volume( ch
, length
, 0.0f
);
495 return audio_relinquish_channel( ch
);
498 static void audio_channel_fadein( audio_channel
*ch
, float length
)
500 audio_require_lock();
501 audio_channel_edit_volume( ch
, 0.0f
, 1 );
502 audio_channel_slope_volume( ch
, length
, 1.0f
);
505 static audio_channel
*audio_channel_crossfade( audio_channel
*ch
,
506 audio_clip
*new_clip
,
507 float length
, u32 flags
)
509 audio_require_lock();
513 ch
= audio_channel_fadeout( ch
, length
);
515 audio_channel
*replacement
= audio_get_first_idle_channel();
518 audio_channel_init( replacement
, new_clip
, flags
);
519 audio_channel_fadein( replacement
, length
);
525 static void audio_channel_sidechain_lfo( audio_channel
*ch
, int lfo_id
,
528 audio_require_lock();
529 ch
->editable_state
.lfo
= &vg_audio
.oscillators
[ lfo_id
];
530 ch
->editable_state
.lfo_amount
= amount
;
531 ch
->editble_state_write_mask
|= AUDIO_EDIT_LFO_ATTACHMENT
;
534 static void audio_channel_set_spacial( audio_channel
*ch
, v3f co
, float range
)
536 audio_require_lock();
537 if( ch
->flags
& AUDIO_FLAG_SPACIAL_3D
){
538 v3_copy( co
, ch
->editable_state
.spacial_falloff
);
541 ch
->editable_state
.spacial_falloff
[3] = 1.0f
;
543 ch
->editable_state
.spacial_falloff
[3] = 1.0f
/range
;
545 ch
->editble_state_write_mask
|= AUDIO_EDIT_SPACIAL
;
548 vg_warn( "Tried to set spacialization paramaters for 2D channel (%s)\n",
553 static int audio_oneshot_3d( audio_clip
*clip
, v3f position
,
554 float range
, float volume
)
556 audio_require_lock();
557 audio_channel
*ch
= audio_get_first_idle_channel();
560 audio_channel_init( ch
, clip
, AUDIO_FLAG_SPACIAL_3D
);
561 audio_channel_set_spacial( ch
, position
, range
);
562 audio_channel_edit_volume( ch
, volume
, 1 );
563 ch
= audio_relinquish_channel( ch
);
571 static int audio_oneshot( audio_clip
*clip
, float volume
, float pan
)
573 audio_require_lock();
574 audio_channel
*ch
= audio_get_first_idle_channel();
577 audio_channel_init( ch
, clip
, 0x00 );
578 audio_channel_edit_volume( ch
, volume
, 1 );
579 ch
= audio_relinquish_channel( ch
);
587 static void audio_set_lfo_wave( int id
, enum lfo_wave_type type
,
590 audio_require_lock();
591 audio_lfo
*lfo
= &vg_audio
.oscillators
[ id
];
592 lfo
->editable_state
.polynomial_coefficient
= coefficient
;
593 lfo
->editable_state
.wave_type
= type
;
595 lfo
->editble_state_write_mask
|= AUDIO_EDIT_LFO_WAVE
;
598 static void audio_set_lfo_frequency( int id
, float freq
)
600 audio_require_lock();
601 audio_lfo
*lfo
= &vg_audio
.oscillators
[ id
];
602 lfo
->editable_state
.period
= 44100.0f
/ freq
;
603 lfo
->editble_state_write_mask
|= AUDIO_EDIT_LFO_PERIOD
;
609 * -----------------------------------------------------------------------------
611 static int audio_channel_load_source( audio_channel
*ch
)
613 u32 format
= ch
->source
->flags
& AUDIO_FLAG_FORMAT
;
615 if( format
== k_audio_format_vorbis
){
616 /* Setup vorbis decoder */
617 u32 index
= ch
- vg_audio
.channels
;
619 u8
*buf
= (u8
*)vg_audio
.decode_buffer
,
620 *loc
= &buf
[AUDIO_DECODE_SIZE
*index
];
622 stb_vorbis_alloc alloc
= {
623 .alloc_buffer
= (char *)loc
,
624 .alloc_buffer_length_in_bytes
= AUDIO_DECODE_SIZE
628 stb_vorbis
*decoder
= stb_vorbis_open_memory(
630 ch
->source
->size
, &err
, &alloc
);
633 vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n",
634 ch
->source
->path
, err
);
638 ch
->source_length
= stb_vorbis_stream_length_in_samples( decoder
);
639 ch
->vorbis_handle
= decoder
;
642 else if( format
== k_audio_format_bird
){
643 u32 index
= ch
- vg_audio
.channels
;
645 u8
*buf
= (u8
*)vg_audio
.decode_buffer
;
646 struct synth_bird
*loc
= (void *)&buf
[AUDIO_DECODE_SIZE
*index
];
648 memcpy( loc
, ch
->source
->data
, ch
->source
->size
);
649 synth_bird_reset( loc
);
651 ch
->bird_handle
= loc
;
652 ch
->source_length
= synth_bird_get_length_in_samples( loc
);
654 else if( format
== k_audio_format_stereo
){
655 ch
->source_length
= ch
->source
->size
/ 2;
657 else if( format
== k_audio_format_gen
){
658 ch
->source_length
= 0xffffffff;
661 ch
->source_length
= ch
->source
->size
;
667 static void audio_decode_uncompressed_mono( i16
*src
, u32 count
, float *dst
)
669 for( u32 i
=0; i
<count
; i
++ ){
670 dst
[ i
*2 + 0 ] = ((float)src
[i
]) * (1.0f
/32767.0f
);
671 dst
[ i
*2 + 1 ] = ((float)src
[i
]) * (1.0f
/32767.0f
);
676 * adapted from stb_vorbis.h, since the original does not handle mono->stereo
679 stb_vorbis_get_samples_float_interleaved_stereo( stb_vorbis
*f
, float *buffer
,
683 c
= VG_MIN( 1, f
->channels
- 1 );
686 int k
= f
->channel_buffer_end
- f
->channel_buffer_start
;
691 for( int j
=0; j
< k
; ++j
) {
692 *buffer
++ = f
->channel_buffers
[ 0 ][f
->channel_buffer_start
+j
];
693 *buffer
++ = f
->channel_buffers
[ c
][f
->channel_buffer_start
+j
];
697 f
->channel_buffer_start
+= k
;
702 if( !stb_vorbis_get_frame_float( f
, NULL
, NULL
))
710 * ........ more wrecked code sorry!
713 stb_vorbis_get_samples_i16_downmixed( stb_vorbis
*f
, i16
*buffer
, int len
)
716 c
= VG_MIN( 1, f
->channels
- 1 );
719 int k
= f
->channel_buffer_end
- f
->channel_buffer_start
;
724 for( int j
=0; j
< k
; ++j
) {
725 float sl
= f
->channel_buffers
[ 0 ][f
->channel_buffer_start
+j
],
726 sr
= f
->channel_buffers
[ c
][f
->channel_buffer_start
+j
];
728 *buffer
++ = vg_clampf( 0.5f
*(sl
+sr
), -1.0f
, 1.0f
) * 32767.0f
;
729 //*buffer++ = vg_clampf( sr, -1.0f, 1.0f ) * 32767.0f;
733 f
->channel_buffer_start
+= k
;
738 if( !stb_vorbis_get_frame_float( f
, NULL
, NULL
))
745 static inline float audio_lfo_pull_sample( audio_lfo
*lfo
)
749 if( lfo
->time
>= lfo
->_
.period
)
753 t
/= (float)lfo
->_
.period
;
755 if( lfo
->_
.wave_type
== k_lfo_polynomial_bipolar
){
771 return (( 2.0f
* lfo
->sqrt_polynomial_coefficient
* t
) /
772 /* --------------------------------------- */
773 ( 1.0f
+ lfo
->_
.polynomial_coefficient
* t
*t
)
782 static void audio_channel_get_samples( audio_channel
*ch
,
783 u32 count
, float *buf
)
785 vg_profile_begin( &_vg_prof_audio_decode
);
787 u32 remaining
= count
;
790 u32 format
= ch
->source
->flags
& AUDIO_FLAG_FORMAT
;
793 u32 samples_this_run
= VG_MIN(remaining
, ch
->source_length
- ch
->cursor
);
794 remaining
-= samples_this_run
;
796 float *dst
= &buf
[ buffer_pos
* 2 ];
798 if( format
== k_audio_format_stereo
){
799 for( int i
=0;i
<samples_this_run
; i
++ ){
804 else if( format
== k_audio_format_vorbis
){
805 int read_samples
= stb_vorbis_get_samples_float_interleaved_stereo(
810 if( read_samples
!= samples_this_run
){
811 vg_warn( "Invalid samples read (%s)\n", ch
->source
->path
);
813 for( int i
=0; i
<samples_this_run
; i
++ ){
819 else if( format
== k_audio_format_bird
){
820 synth_bird_generate_samples( ch
->bird_handle
, dst
, samples_this_run
);
822 else if( format
== k_audio_format_gen
){
823 void (*fn
)( void *data
, f32
*buf
, u32 count
) = ch
->source
->func
;
824 fn( ch
->source
->data
, dst
, samples_this_run
);
827 i16
*src_buffer
= ch
->source
->data
,
828 *src
= &src_buffer
[ch
->cursor
];
830 audio_decode_uncompressed_mono( src
, samples_this_run
, dst
);
833 ch
->cursor
+= samples_this_run
;
834 buffer_pos
+= samples_this_run
;
836 if( (ch
->flags
& AUDIO_FLAG_LOOP
) && remaining
){
837 if( format
== k_audio_format_vorbis
)
838 stb_vorbis_seek_start( ch
->vorbis_handle
);
839 else if( format
== k_audio_format_bird
)
840 synth_bird_reset( ch
->bird_handle
);
850 buf
[ buffer_pos
*2 + 0 ] = 0.0f
;
851 buf
[ buffer_pos
*2 + 1 ] = 0.0f
;
857 vg_profile_end( &_vg_prof_audio_decode
);
860 static void audio_channel_mix( audio_channel
*ch
, float *buffer
)
862 float framevol_l
= vg_audio
.internal_global_volume
,
863 framevol_r
= vg_audio
.internal_global_volume
;
865 float frame_samplerate
= ch
->_
.sampling_rate
;
867 if( ch
->flags
& AUDIO_FLAG_SPACIAL_3D
){
869 v3_sub( ch
->_
.spacial_falloff
, vg_audio
.internal_listener_pos
, delta
);
871 float dist
= v3_length( delta
),
872 vol
= vg_maxf( 0.0f
, 1.0f
- ch
->_
.spacial_falloff
[3]*dist
);
878 v3_muls( delta
, 1.0f
/dist
, delta
);
879 float pan
= v3_dot( vg_audio
.internal_listener_ears
, delta
);
880 vol
= powf( vol
, 5.0f
);
882 framevol_l
*= (vol
* 0.5f
) * (1.0f
- pan
);
883 framevol_r
*= (vol
* 0.5f
) * (1.0f
+ pan
);
885 if( !(ch
->source
->flags
& AUDIO_FLAG_NO_DOPPLER
) ){
886 const float vs
= 323.0f
;
888 float dv
= v3_dot(delta
,vg_audio
.internal_listener_velocity
);
889 float doppler
= (vs
+dv
)/vs
;
890 doppler
= vg_clampf( doppler
, 0.6f
, 1.4f
);
892 if( fabsf(doppler
-1.0f
) > 0.01f
)
893 frame_samplerate
*= doppler
;
897 if( !vg_validf( framevol_l
) ||
898 !vg_validf( framevol_r
) ||
899 !vg_validf( frame_samplerate
) ){
900 vg_fatal_error( "Invalid sampling conditions.\n"
901 "This crash is to protect your ears.\n"
902 " channel: %p (%s)\n"
905 " listener: %.2f %.2f %.2f [%.2f %.2f %.2f]\n",
906 ch
, ch
->name
, frame_samplerate
,
907 framevol_l
, framevol_r
,
908 vg_audio
.internal_listener_pos
[0],
909 vg_audio
.internal_listener_pos
[1],
910 vg_audio
.internal_listener_pos
[2],
911 vg_audio
.internal_listener_ears
[0],
912 vg_audio
.internal_listener_ears
[1],
913 vg_audio
.internal_listener_ears
[2]
918 u32 buffer_length
= AUDIO_MIX_FRAME_SIZE
;
919 if( frame_samplerate
!= 1.0f
){
920 float l
= ceilf( (float)(AUDIO_MIX_FRAME_SIZE
) * frame_samplerate
);
924 float pcf
[ AUDIO_MIX_FRAME_SIZE
* 2 * 2 ];
926 audio_channel_get_samples( ch
, buffer_length
, pcf
);
928 vg_profile_begin( &_vg_prof_audio_mix
);
930 float volume_movement
= ch
->volume_movement
;
931 float const fvolume_rate
= vg_maxf( 1.0f
, ch
->_
.volume_rate
);
932 const float inv_volume_rate
= 1.0f
/fvolume_rate
;
934 float volume
= ch
->_
.volume
;
935 const float volume_start
= ch
->volume_movement_start
;
936 const float volume_target
= ch
->_
.volume_target
;
938 for( u32 j
=0; j
<AUDIO_MIX_FRAME_SIZE
; j
++ ){
939 volume_movement
+= 1.0f
;
940 float movement_t
= volume_movement
* inv_volume_rate
;
941 movement_t
= vg_minf( movement_t
, 1.0f
);
942 volume
= vg_lerpf( volume_start
, volume_target
, movement_t
);
944 float vol_norm
= volume
* volume
;
947 vol_norm
*= 1.0f
+ audio_lfo_pull_sample(ch
->_
.lfo
) * ch
->_
.lfo_amount
;
949 float vol_l
= vol_norm
* framevol_l
,
950 vol_r
= vol_norm
* framevol_r
,
954 if( frame_samplerate
!= 1.0f
){
955 /* absolutely garbage resampling, but it will do
958 float sample_index
= frame_samplerate
* (float)j
;
959 float t
= vg_fractf( sample_index
);
961 u32 i0
= floorf( sample_index
),
964 sample_l
= pcf
[ i0
*2+0 ]*(1.0f
-t
) + pcf
[ i1
*2+0 ]*t
;
965 sample_r
= pcf
[ i0
*2+1 ]*(1.0f
-t
) + pcf
[ i1
*2+1 ]*t
;
968 sample_l
= pcf
[ j
*2+0 ];
969 sample_r
= pcf
[ j
*2+1 ];
972 buffer
[ j
*2+0 ] += sample_l
* vol_l
;
973 buffer
[ j
*2+1 ] += sample_r
* vol_r
;
976 ch
->volume_movement
+= AUDIO_MIX_FRAME_SIZE
;
977 ch
->volume_movement
= VG_MIN( ch
->volume_movement
, ch
->_
.volume_rate
);
978 ch
->_
.volume
= volume
;
980 vg_profile_end( &_vg_prof_audio_mix
);
983 static void audio_mixer_callback( void *user
, u8
*stream
, int byte_count
){
985 * Copy data and move edit flags to commit flags
986 * ------------------------------------------------------------- */
988 int use_dsp
= vg_audio
.dsp_enabled
;
990 v3_copy( vg_audio
.external_listener_pos
, vg_audio
.internal_listener_pos
);
991 v3_copy( vg_audio
.external_listener_ears
, vg_audio
.internal_listener_ears
);
992 v3_copy( vg_audio
.external_lister_velocity
,
993 vg_audio
.internal_listener_velocity
);
994 vg_audio
.internal_global_volume
= vg_audio
.external_global_volume
;
996 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
997 audio_channel
*ch
= &vg_audio
.channels
[i
];
1002 if( ch
->activity
== k_channel_activity_alive
){
1003 if( (ch
->cursor
>= ch
->source_length
) &&
1004 !(ch
->flags
& AUDIO_FLAG_LOOP
) )
1006 ch
->activity
= k_channel_activity_end
;
1010 /* process relinquishments */
1011 if( (ch
->activity
!= k_channel_activity_reset
) && ch
->_
.relinquished
){
1012 if( (ch
->activity
== k_channel_activity_end
)
1013 || (ch
->_
.volume
== 0.0f
)
1014 || (ch
->activity
== k_channel_activity_error
) )
1016 ch
->_
.relinquished
= 0;
1018 ch
->activity
= k_channel_activity_reset
;
1023 /* process new channels */
1024 if( ch
->activity
== k_channel_activity_reset
){
1025 ch
->_
= ch
->editable_state
;
1027 ch
->source_length
= 0;
1028 ch
->activity
= k_channel_activity_wake
;
1031 if( ch
->editble_state_write_mask
& AUDIO_EDIT_OWNERSHIP
)
1032 ch
->_
.relinquished
= ch
->editable_state
.relinquished
;
1034 ch
->editable_state
.relinquished
= ch
->_
.relinquished
;
1037 if( ch
->editble_state_write_mask
& AUDIO_EDIT_VOLUME
){
1038 ch
->_
.volume
= ch
->editable_state
.volume
;
1039 ch
->_
.volume_target
= ch
->editable_state
.volume
;
1042 ch
->editable_state
.volume
= ch
->_
.volume
;
1046 if( ch
->editble_state_write_mask
& AUDIO_EDIT_VOLUME_SLOPE
){
1047 ch
->volume_movement_start
= ch
->_
.volume
;
1048 ch
->volume_movement
= 0;
1050 ch
->_
.volume_target
= ch
->editable_state
.volume_target
;
1051 ch
->_
.volume_rate
= ch
->editable_state
.volume_rate
;
1054 ch
->editable_state
.volume_target
= ch
->_
.volume_target
;
1055 ch
->editable_state
.volume_rate
= ch
->_
.volume_rate
;
1059 if( ch
->editble_state_write_mask
& AUDIO_EDIT_SAMPLING_RATE
)
1060 ch
->_
.sampling_rate
= ch
->editable_state
.sampling_rate
;
1062 ch
->editable_state
.sampling_rate
= ch
->_
.sampling_rate
;
1065 if( ch
->editble_state_write_mask
& AUDIO_EDIT_LFO_ATTACHMENT
){
1066 ch
->_
.lfo
= ch
->editable_state
.lfo
;
1067 ch
->_
.lfo_amount
= ch
->editable_state
.lfo_amount
;
1070 ch
->editable_state
.lfo
= ch
->_
.lfo
;
1071 ch
->editable_state
.lfo_amount
= ch
->_
.lfo_amount
;
1075 if( ch
->editble_state_write_mask
& AUDIO_EDIT_SPACIAL
)
1076 v4_copy( ch
->editable_state
.spacial_falloff
,ch
->_
.spacial_falloff
);
1078 v4_copy( ch
->_
.spacial_falloff
,ch
->editable_state
.spacial_falloff
);
1081 /* currently readonly, i guess */
1082 ch
->editable_state
.pan_target
= ch
->_
.pan_target
;
1083 ch
->editable_state
.pan
= ch
->_
.pan
;
1084 ch
->editble_state_write_mask
= 0x00;
1087 for( int i
=0; i
<AUDIO_LFOS
; i
++ ){
1088 audio_lfo
*lfo
= &vg_audio
.oscillators
[ i
];
1090 if( lfo
->editble_state_write_mask
& AUDIO_EDIT_LFO_WAVE
){
1091 lfo
->_
.wave_type
= lfo
->editable_state
.wave_type
;
1093 if( lfo
->_
.wave_type
== k_lfo_polynomial_bipolar
){
1094 lfo
->_
.polynomial_coefficient
=
1095 lfo
->editable_state
.polynomial_coefficient
;
1096 lfo
->sqrt_polynomial_coefficient
=
1097 sqrtf(lfo
->_
.polynomial_coefficient
);
1101 if( lfo
->editble_state_write_mask
& AUDIO_EDIT_LFO_PERIOD
){
1102 if( lfo
->_
.period
){
1103 float t
= lfo
->time
;
1104 t
/= (float)lfo
->_
.period
;
1106 lfo
->_
.period
= lfo
->editable_state
.period
;
1107 lfo
->time
= lfo
->_
.period
* t
;
1111 lfo
->_
.period
= lfo
->editable_state
.period
;
1115 lfo
->editble_state_write_mask
= 0x00;
1118 dsp_update_tunings();
1123 * ------------------------------------------------------------- */
1124 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
1125 audio_channel
*ch
= &vg_audio
.channels
[i
];
1127 if( ch
->activity
== k_channel_activity_wake
){
1128 if( audio_channel_load_source( ch
) )
1129 ch
->activity
= k_channel_activity_alive
;
1131 ch
->activity
= k_channel_activity_error
;
1137 * -------------------------------------------------------- */
1138 int frame_count
= byte_count
/(2*sizeof(float));
1141 float *pOut32F
= (float *)stream
;
1142 for( int i
=0; i
<frame_count
*2; i
++ )
1145 for( int i
=0; i
<AUDIO_LFOS
; i
++ ){
1146 audio_lfo
*lfo
= &vg_audio
.oscillators
[i
];
1147 lfo
->time_startframe
= lfo
->time
;
1150 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
1151 audio_channel
*ch
= &vg_audio
.channels
[i
];
1153 if( ch
->activity
== k_channel_activity_alive
){
1155 ch
->_
.lfo
->time
= ch
->_
.lfo
->time_startframe
;
1157 u32 remaining
= frame_count
,
1161 audio_channel_mix( ch
, pOut32F
+subpos
);
1162 remaining
-= AUDIO_MIX_FRAME_SIZE
;
1163 subpos
+= AUDIO_MIX_FRAME_SIZE
*2;
1169 vg_profile_begin( &_vg_prof_dsp
);
1170 for( int i
=0; i
<frame_count
; i
++ )
1171 vg_dsp_process( pOut32F
+ i
*2, pOut32F
+ i
*2 );
1172 vg_profile_end( &_vg_prof_dsp
);
1177 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
1178 audio_channel
*ch
= &vg_audio
.channels
[i
];
1179 ch
->readable_activity
= ch
->activity
;
1182 /* Profiling information
1183 * ----------------------------------------------- */
1184 vg_profile_increment( &_vg_prof_audio_decode
);
1185 vg_profile_increment( &_vg_prof_audio_mix
);
1186 vg_profile_increment( &_vg_prof_dsp
);
1188 vg_prof_audio_mix
= _vg_prof_audio_mix
;
1189 vg_prof_audio_decode
= _vg_prof_audio_decode
;
1190 vg_prof_audio_dsp
= _vg_prof_dsp
;
1192 vg_audio
.samples_last
= frame_count
;
1194 if( vg_audio
.debug_dsp
){
1195 vg_dsp_update_texture();
1201 static void audio_clip_load( audio_clip
*clip
, void *lin_alloc
)
1203 if( lin_alloc
== NULL
)
1204 lin_alloc
= vg_audio
.audio_pool
;
1206 #ifdef VG_AUDIO_FORCE_COMPRESSED
1208 if( (clip
->flags
& AUDIO_FLAG_FORMAT
) != k_audio_format_bird
){
1209 clip
->flags
&= ~AUDIO_FLAG_FORMAT
;
1210 clip
->flags
|= k_audio_format_vorbis
;
1215 /* load in directly */
1216 u32 format
= clip
->flags
& AUDIO_FLAG_FORMAT
;
1218 /* TODO: This contains audio_lock() and unlock, but i don't know why
1219 * can probably remove them. Low priority to check this */
1221 /* TODO: packed files for vorbis etc, should take from data if its not not
1222 * NULL when we get the clip
1225 if( format
== k_audio_format_vorbis
){
1227 vg_fatal_error( "No path specified, embeded vorbis unsupported" );
1231 clip
->data
= vg_file_read( lin_alloc
, clip
->path
, &clip
->size
);
1235 vg_fatal_error( "Audio failed to load" );
1237 float mb
= (float)(clip
->size
) / (1024.0f
*1024.0f
);
1238 vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip
->path
, mb
);
1240 else if( format
== k_audio_format_stereo
){
1241 vg_fatal_error( "Unsupported format (Stereo uncompressed)" );
1243 else if( format
== k_audio_format_bird
){
1245 vg_fatal_error( "No data, external birdsynth unsupported" );
1248 u32 total_size
= clip
->size
+ sizeof(struct synth_bird
);
1249 total_size
-= sizeof(struct synth_bird_settings
);
1250 total_size
= vg_align8( total_size
);
1252 if( total_size
> AUDIO_DECODE_SIZE
)
1253 vg_fatal_error( "Bird coding too long\n" );
1255 struct synth_bird
*bird
= vg_linear_alloc( lin_alloc
, total_size
);
1256 memcpy( &bird
->settings
, clip
->data
, clip
->size
);
1259 clip
->size
= total_size
;
1261 vg_info( "Loaded bird synthesis pattern (%u bytes)\n", total_size
);
1265 vg_fatal_error( "No path specified, embeded mono unsupported" );
1268 vg_linear_clear( vg_mem
.scratch
);
1271 stb_vorbis_alloc alloc
= {
1272 .alloc_buffer
= vg_linear_alloc( vg_mem
.scratch
, AUDIO_DECODE_SIZE
),
1273 .alloc_buffer_length_in_bytes
= AUDIO_DECODE_SIZE
1276 void *filedata
= vg_file_read( vg_mem
.scratch
, clip
->path
, &fsize
);
1279 stb_vorbis
*decoder
= stb_vorbis_open_memory(
1280 filedata
, fsize
, &err
, &alloc
);
1283 vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n",
1285 vg_fatal_error( "Vorbis decode error" );
1288 /* only mono is supported in uncompressed */
1289 u32 length_samples
= stb_vorbis_stream_length_in_samples( decoder
),
1290 data_size
= length_samples
* sizeof(i16
);
1293 clip
->data
= vg_linear_alloc( lin_alloc
, vg_align8(data_size
) );
1294 clip
->size
= length_samples
;
1297 int read_samples
= stb_vorbis_get_samples_i16_downmixed(
1298 decoder
, clip
->data
, length_samples
);
1300 if( read_samples
!= length_samples
)
1301 vg_fatal_error( "Decode error" );
1304 float mb
= (float)(data_size
) / (1024.0f
*1024.0f
);
1305 vg_info( "Loaded audio clip '%s' (%.1fmb) %u samples\n", clip
->path
, mb
,
1311 static void audio_clip_loadn( audio_clip
*arr
, int count
, void *lin_alloc
)
1313 for( int i
=0; i
<count
; i
++ )
1314 audio_clip_load( &arr
[i
], lin_alloc
);
1317 static void audio_require_clip_loaded( audio_clip
*clip
)
1319 if( clip
->data
&& clip
->size
)
1323 vg_fatal_error( "Must load audio clip before playing! \n" );
1330 static void audio_debug_ui(
1339 if( !vg_audio
.debug_ui
)
1344 glBindTexture( GL_TEXTURE_2D
, vg_dsp
.view_texture
);
1345 glTexSubImage2D( GL_TEXTURE_2D
, 0, 0, 0, 256, 256,
1346 GL_RGBA
, GL_UNSIGNED_BYTE
,
1347 vg_dsp
.view_texture_buffer
);
1351 * -----------------------------------------------------------------------
1354 float budget
= ((double)vg_audio
.samples_last
/ 44100.0) * 1000.0;
1355 vg_profile_drawn( (struct vg_profile
*[]){ &vg_prof_audio_decode
,
1357 &vg_prof_audio_dsp
}, 3,
1358 budget
, (ui_rect
){ 4, VG_PROFILE_SAMPLE_COUNT
*2 + 8,
1372 if( vg_audio
.debug_dsp
){
1373 ui_rect view_thing
= { 4, vg
.window_y
-512-4, 512, 512 };
1374 ui_image( view_thing
, vg_dsp
.view_texture
);
1377 ui_rect overlap_buffer
[ AUDIO_CHANNELS
];
1378 u32 overlap_length
= 0;
1380 /* Draw audio stack */
1381 for( int i
=0; i
<AUDIO_CHANNELS
; i
++ ){
1382 audio_channel
*ch
= &vg_audio
.channels
[i
];
1385 ui_split( window
, k_ui_axis_h
, 18, 1, row
, window
);
1387 if( !ch
->allocated
){
1388 ui_fill( row
, 0x50333333 );
1392 const char *formats
[] =
1412 const char *activties
[] =
1421 u32 format_index
= (ch
->source
->flags
& AUDIO_FLAG_FORMAT
)>>9;
1423 snprintf( perf
, 127, "%02d[%#04x.%#06x]%c%c%cD %s [%s] %4.2fv'%s'",
1425 ch
->world_id
, ch
->group
,
1426 (ch
->editable_state
.relinquished
)? 'r': '_',
1429 formats
[format_index
],
1430 activties
[ch
->readable_activity
],
1431 ch
->editable_state
.volume
,
1434 ui_fill( row
, 0xa0000000 | ch
->colour
);
1435 ui_text( row
, perf
, 1, k_ui_align_middle_left
, 0 );
1438 if( AUDIO_FLAG_SPACIAL_3D
){
1440 v3_copy( ch
->editable_state
.spacial_falloff
, wpos
);
1443 m4x4_mulv( mtx_pv
, wpos
, wpos
);
1445 if( wpos
[3] > 0.0f
){
1446 v2_muls( wpos
, (1.0f
/wpos
[3]) * 0.5f
, wpos
);
1447 v2_add( wpos
, (v2f
){ 0.5f
, 0.5f
}, wpos
);
1450 wr
[0] = vg_clampf(wpos
[0] * vg
.window_x
, -32000.0f
,32000.0f
);
1451 wr
[1] = vg_clampf((1.0f
-wpos
[1]) * vg
.window_y
,-32000.0f
,32000.0f
);
1455 for( int j
=0; j
<12; j
++ ){
1457 for( int k
=0; k
<overlap_length
; k
++ ){
1458 ui_px
*wk
= overlap_buffer
[k
];
1459 if( ((wr
[0] <= wk
[0]+wk
[2]) && (wr
[0]+wr
[2] >= wk
[0])) &&
1460 ((wr
[1] <= wk
[1]+wk
[3]) && (wr
[1]+wr
[3] >= wk
[1])) )
1473 ui_text( wr
, perf
, 1, k_ui_align_middle_left
, 0 );
1474 rect_copy( wr
, overlap_buffer
[ overlap_length
++ ] );
1483 #endif /* VG_AUDIO_H */