summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Halle <niklas@niklashalle.net>2020-12-06 12:01:17 +0100
committerNiklas Halle <niklas@niklashalle.net>2020-12-06 12:01:17 +0100
commite5dd70fa6273c030c32336257ed630fe377de6fd (patch)
treebb2e72cbb3d648d4012678c3c5910f7b6b218f1c
parent28d5505edae76ed91708a895815eecf542c23060 (diff)
downloadwdti_project-e5dd70fa6273c030c32336257ed630fe377de6fd.tar.gz
wdti_project-e5dd70fa6273c030c32336257ed630fe377de6fd.zip
much better
-rw-r--r--HarmoniousHarps_DemoMA01.mp3bin0 -> 1193837 bytes
-rw-r--r--HarmoniousHarps_DemoMA01.wavbin0 -> 10509764 bytes
-rw-r--r--test2.wavbin0 -> 2425544 bytes
-rw-r--r--test3.wavbin0 -> 4657004 bytes
-rw-r--r--test4.wavbin0 -> 3010310 bytes
-rw-r--r--theremine.m94
-rw-r--r--theremine.m~180
7 files changed, 242 insertions, 32 deletions
diff --git a/HarmoniousHarps_DemoMA01.mp3 b/HarmoniousHarps_DemoMA01.mp3
new file mode 100644
index 0000000..20d9f61
--- /dev/null
+++ b/HarmoniousHarps_DemoMA01.mp3
Binary files differ
diff --git a/HarmoniousHarps_DemoMA01.wav b/HarmoniousHarps_DemoMA01.wav
new file mode 100644
index 0000000..cf3bbb3
--- /dev/null
+++ b/HarmoniousHarps_DemoMA01.wav
Binary files differ
diff --git a/test2.wav b/test2.wav
new file mode 100644
index 0000000..7070595
--- /dev/null
+++ b/test2.wav
Binary files differ
diff --git a/test3.wav b/test3.wav
new file mode 100644
index 0000000..e696d2b
--- /dev/null
+++ b/test3.wav
Binary files differ
diff --git a/test4.wav b/test4.wav
new file mode 100644
index 0000000..d296887
--- /dev/null
+++ b/test4.wav
Binary files differ
diff --git a/theremine.m b/theremine.m
index f6fb28c..11f0dc0 100644
--- a/theremine.m
+++ b/theremine.m
@@ -5,42 +5,50 @@ clear;
%%%%%%%%
% how many updates per second, determines the length of audio snippets
-const_frames_per_second = 60;
+const_frames_per_second = 100;
-const_Fs = 96000; % sampling rate in Hz
+const_Fs = 44100; % sampling rate in Hz
const_te = 1/const_frames_per_second; % signal duration in seconds
-const_samples_per_frame = const_Fs * const_te;
+const_samples_per_frame = ceil(const_Fs * const_te);
const_sample_range = 0:const_samples_per_frame-1;
-const_fade_speed = 0.2;
+% factor the last read frame is multiplied by
+const_fade_speed = 0.975;
% signal "generator"
-signal = @(freq, amp) sin(freq ./ const_Fs .* 2 .* pi .* const_sample_range) * amp;
+signal = @(freq) (freq ./ const_Fs .* 2 .* pi .* const_sample_range);
% time given for calculation
-const_calc_offset = 5;
+const_calc_offset = 0;
% 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));
+deviceWriter = audioDeviceWriter('SampleRate', const_Fs, 'SupportVariableSizeInput', true, 'BufferSize', 3 * const_samples_per_frame);
%%%%%%%%%%%%%%%%%%%
% init matleap by calling for first frame %
%%%%%%%%%%%%%%%%%%%
-matleap_frame;
+matleap_frame
-% runtime vars
-P = NaN(100000,3);
+% runtime variables
+P = NaN(1000000,3);
count = 1;
done = false;
-freq_one = 0;
-freq_two = 0;
+x_one = 0;
+x_two = 0;
-signal_one = signal(0,0);
-signal_two = signal(0,0);
+y_one = 0;
+y_two = 0;
+
+offset_one = 0;
+offset_two = 0;
+
+signal_one = sin(signal(0));
+signal_two = sin(signal(0));
full_signal = signal_one + signal_two;
complete_signal = full_signal;
@@ -49,7 +57,7 @@ complete_signal = full_signal;
gesture_count = 0;
%while count < 100000 && gesture_count < 3
-while gesture_count < (1.5 * (const_frames_per_second - const_calc_offset))
+while gesture_count < (1 * (const_frames_per_second - const_calc_offset))
frame = matleap_frame;
handCount = size(frame.hands);
@@ -57,16 +65,20 @@ while gesture_count < (1.5 * (const_frames_per_second - const_calc_offset))
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;
+ y_one = y_one * const_fade_speed;
+ y_two = y_two * const_fade_speed;
% TODO
elseif isequal(one_hand, handCount)
% fade hand two out
- signla_two = signal_two * const_fade_speed;
+ y_two = y_two * const_fade_speed;
+
+ pos = frame.hands(1).palm.position;
+ %pos = frame.hands(1).palm.stabilized_position;
+
+ x_one = pos(1);
+ y_one = pos(2);
- 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;
@@ -78,29 +90,43 @@ while gesture_count < (1.5 * (const_frames_per_second - const_calc_offset))
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);
+ pos = frame.hands(1).palm.position;
+ %pos = frame.hands(1).palm.stabilized_position;
+
+ x_one = pos(1);
+ y_one = pos(2);
+
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);
+ pos = frame.hands(2).palm.position;
+ %pos = frame.hands(2).palm.stabilized_position;
+
+ x_two = pos(1);
+ y_two = pos(2);
else
- "That should not happen:"
- handCount
+ disp("That should not happen:");
+ disp(handCount);
return;
end
% play current sound
+ [signal_one, offset_one] = get_theremin_sound_bit(x_one, y_one, offset_one, signal);
+ [signal_two, offset_two] = get_theremin_sound_bit(x_two, y_two, offset_two, signal);
full_signal = signal_one + signal_two;
+ if deviceWriter(full_signal(:)) ~= 0
+ disp("Buffer ran empty!");
+ end
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);
+ %java.lang.Thread.sleep((1/(const_frames_per_second - const_calc_offset)) * 1000);
end
-theremin_player = audioplayer(complete_signal, const_Fs);
-play(theremin_player);
+release(deviceWriter)
+
+%theremin_player = audioplayer(complete_signal, const_Fs);
+%play(theremin_player);
% extract values
x = P(:,1); % links (-) rechconst_Ts (+) (LED zu uns)
@@ -129,7 +155,7 @@ xlabel('depth');
ylabel('left right');
zlabel('height');
-function sound = get_theremin_sound_bit(x, y, generator)
+function [sound,offset] = get_theremin_sound_bit(x, y, offset, generator)
% finding ranges for x and y:
%'x'
%min(x)
@@ -141,8 +167,12 @@ function sound = get_theremin_sound_bit(x, y, generator)
% --> 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
+ volume = y / 2000;
+ frequency = max(0.0001, (x + 400) / 1200) * 3000; % https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/60.17.html # How it works
- sound = generator(frequency, volume);
+ base = generator(frequency) + offset;
+
+ offset = base(end);
+
+ sound = sin(base) .* volume;
end \ No newline at end of file
diff --git a/theremine.m~ b/theremine.m~
new file mode 100644
index 0000000..1950a36
--- /dev/null
+++ b/theremine.m~
@@ -0,0 +1,180 @@
+clear;
+
+%%%%%%%%
+% "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_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
+const_fade_speed = 0.975;
+
+% signal "generator"
+signal = @(freq) (freq ./ const_Fs .* 2 .* pi .* const_sample_range);
+
+% time given for calculation
+const_calc_offset = 0;
+
+% 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));
+
+deviceWriter = audioDeviceWriter('SampleRate', const_Fs, 'SupportVariableSizeInput', true, 'BufferSize', 3 * const_samples_per_frame);
+
+%%%%%%%%%%%%%%%%%%%
+% init matleap by calling for first frame %
+%%%%%%%%%%%%%%%%%%%
+matleap_frame
+
+% runtime variables
+P = NaN(1000000,3);
+count = 1;
+done = false;
+
+x_one = 0;
+x_two = 0;
+
+y_one = 0;
+y_two = 0;
+
+offset_one = 0;
+offset_two = 0;
+
+signal_one = sin(signal(0));
+signal_two = sin(signal(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 * (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, offset_one] = get_theremin_sound_bit(x_one, y_one * const_fade_speed, offset_one, signal);
+ [signal_two, offset_two] = get_theremin_sound_bit(x_two, y_two * const_fade_speed, offset_two, signal);
+
+ % TODO
+ elseif isequal(one_hand, handCount)
+ % fade hand two out
+ [signal_two, offset_two] = get_theremin_sound_bit(x_two, y_two * const_fade_speed, offset_two, signal);
+
+ pos = frame.hands(1).palm.position;
+ %pos = frame.hands(1).palm.stabilized_position;
+
+ x_one = pos(1);
+ y_one = pos(2);
+
+ [signal_one, offset_one] = get_theremin_sound_bit(x_one, y_one, offset_one, 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.position;
+ %pos = frame.hands(1).palm.stabilized_position;
+
+ x_one = pos(1);
+ y_one = pos(2);
+
+ [signal_two, offset_two] = get_theremin_sound_bit(x_two, y_two * const_fade_speed, offset_two, signal);
+ P(count, 1:3) = pos;
+ count = count + 1;
+
+ pos = frame.hands(2).palm.position;
+ %pos = frame.hands(2).palm.stabilized_position;
+
+ x_two = pos(1);
+ y_two = pos(2);
+
+ [signal_two, offset_two] = get_theremin_sound_bit(x_two, y_two, offset_two, signal);
+ else
+ disp("That should not happen:");
+ disp(handCount);
+ return;
+ end
+
+ % play current sound
+ full_signal = signal_one + signal_two;
+ if deviceWriter(full_signal(:)) ~= 0
+ disp("Buffer ran empty!");
+ end
+ 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
+
+release(deviceWriter)
+
+%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,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)
+ % --> -300 < x < 300
+ % --> 0 < y < 600
+
+ % therefore
+ volume = y / 2000;
+ frequency = max(0.0001, (x + 400) / 1200) * 3000; % https://web.physics.ucsb.edu/~lecturedemonstrations/Composer/Pages/60.17.html # How it works
+
+ base = generator(frequency) + offset;
+
+ offset = base(end);
+
+ sound = sin(base) .* volume;
+end \ No newline at end of file