From ceefc33fe49a80bc7b517607eb8ca78adbe40cb6 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 27 Apr 2019 15:26:48 -0300 Subject: [PATCH] Improved tutorial for sync audio with music, use two approaches. --- audio/bpm_sync/Control.gd | 34 +++++++++++++++-- audio/bpm_sync/play_button.png | Bin 2466 -> 0 bytes audio/bpm_sync/play_button_hl.png | Bin 2156 -> 0 bytes audio/bpm_sync/play_sound_button.png | Bin 0 -> 2877 bytes ...ng.import => play_sound_button.png.import} | 6 +-- audio/bpm_sync/play_sound_button_hl.png | Bin 0 -> 2263 bytes .../bpm_sync/play_sound_button_hl.png.import | 34 +++++++++++++++++ audio/bpm_sync/play_system_button.png | Bin 0 -> 3195 bytes ...g.import => play_system_button.png.import} | 6 +-- audio/bpm_sync/play_system_button_hl.png | Bin 0 -> 2531 bytes .../bpm_sync/play_system_button_hl.png.import | 34 +++++++++++++++++ audio/bpm_sync/player.tscn | 36 ++++++++++++------ 12 files changed, 129 insertions(+), 21 deletions(-) delete mode 100644 audio/bpm_sync/play_button.png delete mode 100644 audio/bpm_sync/play_button_hl.png create mode 100644 audio/bpm_sync/play_sound_button.png rename audio/bpm_sync/{play_button.png.import => play_sound_button.png.import} (68%) create mode 100644 audio/bpm_sync/play_sound_button_hl.png create mode 100644 audio/bpm_sync/play_sound_button_hl.png.import create mode 100644 audio/bpm_sync/play_system_button.png rename audio/bpm_sync/{play_button_hl.png.import => play_system_button.png.import} (68%) create mode 100644 audio/bpm_sync/play_system_button_hl.png create mode 100644 audio/bpm_sync/play_system_button_hl.png.import diff --git a/audio/bpm_sync/Control.gd b/audio/bpm_sync/Control.gd index e537f75b..7499dd55 100644 --- a/audio/bpm_sync/Control.gd +++ b/audio/bpm_sync/Control.gd @@ -7,18 +7,34 @@ var playing = false const COMPENSATE_FRAMES = 2 const COMPENSATE_HZ = 60.0 +const SYNC_SOURCE_SYSTEM_CLOCK = 0 +const SYNC_SOURCE_SOUND_CLOCK = 1 + +var sync_source = SYNC_SOURCE_SYSTEM_CLOCK + + func strsec(secs): var s = str(secs) if (s.length()==1): s="0"+s return s -# warning-ignore:unused_argument +# used by system clock +var time_begin +var time_delay + func _process(delta): if (!playing or !$Player.playing): return - var time = $Player.get_mix_time() + AudioServer.get_time_since_last_mix() - AudioServer.get_output_latency() + (1/COMPENSATE_HZ)*COMPENSATE_FRAMES + var time + if (sync_source == SYNC_SOURCE_SYSTEM_CLOCK): + # obtain from ticks + time = (OS.get_ticks_usec() - time_begin) / 1000000.0 + # compensate + time -= time_delay + elif (sync_source == SYNC_SOURCE_SOUND_CLOCK): + time = $Player.get_playback_position() + AudioServer.get_time_since_last_mix() - AudioServer.get_output_latency() + (1/COMPENSATE_HZ)*COMPENSATE_FRAMES var beat = int(time * BPM / 60.0) var seconds = int(time) @@ -26,8 +42,18 @@ func _process(delta): $Label.text = str("BEAT: ",beat % BARS +1,"/",BARS," TIME: ",seconds/60,":",strsec(seconds%60)," / ",seconds_total/60,":",strsec(seconds_total%60)) -func _on_Button_pressed(): - print(AudioServer.get_output_latency()) + +func _on_PlaySystem_pressed(): + pass # Replace with function body. + sync_source = SYNC_SOURCE_SYSTEM_CLOCK + time_begin = OS.get_ticks_usec() + time_delay = AudioServer.get_time_to_next_mix() + AudioServer.get_output_latency() playing=true $Player.play() + +func _on_PlaySound_pressed(): + sync_source = SYNC_SOURCE_SOUND_CLOCK + playing=true + $Player.play() + diff --git a/audio/bpm_sync/play_button.png b/audio/bpm_sync/play_button.png deleted file mode 100644 index b400aebb3bbafa518c847642746e7de7898b2ba6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2466 zcmV;T30?MyP)}H8voMMr(;BQlN;bwMNd;d-j%u$S-M1h@dT{ zv4yslmLsL4z|o!8KW4^TmixWCcRTw&pTBl)e%^e)^S<*u&&)eeW<=z(A~Fso7I>A| zsECXLrU845F`asv9YsVwCL%NSOsElNipX?56OMENJ(%De@K@j-W6axn>K!tGh zPJRfi10FEOTvQ2$m&6e5r>@}l2w(;99}&4*C2+$4S9J5Y>wt|SvR6c=sT8$sfW}_t z-3+`aB2S3OSe2wU4Up`|GA+Of5qVHV5-Lq?8DJn?#UsG0B66F`6Eg#dNVzsO8Tg}! zw28tA|ghmtIeCh{%`}(CL*mOGFc^b&j1m(gwetp5gDmcx@Ums_*aDagXJoxdj^QO z8u*Qf91@X~%Icm0BBlcEBC<_Hu2Fg2GeE=w;EnM9piX6W&j8R>c79bv?oz4UGeE>d z;7JkLEh0CnJh}J8b~ava|CBh=|J0&%0W7)+cWQGQiRB zv9v4I0PfNPye=XuTq!%N0WN1Oum(6RB28)lcbNi+h-?>;NooLhX{M{}T(1UjlPInH zrid(41Gvl8z+)n^Uqo(F1GvjfV4sL=6_N330C%~a;A!O_iO2{wfSWV`E5jSb1!@3y znFMSL%g$5P0PZpiI25LpuTlfJOG_9wR(07~4NzIGBq%!{5s_v!fV*4|Y!{K|MC9XY z0C$;7PL!&J_TgMu<;5tfZJi?84+1F zlwqS9pt=|VJVuaK{)`&HT_yv2!l#w5RRg$72KcXt{8U65)Bx`CU0{DD-gH(2R6pl| zyMgJI7+rmYp5Llw4Y1M}bH0*yol5nQ1(q0NP7FoZp;Qkif!mESJ2emB7Cx{X_~=lI zuPs1z@O$8!#+dhqW9Mps;o}8@r;3k3*O0n}gKTRTP@8lRylyr#62Fi#53;QWs4^Y~ zt_A)E*xnW#DkG=?hK8pIMmzr@!DsXOO{Gns_W+gUD6kMXSjt8!d4HfSKxOyvnx;ol+J6w9l+i=39kky zoezO~fc12J7&|t?s{u-5E$|>gtv;5*s{sbbK41~uWbooBz8awaoFvHG@2nN!)d2m& z2kr-c$pABW)h@gmpl_Zec!%%(TD$7i0KM~K*w6o~mW5XXT+UfwG4Ko(%HUO#@M?fd zc^LQ!aM2av)c^t8fhEAZE;RRQfG&;!w^7DQUEG9s)c_v=%YZG!IDM-I7#xoR-v=(J z@NOBPji5~Xw(HHkYX*pQnN|%jcxs|ds|FYx>wpJ);Kt$#hm}=OY{;Dy+AX<(?1^w@&N*t5#`|}CL_s8?R&BmCQfdfS?!zIj} zJNLM?_Wp34o5zkF8+8k`wzggcJRVNI+}POokmdmfAJ%!5J}%$)Baz?SwQJYT@Fs9e z__t~8?d>;qw_YZbSx@jbGQbbo+uN@PXlQ6y4NL-j&+}Sl&z^nGX#>O+D(s1_Ao0^(- zS5vo|h>`H@*sUv%KWfw~@A zf!Bd35}0MJeK!1kw6U>qB~?b%-vnA~y<9FgPDJiXCX?+zefalBQmIrWUJHw2|CiF~ z^b1AvHushjC@}hOJx~v!3VuI}FEW8)GV!1X@xMVO(Z_ z=H})z1VhX9m=h>izoQ_R(NV1@wpv?&vgGmy8vEz-`6%|^pGu`(=^-(-*;;#RK~CTo z#26hZw42x;xJg884^4Y z?JEU2fp2RI5Mv5se}VxhdZnqU=@{YgbG_vR)By1zy5isJ=;&zg=Q^AElM~P`V3_j= zz3_%HW@1t7|J1^T3-kTl$5w)`ht>6!6VMhQ9#=os+D-jk$ry7AcrMBbw6?a6*Hft| gilQirqQrv#0k1=7ny^;iivR!s07*qoM6N<$f>;NVdjJ3c diff --git a/audio/bpm_sync/play_button_hl.png b/audio/bpm_sync/play_button_hl.png deleted file mode 100644 index a8d7feaac7efac1eccebfc1fd8b93d14d78b1ac4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2156 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 literal 0 HcmV?d00001 diff --git a/audio/bpm_sync/play_sound_button_hl.png.import b/audio/bpm_sync/play_sound_button_hl.png.import new file mode 100644 index 00000000..11227315 --- /dev/null +++ b/audio/bpm_sync/play_sound_button_hl.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/play_sound_button_hl.png-8d86f81fe37a5f2959088b0948283133.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://play_sound_button_hl.png" +dest_files=[ "res://.import/play_sound_button_hl.png-8d86f81fe37a5f2959088b0948283133.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/audio/bpm_sync/play_system_button.png b/audio/bpm_sync/play_system_button.png new file mode 100644 index 0000000000000000000000000000000000000000..7689f179b2be8b8a8b8e98f82592cddbf4e25eb5 GIT binary patch literal 3195 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 i#)9Pkj2M+4-&NgDHHX|DVCaf|V*tj