-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathMainWindow.cs
131 lines (111 loc) · 4.89 KB
/
MainWindow.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
namespace Microsoft.Psi.Samples.LinuxWebcamWithAudioSample
{
using System;
using System.IO;
using System.Reflection;
using Gdk;
using Microsoft.Psi;
using Microsoft.Psi.Audio;
using Microsoft.Psi.Imaging;
using Microsoft.Psi.Media;
/// <summary>
/// Webcam with audio sample program.
/// </summary>
public class MainWindow : Gtk.Window
{
private readonly Gtk.Image displayImage;
private readonly Gtk.Label displayText;
private readonly Gtk.LevelBar displayLevel;
private Pipeline pipeline;
private byte[] imageData = new byte[640 * 480 * 3];
/// <summary>
/// Initializes a new instance of the <see cref="MainWindow"/> class.
/// </summary>
public MainWindow()
: base("Webcam with Audio Sample")
{
// create the window widgets from the MainWindow.xml resource using the builder
using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Microsoft.Psi.Samples.LinuxWebcamWithAudioSample.MainWindow.xml");
using StreamReader reader = new StreamReader(stream);
var builder = new Gtk.Builder();
builder.AddFromString(reader.ReadToEnd());
this.Add((Gtk.Widget)builder.GetObject("root"));
// get the widgets which we will modify
this.displayImage = (Gtk.Image)builder.GetObject("image");
this.displayText = (Gtk.Label)builder.GetObject("value");
this.displayLevel = (Gtk.LevelBar)builder.GetObject("level");
// window event handlers
this.Shown += this.MainWindow_Shown;
this.DeleteEvent += this.MainWindow_DeleteEvent;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (disposing)
{
this.pipeline?.Dispose();
this.displayImage?.Dispose();
this.displayText?.Dispose();
this.displayLevel?.Dispose();
}
base.Dispose(disposing);
}
private void MainWindow_Shown(object sender, EventArgs e)
{
// Create the \psi pipeline
this.pipeline = Pipeline.Create();
// Create the webcam component
var webcam = new MediaCapture(this.pipeline, 640, 480, "/dev/video0", PixelFormatId.YUYV);
// Create the audio capture component
var audio = new AudioCapture(this.pipeline, new AudioCaptureConfiguration { DeviceName = "plughw:0,0", Format = WaveFormat.Create16kHz1Channel16BitPcm() });
// Create an acoustic features extractor component and pipe the audio to it
var acousticFeatures = new AcousticFeaturesExtractor(this.pipeline);
audio.PipeTo(acousticFeatures);
// Fuse the webcam images with the audio log energy level
var webcamWithAudioEnergy = webcam.Join(acousticFeatures.LogEnergy, RelativeTimeInterval.Past());
// Overlay the audio energy on the webcam image and display it in the window.
// The "Do" operator is executed on each fused webcam and audio energy sample.
webcamWithAudioEnergy.Do(
frame =>
{
// Update the window with the latest frame
this.DrawFrame(frame);
},
DeliveryPolicy.LatestMessage);
// Start the pipeline running
this.pipeline.RunAsync();
}
private void DrawFrame((Shared<Image> Image, float AudioLevel) frame)
{
// copy the frame image to the pixel buffer
var pixbuf = this.ImageToPixbuf(frame.Image);
// clamp level to between 0 and 20
var audioLevel = frame.AudioLevel < 0 ? 0 : frame.AudioLevel > 20 ? 20 : frame.AudioLevel;
// redraw on the UI thread
Gtk.Application.Invoke(
(sender, e) =>
{
this.displayImage.Pixbuf = pixbuf;
this.displayLevel.Value = audioLevel;
this.displayText.Text = audioLevel.ToString("0.0");
});
}
private Pixbuf ImageToPixbuf(Shared<Image> image)
{
var length = image.Resource.Stride * image.Resource.Height;
if (this.imageData.Length != length)
{
this.imageData = new byte[length];
}
image.Resource.CopyTo(this.imageData);
return new Pixbuf(this.imageData, false, 8, image.Resource.Width, image.Resource.Height, image.Resource.Stride);
}
private void MainWindow_DeleteEvent(object o, Gtk.DeleteEventArgs args)
{
this.pipeline.Dispose();
this.pipeline = null;
}
}
}