summaryrefslogtreecommitdiffstats
path: root/theremine.m
diff options
context:
space:
mode:
Diffstat (limited to 'theremine.m')
-rw-r--r--theremine.m148
1 files changed, 148 insertions, 0 deletions
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