summaryrefslogblamecommitdiffstats
path: root/theremine.m
blob: f6fb28c5741eaab968e016d66a1ad61d43e06cd5 (plain) (tree)



















































































































































                                                                                                                                      
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