public void OnFrame(object sender, FrameEventArgs args) { // Get the most recent frame and report some basic information Frame frame = args.frame; Hand h; if (frame.Hands.Count == 0) { return; } h = frame.Hands[0]; Console.WriteLine(string.Format("Velocity is {0}", h.PalmVelocity)); palm.Move(h.PalmPosition, h.PalmVelocity); if (palm.Stopped) { // check if this is the first time we're reading that the hand is stopped if (!handStopped) { Console.WriteLine("Beat!"); handStopped = true; // possible beat. get volume data, centroid of movement, and append the tempo to the queue TimeSpan dur = palm.PreviousDuration; Vector centroid = palm.Centroid; Vector startPos = palm.StartPosition; Vector stopPos = palm.StopPosition; oscHandler = new OSCHandler(); float estTempo = 60 * 1000 / dur.Milliseconds; oscHandler.SendTempo((int)Math.Round(estTempo)); // X centroid of hand during movement = pan Vector normCentroid = bounder.NormalizePoint(centroid); oscHandler.SendPan((double)normCentroid.x); // get normalized distance by normalizing the points Vector startNorm = bounder.NormalizePoint(startPos); Vector stopNorm = bounder.NormalizePoint(stopPos); oscHandler.SendVolume(stopNorm.DistanceTo(startNorm)); } // otherwise, check if the hand meets fermata threshold else if (palm.DurationStopped > Listener.fermataThreshold) { Console.WriteLine(string.Format("Duration stopped is {0}, threshold is {1}", palm.DurationStopped, Listener.fermataThreshold)); oscHandler = new OSCHandler(); oscHandler.SendFermata(); } } else { // check if it was stopped previously if (handStopped) { oscHandler = new OSCHandler(); oscHandler.SendTempo(); } handStopped = false; } }
/// <summary> /// Event responder to receiving a new frame /// </summary> /// <param name="sender"></param> /// <param name="args"></param> public void OnFrame(object sender, FrameEventArgs args) { // Get the most recent frame and report some basic information Frame frame = args.frame; InteractionBox box = frame.InteractionBox; double xBounds = frame.InteractionBox.Width; Hand h; // search through detected hands int matchIndex = -1; for (int i = 0; i < frame.Hands.Count; i++) { if (frame.Hands[i].IsRight && UseRightHand) { matchIndex = i; break; } else if (frame.Hands[i].IsLeft && !UseRightHand) { matchIndex = i; break; } } if (matchIndex < 0) { // no matching hands were detected. just send the last played tempo oscHandler.SendTempo(); return; } h = frame.Hands[matchIndex]; // further stabilize this position by adding the average of the last three points xPositions.EnqueueMovingAverage(h.StabilizedPalmPosition.x, 3); lastTwoBeatsPositions.Add(h.StabilizedPalmPosition.x); //allPositions.Add(h.StabilizedPalmPosition); double xBackAvg = xPositions.BackAverage(.8); double xFrontAvg = xPositions.FrontAverage(.2); double averageXpos = 0; if ((xBackAvg * xFrontAvg < 0 && xPositions.Length() > 20)) { BeatAmt++; Console.WriteLine("Beat!"); if (BeatAmt % 2 == 0) { averageXpos = lastTwoBeatsPositions.Average(); lastTwoBeatsPositions.Clear(); } xPositions.Clear(); if (firstBeat) { // not enough data to create a tempo. we will use this as a starting point startTime = DateTime.Now; initialPosition = h.PalmPosition; firstBeat = false; return; } else { TimeSpan span = DateTime.Now - startTime; startTime = DateTime.Now; double durSeconds = span.Seconds + (span.Milliseconds / 1000.0); int estTempo = (int)Math.Round(60 / durSeconds); estimatedTempos.Enqueue(estTempo); var initialNorm = box.NormalizePoint(initialPosition); var currentNorm = box.NormalizePoint(h.StabilizedPalmPosition); float dist = initialNorm.DistanceTo(currentNorm); Console.WriteLine(string.Format("Actual 3D normalized dist {0}", dist)); double xDist = Math.Abs(currentNorm.x - initialNorm.x); var nonNormDist = initialPosition.DistanceTo(h.StabilizedPalmPosition); Console.WriteLine(string.Format("Non normalized dist {0}", nonNormDist)); dist = nonNormDist / 100; // reset initial position initialPosition = h.StabilizedPalmPosition; // send volume based on scale of distance if (BeatAmt % 2 == 0) { Vector avgXPosition = new Vector((float)averageXpos, 0, 0); Vector normX = box.NormalizePoint(avgXPosition); oscHandler.SendPan(normX.x); oscHandler.SendVolume(dist * 2 > 1 ? 1 : dist * 2); // round the average to the nearest 5 to prevent too many changes oscHandler.SendTempo((int)Math.Round(estimatedTempos.Average() / 5) * 5); } Console.WriteLine("-----"); } } else { // check if the time between the last beat time and the current time is greater than the threshold for a fermata } }