Блог Дмитрия Сошникова

про технологии и человеческое счастье

You are currently browsing the archives for Март, 2014.

Приглашаю на очередной #openbirthday #40

Приглашаю вас на празднование моего открытого дня рождения #openbirthday 2014! В этом году я не поленился, и детали мероприятия описаны на официальном сайте http://www.openbirthday.ru. Кстати, чтобы сделать этот сайт я потратил около 15 минут – развернул WordPress в Windows Azure, прикрутил к нему имевшийся ранее домен, сконфигурировал красивую тему и отредактировал текст записи. Ну чем не чудеса облачных технологий?

Детали мероприятия:

  • Суббота, 29 марта 2014 г.
  • С 12:00 до последнего посетителя (хотя в 19:00 уходит мой поезд в Саратов).
  • Антикафе “Территория общения“, 2 минуты от м. Чеховская, Пушкинская, Тверская

Очень приглашаю всех друзей, знакомых, коллег (из Майкрософт, МАИ, НИУ ВШЭ, МФТИ и т.д.), студентов-партнеров, бывших и нынешних студентов, заглянуть и разделить со мной радость этого дня! В программе мероприятия:

  • Беседы на около-IT-шные темы, небольшой мозговой штурм на тему приближающейся сингулярности и гибели человечества, по вопросам образования и фотографирования котиков
  • Мини-хакатон (по желанию), я захвачу с собой Leap Motion и Makey-Makey. Если хотите в этом участвовать – захватите свой ноутбук!
  • Чайная церемония гун фу ча
  • Знакомства и запись поздравлений
  • Настольные игры и специальный ведущий игровой части – @vickievalerie

Правила проведения #openbirthday:

  • Я буду рад видеть всех, кто придет – знакомых или не очень. Можно и нужно приходить без приглашения.
  • #OpenBirthday подразумевает #NoPresents. Приходите без подарков, подарком будет ваше присутствие. Но если вы принесете с собой что-нибудь вкусное, то все будут вам признательны. Можно еще принести книжки для #BookCrossing
  • Вы самостоятельно оплачиваете своё пребывание в антикафе по стандартным расценкам (2 руб./мин), приходите и уходите в любое удобное для вас время (для упрощения логистики)

Контактная информация: @shwars. Если вы пришли, а никого нет – значит произошел форс-мажор и мы переместились в другое место, о чем я обязательно напишу в твиттере. Если вы хотите придти после 15:00 – лучше позвонить, чтобы убедиться, что критическая масса людей еще на месте.

Надеюсь, до скорой встречи!

Дмитрий Сошников

Add a comment

Цифровой терменвокс на базе Leap Motion (powered by .NET)

С момента появления сенсора Kinect for Windows я питал тихую страсть к программированию такого рода устройств – ведь это волшебное чувство, когда написанная тобой программа отзывается на движения человека на расстоянии! Сегодня я расскажу вам про программирование ещё одного похожего устройства – Leap Motion.

6tag_060314-114131

По сути дела, Leap Motion – это небольшой Kinect, который может распознавать положение кистей рук. По замыслу создателей (хорошо отраженных в этом видео), его можно использовать для управления компьютером во множестве различных сценариев. В этом посте мы рассмотрим, как программируется Leap Motion (на платформе .NET), и как можно не его основе создать простой музыкальный инструмент – терменвокс. Вот такой:

Простейший терменвокс на базе Leap Motion

  

Leap Motion для программиста

С точки зрения программиста, Leap Motion предоставляет набор удобных API (документированных тут), которые позволяют:

  • С высокой частотой (более, чем 60-100 кадров в секунду) получать модель пространства, включающую в себя координаты и скорости пальцев рук, нормали ладоней, положения и скорости различных “инструментов” (Leap Motion хорошо распознает карандаши и авторучки)
  • Распознавать основные жесты: окружность, swipe, нажатие
  • Эмулировать touch surface, т.е. касания некоторой виртуальной поверхности перед экраном
  • Распознавать основные движения рук и пальцев (motions), транслируя их в преобразования поворота, перемещения или масштабирования.

В отличие от Kinect, Leap Motion не предоставляет доступа к 3D-данным, полученным с камеры

Программировать Leap Motion можно на различных языках и платформах, в том числе .NET. В этой статье мы рассмотрим использование первой возможности – доступа к модели руки.

Отслеживаем простейшие движения

Для наших экспериментов создадим пустой WPF-проект, и добавим на основной экран цветную окружность. Нашим первым шагом будет научиться перемещать эту окружность по экрану движениями пальца. Итак, разметка основной странички (XAML) будет выглядеть так:

<Window x:Class="LeapVoxSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="768" Width="1024" Background="Black">
    <Canvas>
        <Ellipse x:Name="ptr" Fill="Yellow" Height="30" Width="30"/>
    </Canvas>
</Window>

Для использования Leap Motion необходимо скачать Leap Motion SDK, и подключить к проекту ссылку на LeapCSharp.NET4.0.dll. Однако это еще не всё – Leap SDK требует также библиотек Leap.dll и LeapCSharp.dll, которые должны находится в одной директории с выполняемым файлом проекта. Поэтому найдите эти файлы в директории LeapSDK\lib\x86 (в той директории, где установлен Leap SDK), перетащите их в проект Visual Studio и установите свойства “действия при компиляции = контент, копировать в выходную директорию = копировать, если новее”.

Все общение с контроллером Leap ведется через объект Controller. Создадим такой объект в нашем основном файле MainWindows.xaml.cs:

Controller Leap = new Controller();

Теперь Leap Motion готов предоставлять нам кадры с данными о положении рук. Получать кадры можно двумя способами:

  • Передать в объект Controller экземпляр класса Listener, в котором будет перегружен метод OnFrame. Этот метод будет автоматически вызываться Leap Motion SDK с максимально возможной частотой кадров.
  • Создать свой метод, который будет периодически опрашивать класс Controller и получать с него текущий кадр. Так следует поступать, есть в программе уже есть естественный цикл, или если мы хотим выполнять код в UI-потоке выполнения.

В нашем случае для создания цикла опроса конроллера используем DispatcherTimer, который будет срабатывать 30 раз в секунду:

DispatcherTimer dt = new DispatcherTimer()
    {
        Interval = TimeSpan.FromSeconds(1 / 30)
    };

public MainWindow()
{
    InitializeComponent();
    dt.Tick += dt_Tick;
    dt.Start();
}

В методе dt_Tick будет сосредоточена основная логика отслеживания движений. Мы получаем текущий кадр (Frame), и если в этом кадре видны пальцы – берем первый попавшийся их них и используем его координаты, чтобы изменить положение окружности:

void dt_Tick(object sender, EventArgs e)
{
    var fr = Leap.Frame();
    if (fr!=null && fr.Fingers.Count>0)
    {
        var f = fr.Fingers[0];
        Canvas.SetLeft(ptr, 512 + f.TipPosition.x);
        Canvas.SetTop(ptr, 768-f.TipPosition.y);
    }
}

Мы добились того, что можем перемещать кружок по экрану, передвигая палец над контроллером Leap Motion. Пример кода на данном этапе можно посмотреть на GitHub.

Программная генерация звука различной высоты

Для программной генерации звука различной высоты мы используем библиотеку NAudio. Простейший способ добавить поддержку NAudio в проект – использовать Nuget, набрав в консоли диспетчера пакетов:

install-package NAudio

Процесс генерации звука переменной высоты подробно описан в статье Чарльза Петцольда на MSDN. Если коротко – мы создаем класс, который генерирует синусоидальную волну звука, и передаем её на вход методу NAudio, который эту волну воспроизводит. При этом есть ряд тонкостей: чтобы звук менялся более плавно, необходимо плавно менять частоту звука, и при этом учитывать задержку буферизации аудио. Все эти тонкости учтены в классе PortamentoSineWaveOscillator.cs, который необходимо поместить в проект.

Для генерации звука мы создаем объект типа WaveOut и инициализируем его, передавая экземпляр созданного нами осциллятора:

WaveOut WaveGen = new WaveOut();
PortamentoSineWaveOscillator Osc = new PortamentoSineWaveOscillator(44100,120);

Инициалиацию мы проводим в конструкторе страницы:

WaveGen.Init(Osc);
WaveGen.Play();

Теперь нам достаточно изменять свойство Osc.Pitch, чтобы соответствующим образом менялась высота звука, и Osc.Amplitude для изменения громкости. Пускай горизонтальные движения пальцев отвечают за громкость, а вертикальные – за высоту звука. Коэффициенты подбираются опытным путем для достижения кофортного звучания:

void dt_Tick(object sender, EventArgs e)
{
    var fr = Leap.Frame();
    if (fr!=null && fr.Fingers.Count>0)
    {
        var f = fr.Fingers[0];
        ...
        // Меняем высоту звука
        var p = Math.Abs(f.TipPosition.y / 2);
        var a = 255 - Math.Abs(f.TipPosition.x);
        if (p >= 0 && p <= 150) Osc.Pitch = p;
        if (a >= 0 && a <= 255) Osc.Amplitude = (short)a;
    }
}

Версию проекта на этой стадии можно получить тут.

Последние штрихи

Чтобы сделать проект чуть более красивым, вместо обычного круга, перемещаемого по экрану, можно добавить спец.эффекты на основе системы частиц (Particle Systems). Я взял за основу вот эту статью на CodeProject, где приводится исходный код WPF-контрола, представляющего собой источник частиц. Заменив им окружность, добавленную на первом шаге, мы получим финальный проект, исходный код которого доступен на GitHub.

Домашнее задание

Если вы захотите продолжить эксперименты, то простор для творчества практически неограничен! В частности, можно:

  • Добавить поддержку многоголосия и управления сразу несколькими пальцами
  • Экспериментировать с другими способами управления высотой звука, например, брать за основу не положение пальца, а его скорость
  • Добавить поддержку жестов для извлечения специальных звуков (сэмплов)

Если вас будет интерес к этой теме (пишите в комментариях), то я продолжу серию статей, добавляя различные дополнительные интересности, связанные с Leap Motion, Kinect и неожиданным использованием мобильных устройств. О чем вам бы хотелось услышать? Например, в этом видео показано, что ещё можно сделать с помощью Leap Motion за пару часов:

Мини-хакатон с Leap Motion – результаты

Add a comment