Archiv der Kategorie: Programmierung

Visual Studio 2013 und 2015 : Show Line Numbers in editor / Zeilennummern im Editor anzeigen

Problem

Der Visual Studio Quellcode Editor zeigt keine Zeilennummern am linken Rand.
The Visual Studio Source Code editor is not showing line numbers on the left side.

Approach – Ansatz

Use the Tools->Options Menu to activate line numbers
Über den Menüpunkt Extras->Optionen können Sie Zeilennummern einblenden

Solution – Lösung

options

ASP.NET C#: Windows Authentication / Single Sign On

Problem

In einer ASP.NET Seite möchte man den Windows-Anmeldebenutzer ermitteln.

Ansatz / Approach

In der Web-Anwendung muss man zunächst den Haken „Enable Anonymous Access“ entfernen und einen Haken bei „Enable Windows Authentication“ setzen.

Lösung / Solution

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Summary description for AuthenticationService
/// </summary>
public class AuthenticationService
{
   public AuthenticationService()
   {
	//
	// TODO: Add constructor logic here
	//
   }

    public string getUsername()
    {
        string windowsLogin = System.Web.HttpContext.Current.User.Identity.Name;

        if (windowsLogin == null) return "none";

        int hasDomain = windowsLogin.IndexOf(@"\");
        if (hasDomain > 0)
        {
            windowsLogin = windowsLogin.Remove(0, hasDomain + 1);
        } //end if 

        return windowsLogin;
    }
}

VST Plugins in C++ mit WDL-OL: Signalverarbeitung durch INSERT-Effekte und ihre Auswirkungen

Intention

In diesem Artikel dokumentiere ich meine ersten Erkenntnisse, die ich als Informatiker, Musiker und Cubase-Benutzer bei der Entwicklung von VST Plugins in C++ mache. Der Artikel wirkt daher sehr Ich-bezogen, da ich mich auf meinen eigenen Explorations-Lerntyp konzentriere. Ich bin allerdings kein Egozentriker :-/ …

Vorwort

Als musik- und programmierbegeisterterter DAW-Nutzer (ich bin Cubase Fan), fehlt einem oft noch der Draht zu der eigentlichen Audiosignalverarbeitung, die sich durch (Hall-/Echo-/Sustain-…) Effekt-Algorithmen und Heuristken manifestiert und dem eigentlich Werkzeug das Leben einhaucht, dass es benötigt um eine Audioverarbeitungsaufgabe mit mathematischen Modellen zu erfüllen.

Es ist mir als Informatiker bewusst, dass digitale Signale über eine Soundkarte gesendet werden, um dann über einen A/D-Wandler im analogen, physischen Raum Schalldruckschwankungen über Lautsprechermembranen zu erreichen. Ich kenne WAV-Dateien, und weiß dass diese in unterschiedlichen Sample-Raten (44100 Hz, 22050 Hz, 48000 Hz, 96000 Hz… [Samples/Sekunde])  und Auflösungen (z.B. 16 Bit, 24 Bit, 32 Bit float) existieren.

Als Cubase-Nutzer kenne ich die ASIO-Einstellungen (Menü Geräte –> Geräte konfigurieren) und habe bereits den Parameter Buffer Size bemerkt, welcher sich proportional auf die Eingangs- und Ausgangslatenzen, sowie reziprok auf meine CPU-Auslastung auswirkt.

asio_buffer_size

Als Musiker weiß ich geringe Latenzzeiten natürlich zu schätzen :-). Wer kann schon ein Instrument mit dem richtigen Timing auf den Takt einspielen, wenn er das akustische Ergebnis verzögert hört.

Nach dem Artikel Rechenlast beim Mixen verringern aus der c’t musik kreativ 2016 – S. 113 splittet man aufgrund dieses Buffers die Aufnahme in 3 Teile:

  1. Aufnahmephase: Alle komplexen INSERT-Effekte rausnehmen, kleine Sample Buffer einstellen, alle Spuren in Mono Aufnehmen die nicht zwingend Stereo sein müssen (Gesang, Kick, Bass….). Der Mix wird hierdurch auch transparenter, wenn man die Mono-Spuren im Nachgang im Stereopanorama verteilt.
  2. Mixingphase: Aufwendige Effekte hinzuschalten, Sample-Buffer erhöhen
  3. Masteringphase: Rohmix auf Stereospur mit 24-Bit Wortbreite rendern, hohen Sample-Buffer einstellen, so dass man die Masteringeffektkette wieder auf 96 khz fahren kann.

VST Insert-Effekte

Das Grundgerüst

Nachdem ich nun mit dem WDL-OL Framework von Oli Larkin und Visual Studio 2015 ein kompilierfähiges C++-Grundgerüst dank des Tutorials von Martin Finke erzeugt hatte, bemerkte ich schnell den Anwendungsbereich der Signalverarbeitung, der sich für mich anfänglich unkompliziert durch Probieren und Testen offenbaren sollte. Dabei machte ich ein paar (für den Profi triviale) Feststellungen, die ich hier niederschreiben möchte.

Wie sieht nun ein INSERT-Effekt in C++ aus? Was bekomme ich von der DAW von außen geliefert? Was kann ich damit machen? Wie gebe ich es an die DAW zurück?

basic1

In C++ passiert bei einem INSERT-Effekt alles in der Funktion „ProcessDoubleReplacing“, die als Übergabeparameter

  • die Amplitudenwerte des zu bearbeitenden Signals (*input)
  • die Amplitudenwerte des bearbeiteten Signals (*output)
  • die Puffergröße der ASIO-Einstellungen (hier 512)

als Zeiger erhält. Da diese Zeiger auf den tatsächlichen Wert im output-Buffer zeigen, kann die Funktion ohne Rückgabeparameter auskommen und wird VOID deklariert.

Digitale Verzerrung

Einer der einfachsten INSERT Effekte ist die digitale Verzerrung, bei der lediglich die Amplituden abgeschnitten werden müssen. Im Gegensatz zu einer weichen „analogen“ Verzerrung, wie sie durch die Röhren eine Gitarrenverstärkers statt finden kann und durch die Klangcharakteristik eines hart aufgehängten Lautsprechers in ihrer „Wärme“ abgerundet wird, legt die digitale Verzerrung lediglich durch das Abschneiden von Amplituden (auch Clipping genannt) wert auf Distortion / Verzerrung um jeden Preis.

Ein Gitarrenröhrenverstärker fügt dem Signal zunehmend geradzahlige Harmonische (Obertöne) zu und das Signal wird zunehmend weich begrenzt (soft clipping – Wärme).

Bei der digitalen Verzerrung nähern wir uns einer Rechteckform des Signals an (hard clipping – Digitale Verzerrung).

softvshardclipping

Links: Hard-Clipping (Digitale Verzerrung)
Rechts: Soft-Clipping (Wie bei einer Röhre)

Der Hard-Clipping-Algorithmus (links) flacht also nicht wie rechts die Spitzen ab sondern nimmt einfach den überschreitenden Wert als gegebenes Maximum hin. Programmiert sieht das folgendermaßen aus:

mainfunction

mThreshold: Beinhaltet einen Wert zwischen 0 und 1, der mit einem Regler eingestellt wurde.

fmin(): Gibt hier den input-Amplitudenwert zurück, es sei denn mThreshold wird überschritten – dann wird mThreshold zurückgegeben.

fmax(): Gibt den input-Amplitudenwert zurück, es sei den mThreshold wird unterschritten, dann wird -mThreshold zurückgegeben.

 

Oszillation auf die Welle „draufmodulieren“

Ich schrieb eine Klasse „Oscillator.cpp“, die eine Sinus- bzw. Cosinusschwingung generierte. Zunächst dachte ich, dass das simple „addieren“ einer Welle auf die andere eine völlig andere Klangcharakteristik erzeugen würde…. aber es erzeugte eher etwas wie das „Zusammenmischen“ von zwei Signalquellen, so als ob man ein Signal mit dem Mischpult in das andere „reindreht“. Wenn ich so recht drüber nachdenke kann ein Lautsprecher ja auch nur „eine“ Welle erzeugen… diese Welle muss sich aber je Signalquelle unterscheiden… Man erreicht also das „Mixen“ mehrerer Signalquellen durch das aufaddieren von Schwingungen. Und an dieser Stelle wird einem auch klar, dass eine natürliche Schwingung, beispielsweise der Ton eines Instrumentes, aus mehreren Teilschwingungen besteht und nur durch unsere Erfahrung als zwei oder mehrere unterschiedliche Signalquellen interpretiert werden kann. So hat zum Beispiel bei einem Schlagzeug die Bass-Drum einen hohen „Klick-Anteil“, einen druckbringenden „Körper-Anteil“ und einen tiefen „Bass-Anteil“, den man über einen Equalizer separieren kann, und der sich alleinstehend völlig anders anhört.

basic3

Phasenauslöschung: Wenn sich Wellen gegenseitig auslöschen

Ich richtete den linken und den rechten Kanal nun aufeinander und dachte dass sich das „zugemischte“ Signal durch die 180 Grad Phasenverschiebung (um PI) vollständig auslöschen müsste. In Wirklichkeit wurde es aber nur leiser. Ich vermutete, dass hier die kreisförmige Ausdehnung des Schalls aus den Boxen eine Rolle spielt. Wenn man dies bereits im Rechner macht, ist das Resultat bekanntermaßen Stille.

sin(x)+sin(x+PI)=0;

Der Cosinus ist quasi eine Phasenverschiebung um 90 Grad. In einer DAW könnte dies durch das Verschieben einer Audiospur nach rechts bedeuten.

phase_02

180 Grad ist dann noch weiter geschoben…

phase_03

(Bild-Quelle: delamar.de)

Jetzt werden beim Zusammenmischen der beiden Quellen die Amplitudenwerte addiert, wie es im Abschnitt „Oszillation auf die Welle draufmodulieren“ bereits gezeigt wurde. Und genau diese Tatsache führt also zu einer Phasenauslöschung! Eine Phasenauslöschung kann also auch durch die ungünstige Lage von Audiomaterial auf der Zeitachse stattfinden. Wen man das Material ein Stück nach rechts oder links schiebt (natürlich so, dass es nicht merkbar ist) könnte das Resultat auch wieder anders aussehen.

Wenn ich nun die Boxen aufeinander richte erhalte ich tatsächlich Stellungen im Raum, an denen das Signal fast verschwunden ist. Durch die kreisförmige Ausdehnung des Schalls um die Boxen wird es aber nicht vollständig terminiert.

Hier habe ich mein Experiment dokumentiert:

Schalte ich den Cubase Stereo Out Mix auf Mono, indem ich das „Stereo Enhancer“ Plugin in den INSERT-Effekten des Stereo-Outs auf Mono hinzuschalte (links unten ist ein MONO-Button wenn es geladen wurde), ist das Signal wirklich verschwunden bevor es den Computer verlassen hat (Phasenauslöschung bereits Digital).

VST Instrumente

Der Unterschied zu Insert-Effekten

Im Tutorial von Martin Finke wird ein Python-Skript verwendet, um aus den IPlugSamples ein Template für ein neues Projekt zu generieren. Als Grundlage meiner bisherigen Projekte wurde immer das selbe Startprojekt IPlugEffekt verwendet. Meine Vermutung war zunächst, dass jetzt ein anderes Template als Grundlage für ein VST Instrument genutzt wird. Allerdings kann man einen VST Insert Effect mit wenigen Handgriffen in der Quelldatei „ressource.h“ in ein VST Instrument umwandeln.


// #define PLUG_CHANNEL_IO "1-1 2-2"
#if (defined(AAX_API) || defined(RTAS_API))
#define PLUG_CHANNEL_IO "1-1 2-2"
#else
// no audio input. mono or stereo output
#define PLUG_CHANNEL_IO "0-1 0-2"
#endif

 

// …
#define PLUG_IS_INST 1

// …
#define EFFECT_TYPE_VST3 „Instrument|Synth“

// …
#define PLUG_DOES_MIDI
[/javascript]

„0-1 0-2“ bedeutet kein Input und einen Output (Mono) oder  kein Input und zwei Outputs.

PLUG_IS_INST 1“ macht aus dem INSERT Effect endgültig ein Instrument.

Inputs sind bei Instrumenten unnötig, da ein Instrument selber als Signalquelle für den Gesamt-Mix genutzt wird. Die Funktion „ProcessDoubleReplacing“ bekommt als Übergabeparameter allerdings weiter hin die Inputs geliefert. Ich habe noch nicht herausgefunden wofür das gut sein soll ;-).

Inputs sind bei Instrumenten unnötig, da ein Instrument selber als Signalquelle für den Gesamt-Mix genutzt wird. Die Funktion „ProcessDoubleReplacing“ bekommt als Übergabeparameter allerdings weiter hin die Inputs geliefert. Ich habe noch nicht herausgefunden wofür das gut sein soll ;-).

Kostenloses VST3 Effect-Plugin / Free VST3 effects plugin: Digitale Verzerrung / Digital Distortion

Download kostenloses VST3 Plugin Digitale Verzerrung | VST3 Effect Download

Nach dem Download können Sie das Plugin einfach in Ihr VST3 Verzeichnis kopieren (z.B. C:\Program Files (x86)\Common Files\VST3)

Just copy the VST3 Plugin into your VST3 Directory (i.e. C:\Program Files (x86)\Common Files\VST3 ).

Bei diesem VST3 Plugin handelt es sich um eine einfache digitale Verzerrung.

Der Regler lässt sich von 0 Prozent bis 100 Prozent (links) drehen, je näher man an die 100 Prozent kommt, desto stärker werden die Amplituden abgeschnitten. Bei leiseren Signalen muss man ganz nach links drehen. Am 100 % Anschlag ist allerdings die Welle ausgelöscht :-). Also immer ein paar Cent weiter rechts bleiben und die Lautstärke wieder anheben (diese wird ebenfalls abgeschwächt). Eine automatische Lautstärkenkorrektur findet nicht statt, da die Lautheit durch die Annäherung an ein Rechtecksignal relativ hoch wird, sollte dies nämlich besser individuell eingepegelt werden.

Screenshot: Der Effekt „Distortion -> Hard Digital Distortion“ wurde bei den INSERT-Effekten einer Spur in Steinberg Cubase an erster Stelle ausgewählt und dessen GUI über den „e“-Button hervorgebracht.

digitale_verzerrung

 

Komplette IDE mit PHP- und Javascript-Debugging unter Windows unter Verwendung von Wampserver [v3.0.0] und „Eclipse for PHP Developers“ (Eclipse PDT) MARS.2 [v4.5.2]

Problem

Für das Debugging von PHP Webanwendungen wird eine PHP Debuggingumgebung benötigt.

Ansatz

Die kostenlose Anwendung WAMPSERVER (hier v.3.0.0) wird mit „Eclipse for PHP Developers“ (MARS.2) konfiguriert, um das Debugging zu ermöglichen.

Vorgehensweise

  • Download von Wampserver unter http://www.wampserver.de
  • Installation als Administrator (rechte Maustaste „als Administrator ausführen“)
    • z.B. in c:\dev\wamp
  • Download von „Eclipse for PHP Developers“ unter http://www.eclipse.org
  • Entpacken von „Eclipse for PHP Developers“ in ein gewünschtes Verzeichnis

Lösung

Nachdem der Wampserver gestartet wurde und unter der URL http://localhost erreichbar ist, kann bereits mit der Konfiguration von Eclipse begonnen werden.

  1. Eclipse starten
  2. Workspace direkt im WWW root auswählen (bspw. bei Installation in c:\dev\wamp)
    workspace
  3. Mit OK bestätigen
  4. Im Menü „Window -> Preferences“ wählen
    menu_window_preferences
  5. PHP Executable hinzufügen
    PHP_Executables
  6. PHP Executable angebenTab_PHP_Executable
  7. Unten auf den Button „Next->“ klicken (nicht im Screenshot da Edit-Dialog)
  8. Debugger angeben -> XDebug auswählen!Tab_Debugger
  9. Mit okay bestätigen
  10. Einstellungen unter Menu->Preferences->Debug überprüfen (ist der angelegte Debugger aktiviert?).einstellungen_debug
  11. Web Browser angeben (ich empfehle Google Chrome)eclipse_preferences_webbrowser
  12. Neues PHP Projekt anlegen
    neues_php_projekt
  13. Folgende Einstellungen tätigen neues_php_projekt_auswahl
  14. Rechtklick auf das neu angelegte Projekt -> New -> PHP Fileneues_php_projekt_datei_hinzufuegen
  15. Die Datei beispielsweise index.php benennen new_phpfile_index_benennen
  16. Test-Sourcecode in index.php einfügen
    &lt;?php
    	$i=0;
    	$i++;
    	$i=$i+1;
    	print $i;
    ?&gt;
    
  17. Breakpoint setzen (Doppelklick links neben die Zeile)
    debug_configuration_index_Debugger2
  18. Debug Configuration für die Website anlegen (rechts neben die Debug Wanze klicken -> Debug Configurations)
    debugger_wanze
  19. Debug Configurations -> PHP Web Application -> index -> Server
    debug_configuration_index_serverDie Startdatei /Bier.de/index.php entspricht auch dem Aufruf über http://localhost/Bier.de/index.php, da wir den Workspace im c:\dev\wamp\www-rootverzeichnis angelegt haben.
  20. Debug Configurations -> PHP Web Application -> index -> Debugger
    debug_configuration_index_Debugger
    Wenn „Break at First Line“ ausgewählt ist, hält der Debugger automatisch bei der ersten Zeile an. Dies ist nicht immer gewünscht!
  21. Debug Button klicken
  22. Bestätigen dass auf die PHP Debug Perspektive gewechselt wird
  23. Für das Javascript-Debugging Empfehle ich dringend den ausgereiften Chrome Javascript Debugger zu verwenden. Dieser lässt sich in Chrome folgendermaßen starten:
    chrome-debugger1
  24. Hier kann man Breakpoints setzen und den Objektbaum jederzeit einsehen:
    chrome-debugger2

 

 

 

 

Microsoft IIS 7: Windows Authentication fehlt / missing (Single-Sign-On einstellen)

Problem

Eine Seite soll für Windows Authentication konfiguriert warden, im Bereich IIS unter dem Punkt „Authentication“ soll ein Punkt „Windows Authentication“ sein. Dieser ist nicht vorhanden.

Voraussetzungen

Es wird eine Windows Server Variante verwendet (nicht Windows 7 Home Editions)

Ansatz – Approach

Die Server-Rolle muss nachinstalliert warden.

Lösung – Solution

1.) Den Server Manager starten
server_manager_starten

2.) Einen Rollenservice auf dem IIS-Unterpunkt hinzufügen
Add_Role_Services

3.) Auswahl der Authentifizierungsmethode
select_authmethods

4.) Nun ist unter dem Punkt „Windows Authentication“ im Bereich IIS der Punkt „Windows Authentication“ vorhanden, dieser kann ausgewählt warden und Anonymous Login kann disabled warden.
punkt_vorhanden

Excel VBA: Kommandozeile / Command Line / DOS Parameter an Excel übergeben

Problem

An eine Excel-Datei soll ein Kommandozeilenparameter übergeben werden, der in VBA weitergenutzt werden kann.

Ansatz – Approach

  • Nutzung der Kernel32.dll-Bibliothek
  • Deklaration von Kernel32-Funktionen
    • GetCommandLineW
    • lpString
    • RtlMoveMemory
  • Erstellung einer Funktion für die Verwendeung
  • Beispielaufruf

Lösung – Solution

Im Modulkopf von Modul1.bas (oder auch in der Arbeitsmappe) werden Funktionen deklariert:

Modulkopf

1.) Modulkopf (Modul1.bas): Deklaration der Kernel Funktionen für die Ausführung von Kommandozeilenparametern:

' Used at module level to declare the default 
' lower bound for array subscripts (Array starts with 0)
Option Base 0

' Erzwingt die explizite Deklaration aller 
' Variablen in einer Datei 
Option Explicit

' Deklariert die Funktionen aus kernel32.dll 
Declare Function GetCommandLine Lib "kernel32" Alias "GetCommandLineW" () As Long
Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (MyDest As Any, MySource As Any, ByVal MySize As Long)

2.) Erstellen einer einfachen Funktion, die die Ausführung von Kommandos anhand der kernel32.dll-Funktionen erlaubt.

Function CmdToSTr(Cmd As Long) As String
Dim Buffer() As Byte
Dim StrLen As Long
   If Cmd Then
      StrLen = lstrlenW(Cmd) * 2
      If StrLen Then
         ReDim Buffer(0 To (StrLen - 1)) As Byte
         CopyMemory Buffer(0), ByVal Cmd, StrLen
         CmdToSTr = Buffer
      End If
   End If
End Function

3.) Wenn das Workbook (die Arbeitsmappe) geöffnet wird, soll der Parameter (hier /cs:irgendwas ) zur Weiterverwendung genutzt werden können

Private Sub Workbook_Open()
    Dim CmdRaw As Long

    Dim CmdLine As String
    Dim start As Integer
    'The return value is a pointer to the command-line string for the current process.
    CmdRaw = GetCommandLine
    CmdLine = CmdToSTr(CmdRaw)
    
    start = InStr(CmdLine, "/cs:")
    ende = Len(CmdLine) - start - 3
    Tabelle1.Cells(1, 1) = Right(CmdLine, ende)

    mainForm.Show
End Sub

4.) Aufruf der Datei

C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.exe C:\tracematrix.xlsm /cs:meinParameter

.NET C#: Execute command line batch file and process the output line by line (line break treatment)

Problem

A Batch File should be executed and the output processed line by line. This is especially useful when you want to generate line break treatments.

Ansatz – Approach

The usage of a stream reader helps to process the output line by line.

Solution – Lösung

Process p = new Process();

// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;

p.StartInfo.FileName = "D:\\doors_stats\\whatschanged.bat";
p.Start();

StreamReader sr = p.StandardOutput;
string output = "";
while (!sr.EndOfStream)
{
	// Do s.th. with the received line (i.e. concate)
	output += sr.ReadLine() + "\n\n<br/>";
}

.NET C# : Verzeichnis rekursiv kopieren / Copy folder with subfolders (recursive)

Problem

A directory folder with subfolders should be copied. Ein Verzeichnis mit allen Unterverzeichnissen soll rekursiv kopiert warden.

Approach

Usage of DirectoryInfo Class: getDirectories(); in combination with „foreach (DirectoryInfo subdir in dirs)“-Loop
Usage of FileInfo Class: getFiles() in combination with „foreach (FileInfo file in files)“-Loop and Object-Method „file.CopyTo(DESTINATION_FOLDER, true);“

Solution – Lösung

public void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
    // Get the subdirectories for the specified directory.
    DirectoryInfo dir = new DirectoryInfo(sourceDirName);
    DirectoryInfo[] dirs = dir.GetDirectories();

    if (!dir.Exists)
    {
        throw new DirectoryNotFoundException(
            "Source directory does not exist or could not be found: "
            + sourceDirName);
    }

    // If the destination directory doesn't exist, create it.
    if (!Directory.Exists(destDirName))
    {
        Directory.CreateDirectory(destDirName);
    }

    // Get the files in the directory and copy them to the new location.
    FileInfo[] files = dir.GetFiles();
    foreach (FileInfo file in files)
    {
        string temppath = Path.Combine(destDirName, file.Name);
        file.CopyTo(temppath, true);
    }

    // If copying subdirectories, copy them and their contents to new location.
    if (copySubDirs)
    {
        foreach (DirectoryInfo subdir in dirs)
        {
            string temppath = Path.Combine(destDirName, subdir.Name);
            DirectoryCopy(subdir.FullName, temppath, copySubDirs);
        }
    }
}