From 28d5505edae76ed91708a895815eecf542c23060 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Thu, 3 Dec 2020 17:37:01 +0100 Subject: inital, matleap api based on https://github.com/tomh4/matleap --- theremine.m | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 theremine.m (limited to 'theremine.m') diff --git a/theremine.m b/theremine.m new file mode 100644 index 0000000..f6fb28c --- /dev/null +++ b/theremine.m @@ -0,0 +1,148 @@ +clear; + +%%%%%%%% +% "constants" % +%%%%%%%% + +% how many updates per second, determines the length of audio snippets +const_frames_per_second = 60; + +const_Fs = 96000; % sampling rate in Hz +const_te = 1/const_frames_per_second; % signal duration in seconds +const_samples_per_frame = const_Fs * const_te; +const_sample_range = 0:const_samples_per_frame-1; + +const_fade_speed = 0.2; + +% signal "generator" +signal = @(freq, amp) sin(freq ./ const_Fs .* 2 .* pi .* const_sample_range) * amp; + +% time given for calculation +const_calc_offset = 5; + +% dimensions to use for detecting number of hands in frame +zero_hands = size(NaN(0,0)); +one_hand = size(NaN(1,1)); +two_hands = size(NaN(1,2)); + + +%%%%%%%%%%%%%%%%%%% +% init matleap by calling for first frame % +%%%%%%%%%%%%%%%%%%% +matleap_frame; + +% runtime vars +P = NaN(100000,3); +count = 1; +done = false; + +freq_one = 0; +freq_two = 0; + +signal_one = signal(0,0); +signal_two = signal(0,0); + +full_signal = signal_one + signal_two; +complete_signal = full_signal; + +% time gestures, used for program termination +gesture_count = 0; + +%while count < 100000 && gesture_count < 3 +while gesture_count < (1.5 * (const_frames_per_second - const_calc_offset)) + frame = matleap_frame; + handCount = size(frame.hands); + + if isequal(zero_hands, handCount) + gesture_count = 0; + + % slowly lower volume if no hand is there + signal_one = signal_one * const_fade_speed; + signal_two = signal_two * const_fade_speed; + + % TODO + elseif isequal(one_hand, handCount) + % fade hand two out + signla_two = signal_two * const_fade_speed; + + pos = frame.hands(1).palm.stabilized_position; + signal_one = get_theremin_sound_bit(pos(1), pos(2), signal); + P(count, 1:3) = pos; + count = count + 1; + + if frame.gesture > 0 + gesture_count = gesture_count + 1; + else + gesture_count = 0; + end + elseif isequal(two_hands, handCount) + gesture_count = 0; + + pos = frame.hands(1).palm.stabilized_position; + signal_one = get_theremin_sound_bit(pos(1), pos(2), signal); + P(count, 1:3) = pos; + count = count + 1; + + pos = frame.hands(2).palm.stabilized_position; + signal_two = get_theremin_sound_bit(pos(1), pos(2), signal); + else + "That should not happen:" + handCount + return; + end + + % play current sound + full_signal = signal_one + signal_two; + complete_signal = [complete_signal full_signal]; + + % enforce frame rate, leaving a bit of room for calculation + java.lang.Thread.sleep((1/(const_frames_per_second - const_calc_offset)) * 1000); +end + +theremin_player = audioplayer(complete_signal, const_Fs); +play(theremin_player); + +% extract values +x = P(:,1); % links (-) rechconst_Ts (+) (LED zu uns) +y = P(:,2); % oben unten +z = P(:,3); % vorne (+) hinten (-) (LED zu uns) + +% plot +figure("Position",[0,0, 1200, 2400]); +t = tiledlayout(4,1); + +nexttile; +plot(x); +ylabel('left right'); + +nexttile; +plot(y); +ylabel('height'); + +nexttile; +plot(z); +ylabel('depth'); + +nexttile; +plot3(z,x,y); +xlabel('depth'); +ylabel('left right'); +zlabel('height'); + +function sound = get_theremin_sound_bit(x, y, generator) + % finding ranges for x and y: + %'x' + %min(x) + %max(x) + %'y' + %min(y) + %max(y) + % --> -300 < x < 300 + % --> 0 < y < 600 + + % therefore + volume = y / 600; + frequency = (x + 300) / 600 * 3000; % https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/60.17.html # How it works + + sound = generator(frequency, volume); +end \ No newline at end of file -- cgit v1.2.3-54-g00ecf