Tag Archives: Flash

Next Generation User Interfaces How-To: Gesten

Der „X-Y-Positions-Anzeiger für ein Bildschirmsystem“, kurz Maus, ist das Standardeingabegerät für grafische Benutzungsschnittstellen (GUI) geworden. Doch dabei kann mit der Maus weit mehr erreicht werden, als einfach nur das Ziehen und Klicken in Anwendungen. Die Kombination der verschiedenen Maustastenzustände und der Mausposition erlaubt ein Benutzererlebnis ähnlich zur Wii ganz ohne weitere Hardware (weiter unten mehr zur Wii).

image Einfache Maus-Interaktionen wie Drücken, Bewegen und Loslassen der Maus ergeben in Kombination nicht nur Benutzereingaben wie „Drag and Drop“ sondern können auch als Geste für das Durchschneiden eines Objektes am Bildschirm dienen. Für die Flash-Welt liefert der Düsseldorfer David Ochmann unter http://davidochmann.de/#/info?p=462 eine Bibliothek namens DoGestures für ActionScript 2 und 3, die das Verwenden von Mausgesten erleichtert.

Zur Nutzung von DoGesture in Flash muss dessen Klassenpfad erst einmal verfügbar gemacht werden. Dies geschieht über das Menü „Datei -> Einstellungen für das Veröffentlichen“, dann im Register Flash über die Einstellungen für ActionScript. Dort wird der Quellpfad hinzugefügt.

Als nächstes wird nur noch der folgende Code benötigt, um die Klassen per Import bekannt zu machen, die Geste zu erzeugen und auf deren Ereignis zu warten sowie eine passende Ereignisbehandlung durchzuführen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Mache Klassen verfügbar
import de.davidochmann.utilities.dogesture.DoGesture;
import de.davidochmann.utilities.dogesture.events.GestureEvent;
 
// Erzeuge Geste (der ausführliche Weg)
var movedown:DoGesture = new DoGesture(stage);
 
// Lausche dem Ereignis, dass die Geste stattfand
movedown.addEventListener(GestureEvent.GESTURE_COMPLETE, movedownCompleteHandler);
// Wie lange darf das Ausführen der Geste dauern
movedown.setTimeout(1000); 
// Definiere die notwendigen Bewegungen für die Geste
movedown.add( 0, 50);
// Starte das Warten auf die Geste
movedown.start(); 
 
// Ereignismethode
function movedownCompleteHandler(e:GestureEvent):void
{
	// Was soll nun passieren...
	trace("Geste wurde durchgeführt!");
}

image Microsoft Surface ist ein Tisch aus dem Jahre 2007. Er zeichnet sich durch eine berührungsempfindliche Oberfläche aus, der u. a. per Mulit-Touch und durch mehrere Nutzer gleichzeitig bedient werden kann.

Der Maus droht seit ihrer Erfindung 1 963 durch Douglas C. Engelbart und William English Konkurrenz durch die Eingabe mit dem Finger oder anderen Körperteilen. Im Falle von Single-Touch, dient der eine Finger in der Tat auch meist eher als Mausersatz und das sogar mit ganz massiven Nachteilen: Der Finger verdeckt die Informationen am Bildschirm und führt bei der Arbeit an senkrechten Flächen zu schnell ermüdenden Armen – ähnlich wie bei der Arbeit an einer Schultafel führt.

Sobald mehrere Berührungspunkte möglich sind, lassen sich neue intuitive Gesten jenseits der Mausbedienung formulieren. Bekannt sind das Drehen und Skalieren von Inhalten mit zwei Fingern.

Silverlight bietet bereits seit Version 3 Multi-Touch. Dabei beschränkt sich Silverlight abhängig von der Abspielplattform auf die einzelnen Berührungspunkte. Gesten müssen selber erkannt und verarbeitet werden. Ein Beispiel inkl. Quellcode findet sich unter http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4b281bde-9b01-4890-b3d4-b3b45ca2c2e4.

image Für eine einfache Touch-Anwednung in Silverlight benötigen wir ein beliebiges sichtbares Objekt, dass in diesem Beispiel mit monster benannt ist. Alles Weitere geschieht dann in der Code-Behind-Datei. Als erstes wird dort ein Transofrmations-Objekt für die Verschiebung des Monsters angelegt und das Ereignis für Berührungen angemeldet (Touch.FrameReported). In der Ereignismethode wird ab nun bei jedem Touch-Ereignis das Monster genau zu der Position der Berührung bewegt.

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
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
 
namespace SilverTouch
{
    public partial class MainPage : UserControl
    {
 
        public MainPage()
        {
            // Required to initialize variables
            InitializeComponent();
 
            Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded);
        }
 
        private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            // Erzeuge Transformationsobjekt für Verschiebung
            CompositeTransform transform = new CompositeTransform();
            monster.RenderTransform = transform;
 
            // Lausche auf Touch-Ereignis
            Touch.FrameReported += new System.Windows.Input.TouchFrameEventHandler(Touch_FrameReported);
        }
 
        private void Touch_FrameReported(object sender, System.Windows.Input.TouchFrameEventArgs e)
        {
            // Ermittle Tranformationsobjekt 
            CompositeTransform transform = monster.RenderTransform as CompositeTransform;
            // Ermittle primären Berührungspunkt
            TouchPoint tp = e.GetPrimaryTouchPoint(monster);
            // Verschiebe Objekt zum Berührungspunkt
            transform.TranslateX += tp.Position.X - (monster.ActualWidth / 2);
            transform.TranslateY += tp.Position.Y - (monster.ActualHeight / 2);
        }
    }
}

imageAuf dem Windows Phone Series 7 nutzt Silverlight für die Oberflächenelemente Manipulationsereignisse (u. a. ManipulationDelta). Diese teilen mit, inwiefern Skaliert oder Verschoben wurde. Um das Ereignis zu erhalten, kann in Expression Blend 4 oder Visual Studio 2010 bei einem Windows Phone Projekt ein Oberflächenelement mit einem Manipulationsereignis versehen werden.

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
<phoneNavigation:PhoneApplicationPage 
    x:Class="SilverPhone.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}">
 
    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!--TitleGrid is the name of the application and page title-->
        <Grid x:Name="TitleGrid" Grid.Row="0">
            <TextBlock x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"><Run Text="MY "/><Run Text="TOUCH "/><Run Text="APPLICATION"/></TextBlock>
            <TextBlock Text="touch me" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Style}"/>
        </Grid>
 
        <Grid x:Name="ContentGrid" Grid.Row="1">
            <Image x:Name="monster" ManipulationDelta="Main_ManipulationDelta" Source="Assets/monster.png" HorizontalAlignment="Center" VerticalAlignment="Center" Width="240" Height="342"/>
        </Grid>
 
    </Grid>
 
</phoneNavigation:PhoneApplicationPage>

In der zugehörigen Code-Behind-Datei muss dann zum einen ein Tranformationsobjekt für eine Skalierung oder Verschiebung angelegt und in der Ereignismethode für das Manipulationsereignis eine Transformation durchgeführt werden.

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
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Phone.Controls;
 
namespace SilverPhone
{
    public partial class MainPage : PhoneApplicationPage
    {
 
        public MainPage()
        {
            // Required to initialize variables
            InitializeComponent();
 
            Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded);
        }
 
        private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            // Erzeuge Transformationsobjekt für Verschiebung
            CompositeTransform transform = new CompositeTransform();
            monster.RenderTransform = transform;
        }
 
        // Ereignismethode
        private void Main_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            // Ermittle Tranformationsobjekt 
            CompositeTransform transform = monster.RenderTransform as CompositeTransform;
 
            // Verschiebe Objekt bzgl. der durchgeführten Manipulation
            transform.TranslateX += e.DeltaManipulation.Translation.X;
            transform.TranslateY += e.DeltaManipulation.Translation.Y;
        }
    }
}

Für Flash griff man bisher auf Zusatzprogramme zurück, die die notwendigen Daten – meist per TUIO (http://www.tuio.org/) – direkt an Flash übermittelten. Mit Flash Player 10.1 und AIR 2 hält Multi-Touch nun aber auch Einzug in die Flash-Welt. Abhängig von der Abspielplattform verstehen Flash und AIR einzelne Berührungspunkte und Gesten (gerade unter Mac OS ist das noch recht eingeschränkt, siehe auch http://www.adobe.com/devnet/flash/articles/multitouch_gestures.html).

1
2
3
4
5
6
if (!Multitouch.supportsGestureEvents) {
	Alert.show(&quot;Gesten werden nicht unterstützt&quot;, &quot;Hinweis&quot;);
} else {
	// Stelle sicher, Gesten zu nutzen
	Multitouch.inputMode = MultitouchInputMode.GESTURE;
}

Je nach Plattform werden unterschiedliche Gesten unterstützt (Multitouch.supportedGestures). Diese müssten sonst selbst aus den Berührungspunkten ermittelt werden.

Mit dem Flex 4 SDK und AIR 2 kann jedes interaktive Oberflächenelement Gesten nutzen. In den zugehörigen Ereignismethoden werden dann abschließend die Werte der Gesten verwendet.

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
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
			 xmlns:s="library://ns.adobe.com/flex/spark" 
			 xmlns:mx="library://ns.adobe.com/flex/mx"
			 creationComplete="windowedapplication_creationCompleteHandler(event)">
 
	<fx:Script>
		<![CDATA[
 
			import mx.controls.Alert;
			import mx.events.FlexEvent;
 
			protected function windowedapplication_creationCompleteHandler(event:FlexEvent):void
			{
				if (!Multitouch.supportsGestureEvents) {
					Alert.show("Gesten werden nicht unterstützt!", "Hinweis");
				} else {
					// Stelle sicher, Gesten zu nutzen
					Multitouch.inputMode = MultitouchInputMode.GESTURE;
				}
			}
 
			protected function image_gestureZoomHandler(event:TransformGestureEvent):void
			{
				// Skaliere Objekt
				(event.currentTarget as InteractiveObject).scaleX *= event.scaleX;
				(event.currentTarget as InteractiveObject).scaleY *= event.scaleY;
			}
 
			protected function image_gesturePanHandler(event:TransformGestureEvent):void
			{
				// Verschiebe Objekt
				(event.currentTarget as InteractiveObject).x += event.offsetX;
				(event.currentTarget as InteractiveObject).y += event.offsetY;
			}
 
			protected function image_gestureRotateHandler(event:TransformGestureEvent):void
			{
				// Drehe Objekt
				(event.currentTarget as InteractiveObject).rotation += event.rotation;
			}
 
		]]>
	</fx:Script>
 
	<mx:Image x="20" y="20" source="assets/monster.png" 
			  gesturePan="image_gesturePanHandler(event)"
			  gestureZoom="image_gestureZoomHandler(event)"
			  gestureRotate="image_gestureRotateHandler(event)"
			  />
 
</s:WindowedApplication>

image Silverlight bietet seit Version 2 mit dem InkPresenter eine weitere Eingabemöglichkeit: Diesmal mit dem Stift. Der InkPresenter zeichnet die einzelnen Punkte der Stift- oder Mausbewegung auf. Sofern verfügbar sogar drucksensitiv.

 

image In Expression Blend (oder auch mit Visual Studio) fügen Sie das Steuerlement InkPresenter ein und geben diesem einen Hintergrund (Background) hinzu, da andernfalls keine Eingaben erkannt werden. Klar, dass natürlich auch die Größen- und Positionsangaben passen müssen – in diesem Beispiel sind keine expliziten Angaben vorgenommen worden, da auf diese Weise die komplette Fläche ausgefüllt wird. Für die eigentliche Aufzeichnung der Stifteingabe nutzen wir das Drücken der linken Maustaste (MouseLeftButtonDown), das Bewegen der Maus (MouseMove) und die Nachricht, wenn der Bezug zur Maus wieder verloren wird (LostMouseCapture). Die zugehörigen Ereignismethoden landen in der zugehörigen Code-Behind-Datei:

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
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace SilverPen
{
	public partial class MainPage : UserControl
	{
 
		private Stroke currentStroke;
 
		public MainPage()
		{
			// Required to initialize variables
			InitializeComponent();			
		}
 
		private void inkPresenter_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
            // Starte mit der Aufzeichnung
			inkPresenter.CaptureMouse();
            // Merke die Punkte
			StylusPointCollection stylusPointCollection = new StylusPointCollection();
            // Füge die ersten Punkte hinzu
            stylusPointCollection.Add(e.StylusDevice.GetStylusPoints(inkPresenter));
            // Erstelle aus den Punkten einen Strich
			currentStroke = new Stroke(stylusPointCollection);
            // Zeichne den Strich (dieser wird später weiter aktualisiert)
			inkPresenter.Strokes.Add(currentStroke);
		}
 
		private void inkPresenter_LostMouseCapture(object sender, System.Windows.Input.MouseEventArgs e)
		{
            // Beende die Aufzeichnung
			currentStroke = null;
			inkPresenter.ReleaseMouseCapture();
		}
 
		private void inkPresenter_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
		{
			// Füge dem aktuellen Strich neue Punkte hinzu
    		if (currentStroke != null) {
        		currentStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkPresenter));
			}
		}
 
	}
}

Natürlich könnte das Aussehen des gezeichneten Striches (Stroke) über dessen Attribute variiert und zum Beispiel mit dem Druck des Stiftes kombiniert werden:

1
currentStroke.DrawingAttributes.Height = e.StylusDevice.GetStylusPoints(inkPresenter)[0].PressureFactor * 100;

Wenn man das wie im Beispiel unter http://msdn.microsoft.com/en-us/magazine/cc721604.aspx#id0090072 weitertreibt, dann ist sogar eine Handschriftenerkennung im Browser möglich.

Next Generation User Interfaces How-To: Bildverarbeitung

image Ein eindrucksvolles Beispiel für die Verarbeitung von Videodaten ist Eywriter (http://www.eyewriter.org). Hier war es das Ziel, zu möglichst geringen Kosten ein Eyetracking-System zu schaffen, dass es gelähmten Personen erlaubt, einen Computer mit den Augen zu Bedienen und so beispielsweise Texte zu verfassen oder Bilder zu malen.

Sowohl Flash als auch Silverlight erlauben die Nutzung einer Videokamera. Das gestaltet sich dabei sehr ähnlich zu dem Einsatz eines Mikrofons. Im Falle von Flash erhält man sogar wie beim Sound einen Wert zur Aktivität. Dieser beschreibt hier aber nicht die Lautstärke sondern die Veränderungen im Bild. Sprich: Je mehr man sich vor der Kamera bewegt, desto höher ist der Wert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var cam:Camera;
var video:Video;
// Ermittle die Standardkamera
cam=Camera.getCamera();
// Erzwinge die Verarbeitung durch den Flash Player
video = new Video();
video.attachCamera(cam);
// Überprüfe bei jedem &quot;Redraw&quot; des Bildschirms...
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
 
// ...die Aktivität vor der Kamera...
function enterFrameHandler(event:Event):void {
	trace(cam.activityLevel);
	// ...und zeichne eine Linie abhängig vom Wert!
	graphics.lineStyle(0);
	graphics.lineTo(500-x,500-cam.activityLevel*4);
	x--;
}

image Natürlich kann man noch einen Schritt weitergehen und die Bildinformationen auswerten. Ähnlich wie bei Sonys EyeToy (http://www.eyetoy.com/) aus dem Jahr 2003 lässt sich so ermitteln, welche Gesten jemand vor der Kamera durchführt. Am einfachsten geht dies, indem die Anwendung auf spezielle Farbwerte – beispielsweise dem Farbton der Hand – reagiert.

image Einen Schritt weiter geht Microsoft bei dem Project Natal, indem dort auch Tiefenmessung per Infrarot zum Einsatz kommen soll (http://www.xbox.com/en-US/live/projectnatal/). Project Natal befindet sich aktuell noch in der Entwicklung und soll zu Weihnachten 2010 verfügbar sein. Speziell für dieses Projekt hat Microsoft übrigens Johnny Chung Lee eingestellt, der durch seine Experimente mit der Wii bekannt geworden ist (http://johnnylee.net/projects/wii/), darunter ein preiswert umsetzbares Finger- und Headtracking sowie ein Multi-Touch Whiteboard.

Eine einfachere Art der Bilderkennung kommt häufig bei Augmented Reality zum Einsatz (http://saqoosha.net/en/flartoolkit/start-up-guide/ ). Hier wird ein in der Regel aus rechteckigen Blöcken aufgebautes Symbol in die Kamera gehalten und dessen Lage im Raum dient dann zur Steuerung eines Gegenstandes im Computer. Diese Form der erweiterten Realität basiert ursprünglich auf dem ARToolKit von Hirokazu Kato aus dem Jahre 1999 (http://sourceforge.net/projects/artoolkit/). Die Portierung für ActionScript 3 nennt sich FLARToolKit (http://www.libspark.org/wiki/saqoosha/FLARToolKit/en), die für Silverlight SLARToolkit (http://slartoolkit.codeplex.com/).

Für das Lesen eines Barcodes gibt es ebenfalls bereits fertige Bibliotheken wie die von Bernd Engelbrecht unter http://www.codeproject.com/KB/graphics/BarcodeImaging3.aspx. Für einen eigenen Barcode-Scanner ist eine Schaltfläche zum Start der Videoaufzeichnung notwendig.

1
2
3
4
5
6
7
8
9
<UserControl x:Class="SilverScanner.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
 
    <Grid x:Name="LayoutRoot" >
        <Button Content="Scan" Name="scanCapturingBtn" HorizontalAlignment="Left" VerticalAlignment="Top" Click="scanCapturingBtn_Click" />
    </Grid>
 
</UserControl>

Die Vorschau des Videobildes wird in der Code-Behind-Datei per CaptureSource erledigt und im Hintegrund dargestellt. Diese CaptureSource dient ebenfalls für das Ermitteln des Barcodes mit Hilfe der Klassen BarcodeImaging und BarcodeCapture aus dem Beispielprojekt für Silverlight unter http://www.silverlight.net/community/samples/silverlight-4/barcode-scanner/.

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
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
 
namespace SilverScanner
{
    public partial class MainPage : UserControl
    {
 
        CaptureSource captureSource;
        BarcodeCapture barcodeCapture;
 
        public MainPage()
        {
            InitializeComponent();
        }
 
        protected void activateCamera()
        {
            if (captureSource == null)
            {
                // Zeige Vorschau des Videobildes
                captureSource = new CaptureSource();
                captureSource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
                VideoBrush previewBrush = new VideoBrush();
                previewBrush.Stretch = Stretch.Uniform;
                previewBrush.SetSource(captureSource);
                LayoutRoot.Background = previewBrush;
                // Wähle möglichst gutes Videoformat für bessere Scan-Ergebnisse
                VideoFormat desiredFormat = new VideoFormat(PixelFormatType.Format32bppArgb, 640, 480, 12);
                captureSource.VideoCaptureDevice.DesiredFormat = desiredFormat;
                if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
                {
                    captureSource.Start();
                }
 
            }
        }
 
        private void scanCapturingBtn_Click(object sender, RoutedEventArgs e)
        {
            activateCamera();
 
            if (barcodeCapture == null)
            {
                // Starte das Erkennen des Barcodes
                barcodeCapture = new BarcodeCapture();
                barcodeCapture.BarcodeDetected += new EventHandler<barcodeeventargs>(onBarcodeDetected);
                barcodeCapture.CaptureSource = captureSource;
            }
        }
 
        private void onBarcodeDetected(object sender, BarcodeEventArgs e)
        {
            // Zeige gefundenen Barcode
            System.Diagnostics.Debug.WriteLine(e.Barcode);
        }
 
    }
}

Next Generation User Interfaces How-To: Spracheingabe

spracherkennung Die Eingabe von Befehlen funktioniert nicht nur per Kommandozeile sondern auch per Sprachsteuerung. In Windows finden sich die Einstellungen dafür in der Systemsteuerung unter „Erleichterte Bedienung -> Spracherkennung“.

Einige Interaktionsformen bekommt man geschenkt, wenn man sie – wie zum Beispiel die Sprachsteuerung – in seinem Betriebssystem einfach nur aktiviert und ein wenig trainiert. Wenn sich die zu bedienende Anwendung dann noch passend ins System integriert, dann funktioniert die Sprachsteuerung bereits. Schaltflächen in HTML-Dokumenten und auch in Silverlight- sowie Flex-Anwendungen werden dann einfach durch das Aufsagen der entsprechenden Beschriftung aktiviert. Wer sich nicht auf die eingebaute Spracherkennung verlassen möchte oder wo diese gar nicht erst verfügbar ist, der kann auf Bibliotheken zu Spracherkennung zurückgreifen. Didier Brun hat unter http://www.bytearray.org/?p=1151 eine solche Bibliothek bereits für den Flash Player 10.1 angekündigt. Oder man sendet die Sprachaufnahme an einen Server, der das dann verarbeitet…

soundactivity Einfacher geht es, wenn man sich nur mit der Lautstärke zufrieden gibt. Denn mit dem Flash Player können die angeschlossenen Audioquellen – auch mehrere gleichzeitig – genutzt werden. Ohne weiteren Aufwand erhält man dort auch die Lautstärke der jeweiligen Klangquelle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var mic:Microphone;
var sound:SoundTransform;
 
// Verhindere Rückkopplung und stelle die Lautstärke auf 0
sound = new SoundTransform(0);
 
// Ermittle das Standardmikrofon
mic = Microphone.getMicrophone();
// Erzwinge die Verarbeitung durch den Flash Player
mic.setLoopBack(true);
// Verhindere Rückkopplung 
mic.soundTransform = sound;
 
// Überprüfe bei jedem "Redraw" des Bildschirms...
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
 
// ...die Aktivität des Sounds (also die Lautstärke)...
function enterFrameHandler(event:Event):void {
	trace(mic.activityLevel)	
	// ...und zeichne eine Linie abhängig vom Wert!
	graphics.lineStyle(0);
	graphics.lineTo(500-x,500-mic.activityLevel*4);
	x--;
}

Die Lautstärke kann nun für zahlreiche Formen der Eingabe genutzt werden. Vom Applausometer über das Aufblasen von Ballons bis hin zum Vorwärtspusten eines Segelbootes (ja, natürlich zählt hier nur die Lautstärke, aber die Assoziationen in den meisten Gehirnen lassen einen doch eher pusten als das Boot anschreien).

Wem die reine Lautstärke nicht reicht, der kann sowohl mit AIR 2, mit Flash ab Flash Player 10.1 (Microphone SampleDataEvent.SAMPLE_DATA ) als auch mit Silverlight ab Version 4 (AudioSink.OnSamples) den kompletten Sound analysieren. Für den Flash Player 10.1 sieht das dann so aus:

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
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
            creationComplete="application_creationCompleteHandler(event)"
            >
 
   <fx:Script>
      <![CDATA[
         import mx.events.FlexEvent;
 
         protected function application_creationCompleteHandler(event:FlexEvent):void
         {
            var m:Microphone = Microphone.getMicrophone();
            m.addEventListener(SampleDataEvent.SAMPLE_DATA, microphone_sampleDate);
            m.setLoopBack(true);            
         }
 
         protected function microphone_sampleDate(event:SampleDataEvent):void {
            // Verarbeite die Bytes des Samples
            trace(event.data.bytesAvailable);
         }         
      ]]>
   </fx:Script>
 
</s:Application>