From cf424d42e34700b72173c265c75485ae81a5ab05 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Mon, 5 Apr 2021 15:23:02 +0200 Subject: bettering --- matleap.cpp | 2 +- theremin.m | 137 ++++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 78 insertions(+), 61 deletions(-) diff --git a/matleap.cpp b/matleap.cpp index 4a24d3d..7f109c9 100644 --- a/matleap.cpp +++ b/matleap.cpp @@ -252,7 +252,7 @@ void matleap::frame_grabber::open_connection() { } void matleap::frame_grabber::close_connection() { - mexPrintf("Good bye."); + mexPrintf("Good bye.\n"); } matleap::frame_grabber::~frame_grabber() { diff --git a/theremin.m b/theremin.m index 22f9991..3a1ebfe 100644 --- a/theremin.m +++ b/theremin.m @@ -1,33 +1,37 @@ clear; -%%%%%%%% +show_graphs = false; + +%%%%%%%%%%%%%%% % "constants" % -%%%%%%%% +%%%%%%%%%%%%%%% % how many updates per second, determines the length of audio snippets const_frames_per_second = 100; -const_Fs = 44100; % sampling rate in Hz +const_Fs = 44100; % sample rate in Hz const_te = 1/const_frames_per_second; % signal duration in seconds const_samples_per_frame = ceil(const_Fs * const_te); const_sample_range = 0:const_samples_per_frame-1; -% factor the last read frame is multiplied by +% the smaller the value, the quicker the fade out const_fade_speed = 0.975; -% signal "generator" -signal = @(freq) (freq ./ const_Fs .* 2 .* pi .* const_sample_range); +% signal "generator" - only gives the input for sin() +% it does not apply the sin function yet, see below for reasoning +signal_f = @(freq) (freq ./ const_Fs .* 2 .* pi .* const_sample_range); % 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)); +one_hand = size(NaN(1,1)); +two_hands = size(NaN(1,2)); -deviceWriter = audioDeviceWriter('SampleRate', const_Fs, 'SupportVariableSizeInput', true, 'BufferSize', 3 * const_samples_per_frame); +deviceWriter = audioDeviceWriter('SampleRate', const_Fs, ... + 'SupportVariableSizeInput', true, 'BufferSize', 3 * const_samples_per_frame); -%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % init matleap by calling for first frame % -%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% matleap_frame; % runtime variables @@ -38,18 +42,16 @@ done = false; frequency_pos = 0; height_pos = 0; -offset_one = 0; -offset_two = 0; +offset = 0; -signal_one = sin(signal(0)); -signal_two = sin(signal(0)); +signal = sin(signal_f(0)); -full_signal = signal_one + signal_two; -complete_signal = full_signal; +complete_signal = signal; % time gestures, used for program termination gesture_count = 0; +% main loop while gesture_count < const_frames_per_second frame = matleap_frame; handCount = size(frame.hands); @@ -95,17 +97,15 @@ while gesture_count < const_frames_per_second end % play current sound - [signal_one, offset_one] = get_theremin_sound_bit(frequency_pos, height_pos, offset_one, signal); - %[signal_two, offset_two] = get_theremin_sound_bit(x_two, y_two, offset_two, signal); - full_signal = signal_one;% + signal_two; + [signal, offset] = get_theremin_sound_bit(frequency_pos, height_pos, offset, signal_f); - buffer_under_flow = deviceWriter(full_signal(:)); + buffer_under_flow = deviceWriter(signal(:)); if buffer_under_flow ~= 0 disp("Buffer ran empty!"); end - complete_signal = [complete_signal full_signal]; + complete_signal = [complete_signal signal]; end release(deviceWriter) @@ -113,50 +113,67 @@ release(deviceWriter) %theremin_player = audioplayer(complete_signal, const_Fs); %play(theremin_player); -% extract values -x = P(:,1); % links (-) rechts (+) (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'); +if show_graphs == true + % extract values + x = P(:,1); % links (-) rechts (+) (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'); + + %{ + % Plot both audio channels + N = size(complete_signal,2); % Determine total number of samples in audio file + figure; + subplot(1,1,1); + stem(1:N, complete_signal(1,:)); + title('Audio Channel'); + % Plot the spectrum + df = const_Fs / N; + w = (-(N/2):(N/2)-1)*df; + y = fft(complete_signal(1,:), N) / N; % For normalizing, but not needed for our analysis + y2 = fftshift(y); + figure; + plot(w,abs(y2)); + %} +end -nexttile; -plot3(z,x,y); -xlabel('depth'); -ylabel('left right'); -zlabel('height'); +disp('If you want to save your audio, run `audiowrite(<.wav filename>, complete_signal, const_Fs)`'); function [sound,offset] = get_theremin_sound_bit(x, y, offset, generator) - % finding ranges for x and y: - %'x' - %min(x) - %max(x) - %'y' - %min(y) - %max(y) - % --> 50 < x < 270 - % --> 90 < y < 350 - - volume = (y) / 1300; - frequency = max(0.003, (x - 50) / 220) * 1000; % https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/60.17.html # How it works - + % the values used here are mostly empirical + volume = y / 1300; + % How it works: + % https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/60.17.html + frequency = max(0.003, (x - 50) / 220) * 1000; % have at least 3Hz + + % here we generate the array to put into sin(), but offset it with the + % the previous frames offset.. base = generator(frequency) + offset; + % ..which we take from here - doing so stops us from phase jumping offset = base(end); + % at last, apply the volume sound = sin(base) .* volume; end \ No newline at end of file -- cgit v1.2.3-54-g00ecf