RoarAudio/Programmieren/VS

Aus UUGRN
< RoarAudio‎ | Programmieren
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Die Very Simple API oder auch VS ist eine API die sich an die Simple APIs verschiedener anderer Sound Systeme anlehnt und einen leichten Umstieg ermöglichen soll. Im Sie ist recht stark limitiert. Ihr größtes Limit liegt darin das sie im Normalfall nur einen Stream pro Klient verwalten kann.

Die VS ist vollständig Objekt-Orientiert und kann auch einige der Funktionen die RoarAudio herausstellen bedienen. Sie hat weiterhin Schnittstellen-Funktionen um an die Internen Objekte heran zu kommen und ermöglicht somit mit der normalen API gemischt verwendet zu werden.

Grundsätzlicher Ablauf

Zu Beginn wird ein VS Objekt erzeugt. Dieses ist Bereits mit dem Server verbunden. Nun werden Stream Parameter gesetzt und ein Stream auf dem Server erzeugt. Dies Kann auch in Kombination mit dem erzeugen des Objektes geschehen. Nun können Operationen auf das Objekt angewendet werden. Zum Beispiel können Audio Daten geschrieben werden. Nach dem man fertig ist wird das Objekt wieder Freigegeben und die Verbindung zum Server voll automatisch getrennt.

Fehlerbehandlung

Alle Funktionen verwenden -1 oder NULL zur Fehlerrückgabe. Sie haben einen Parameter namens error welcher dazu genutzt werden kann um einen Fehler Code zu bekommen.

Die Funktion roar_vs_strerr() kann dazu verwendet werden um Lesbare Fehlermeldungen zu erzeugen.

Beispiel

int err;
int ret;

ret = roar_vs_mute(vss, ROAR_VS_TRUE, &err);

if ( ret == -1 ) {
 fprintf(stderr, "Fehler: %s\n", roar_vs_strerr(err));
}

Öffnen einer Verbindung zum Server und eines Streams

Es gibt mehre Arten eine Verbindung zu öffnen. Prinzipiell unterscheiden sich zwei Arten: Ob zu Beginn nur eine Verbindung zum Server hergestellt werden soll, oder bereits ein Stream erzeugt wird. Ersteres kann interessant sein, sollte man erst ein paar Daten mit dem Server mittels der Haupt API austauschen wollen, bevor man den Stream erzeugt.

In diesem Teil soll jedoch nur behandelt werden wie man eine Verbindung mit sofortigem erzeugen deines Streams herstellt. Das Andere verfahren wird später beschreiben.

Zum herstellen einer Verbindung mit sofortiger Erzeugung eines Streams wird die Funktion roar_vs_new_simple() verwendet. Diese erwartet folgende Parameter:

  • Name des Servers (kann NULL sein),
  • Name des Klients (kann NULL sein, sollte aber nicht),
  • Die Sample Rate für den Stream (Übliche werte Schliesen 44100, 48000 und andere ein),
  • Die Anzahl der Kanäle für den Stream (1 für Mono, 2 fuer Stereo, ...),
  • Den Verwendeten Codec (Siehe nachfolgende Tabelle),
  • Die Anzahl der Bits pro Sample (Üblicherweise 8 oder 16),
  • Die Stream Direction (ROAR_DIR_PLAY für Playback),
  • Die Fehlercode Variable.

Der Rückgabewert ist das neue Verbindungs-Objekt oder NULL im Fehlerfall.

Beispiel

roar_vs_t * vss;

vss = roar_vs_new_simple(NULL, "myClient", rate, channels, ROAR_CODEC_DEFAULT, bits, ROAR_DIR_PLAY, &err);

Codecs

RoarAudio kann mehre verschiedene Codecs verwenden. Welche genau unterstützt sind hängt vom Server ab. Die nachfolgende Tabelle zeigt eine Auswahl der möglichen Codecs.

Codec Konstante Codec Name Anmerkungen
ROAR_CODEC_DEFAULT Signed Native PCM Vorzeichenbehaftetes Integer PCM in nativer Byte-Reihenfolge. Dies ist ein Alias auf ROAR_CODEC_PCM_S_y mit y der Byte-Reihenfolge des Klients.
ROAR_CODEC_PCM_x_y PCM Integer PCM. x kann S oder U sein für Vorzeichen behaftung oder Unvorzeichen behaftung. y ist die Byte-Reihenfolge und kann die werte LE, BE und PDP haben.
ROAR_CODEC_OGG_VORBIS Ogg Vorbis Der Vorbis Codec in Ogg. Die Parameter rate, bits und channels sollten auf 0 gesetzt werden.
ROAR_CODEC_RIFF_WAVE RIFF/WAVE Micro$oft .wav-Dateien. Die Parameter rate, bits und channels sollten auf 0 gesetzt werden.
ROAR_CODEC_AU AU .au-Dateien. Die Parameter rate, bits und channels sollten auf 0 gesetzt werden.
ROAR_CODEC_ALAW a-Law Der a-Law Codec. Er wird im europäischen ISDN Standard eingesetzt. Der Parameter bits sollte auf 8 gesetzt werden.
ROAR_CODEC_MULAW μ-Law Der μ-Law Codec. Er wird im US-Amerikanischen ISDN Standard eingesetzt. Der Parameter bits sollte auf 8 gesetzt werden.

Schließen der Verbindung

Zum Schließen der Verbindung wird kommt die Funktion roar_vs_close() zum Einsatz. Dieser wird das Verbindungs-Objekt, der Pointer zur Fehlercode Variable sowie der Parameter killit übergeben.

Der Parameter killit kann entweder ROAR_VS_TRUE oder ROAR_VS_FALSE sein. Ist er auf ROAR_VS_TRUE gesetzt wird die Wiedergabe sofort beendet. Ist er auf ROAR_VS_FALSE so wird der verbliebene Puffer (im Klient, Netzwerk und Server) erst zu ende abgespielt. Dies kann im besonderen dann einen Unterschied im Sekunden Bereich machen, sollte die Übertragung einen stark komprimierten Codec einsetzen.

Beispiel

int ret;

ret = roar_vs_close(vss, ROAR_VS_FALSE, &err);

Schreiben und Lesen von Audio Daten

Zum Schreiben und Lesen von Audio Daten stehen die Funktionen roar_vs_write() und roar_vs_read() zur Verfügung. Diese erhalten folgende Parameter:

  • Das Verbindungs-Objekt,
  • Den Puffer zu den Daten,
  • Die Länge der Daten in Byte,
  • Den Pointer auf die Fehlercode Variable.

Der Rückgabewert ist die Anzahl der wirklich geschriebenen oder gelesenen Bytes oder -1 im Fehlerfalle. Die Anzahl kann kleiner sein als die vorgegebene Länge. Hierbei handelt es sich nicht um einen Fehler sondern nur darum das zum aktuellen Zeitpunkt nicht mehr Daten geschrieben oder gelesen werden können. Ein Programm muss es dann erneut versuchen.

Beispiele

Hier sei ein Programm gezeigt welches zwischen zwei Verbindungen kopiert. Dieses Programm Liest die Fehlercodes nicht aus. Ein reelles Programm sollte dies tun.

ssize_t ret;
char buf[1024];

while ((ret = roar_vs_read(vss0, buf, sizeof(buf), NULL)) != -1) {
 if ( roar_vs_write(vss1, buf, ret, NULL) != ret ) {
  // Short-Write handling.
 }
}

Andere Operationen

Neben den Grundoperationen kann die VS API auch diverse Weitere Operationen durchführen. Diese sollen hier kurtz beschrieben werden.

Syncing

...

Blocking

Die normale Betriebsart für das Schreiben und Lesen von Streams ist Blocking. Das heißt, dass wenn man zu schnell schreibt oder liest der Schreib- oder Lesebefehl blockiert bis wieder genug Puffer oder Daten verfügbar ist. Dies dient dazu eine einfache Flusskontrolle zu haben. Für viele einfache Applikationen ist dies ausreichend. Mansche Applikationen benötigen es aber dass sie nicht an solchen Operationen Zwangs-Pausiert werden. Um dies zu unterbinden kann man in den so genannten Non-Blocking Modus gehen. In diesem Fall kehren die Ein-/Ausgabefunktionen unmittelbar zurück, auch wenn kein Puffer oder keine Daten verfügbar sind.

Die Funktion roar_vs_blocking() Kann verwendet werden um den Modus zu setzen. Die Funktion erwartet, neben Verbindungs-Objekt und Fehlercode Pointer, einen Wahrheitswert der den neuen Zustand angibt. Dieser kann entweder ROAR_VS_TRUE, ROAR_VS_FALSE, ROAR_VS_TOGGLE oder ROAR_VS_ASK sein.

Als Rückgabewert erhält man den alten Modus (ROAR_VS_TRUE für Blockend, ROAR_VS_FALSE für nicht blockend) oder -1 im Fehlerfall zurück.

Beispiel

int old;

old = roar_vs_blocking(vss, ROAR_VS_FALSE, &err);

Position und Latenz

...

Pause

Mit der Funktion roar_vs_pause() Kann man den Pause Status des Streams ändern. Diese Funktion erwartet folgende Parameter:

  • Verbinungs-Objekt,
  • Neuer Wert,
  • Pointer auf Fehlercode Variable.

Als Rückgabewert bekommt man den Alten Wert oder -1 im Fehlerfall.

Als neuer Wert kommen folgende mögliche Werte in Frage:

ROAR_VS_TRUE
Setzt das Pause Flag.
ROAR_VS_FALSE
Rücksetzt das Pause Flag.
ROAR_VS_TOGGLE
Wirft das Pause Flag um. Dies ist die empfohlene Verwendung.
ROAR_VS_ASK
Fragt nur den Aktuellen wert an.

Beispiel

int old;

old = roar_vs_pause(vss, ROAR_VS_TOGGLE, &err);

Mute

Bei RoarAudio gibt es neben der Lautstärkeregelung ein getrenntes Mute Flag. Dies kann mit der Funktion roar_vs_mute() Beeinflusst werden. Die Funktion roar_vs_mute() funktioniert exakt wie die Funktion roar_vs_pause() mit der Ausnahme das sie auf dem Mute Flag operiert.

Beispiel

int old;

old = roar_vs_mute(vss, ROAR_VS_TOGGLE, &err);

Lautstärke

Die Lautstärke des Streams kann sowohl gelesen als auch gesetzt werden. Hier soll beides Behandelt werden.

die VS API verwendet native floats zur darstellung der Lautstärke. Der Wertebereich ist 0 (Signal wird komplett ausgeblendet. Sollte jedoch nicht verwendet werden um eine Mute Funktion zu implementieren) bis 1 (Volle Signalstärke).

Gesetzt werden kann die Lautstärke entweder als Einkanal Wert oder als Stereo Wert. Die Funktion roar_vs_volume_mono() kann verwendet werden um sie als Einkanal Wert zu setzen. Diese Funktion erwartet neben dem Verbindungs-Objekt und dem Fehlerocode Pointer nur noch die neue Lautstärke.

Die Funktion roar_vs_volume_stereo() kann dazu verwendet werden den Wert als Stereo Wert zu setzen. Sie verwendet zwei Lautstärke Parameter. Einen für den linken und einen für den rechten Kanal.

Zum lesen kommt die Funktion roar_vs_volume_get() zum Einsatz. Diese erwartet, neben Verbindungs-Objekt und Fehlerocode Pointer, zwei Pointer, einen für den linken und einen für den rechten Kanal.

Möchte man nur eine Einkanal Information über die Lautstärke erfahren so kann man folgende Formel benutzen: <math>c = \frac{l + r}{2}</math>

Beispiele

float c, l, r;
int ret;

c   = 0.5;
ret = roar_vs_volume_mono(vss, c, &err);

l = 0.8;
r = 0.2;
ret = roar_vs_volume_stereo(vss, l, r, &err);

ret = roar_vs_volume_get(vss, &l, &r, &err);
c = (l + r)/2;

Meta Daten

Die Funktion roar_vs_meta() wird verwendet um Meta Daten zu setzen. Dies ist stark empfohlen.

Beispiel

int ret;
struct roar_keyval meta[] = {
 {"TITLE",   "Der Titel des Liedes..."},
 {"ARTIST",  "Ein Künstler"},
 {"VERSION", "Radio Remix"}
};
size_t len = sizeof(meta)/sizeof(*meta); // Länge des meta[]-Arrays in Elementen

ret = roar_vs_meta(vss, meta, len, &err);

Stream Rolle

Die Stream Rolle ist eine logische Gruppierung von Streams die einen bestimmten Zweck erfüllen. Sie wird mittels roar_vs_role() gesetzt.

Beispiel

int ret;

ret = roar_vs_role(vss, ROAR_ROLE_MUSIC, &err);

Liste möglicher Rollen

ROAR_ROLE_UNKNOWN
Die Funktion des Streams ist unbekannt. Dies ist der default.
ROAR_ROLE_NONE
(Sollte nicht verwendet werden)
ROAR_ROLE_MUSIC
Es handelt sich um Musik
ROAR_ROLE_VIDEO
Es handelt sich um die Audio Spur zu einem Video
ROAR_ROLE_GAME
Es Handelt sich um die Audio Spur eines Spiels
ROAR_ROLE_EVENT
Es handelt sich um ein Geräusch das zum Beispiel durch eine Fehler- oder Warnmeldung erzeugt wird.
ROAR_ROLE_BEEP
Es Handelt sich um ein Notify Beep (Sollte ehr nicht verwendet werden).
ROAR_ROLE_PHONE
Es Handelt sich um eine Echtzeit Sparchübertragung wie etwa einem Telephon.
ROAR_ROLE_BACKGROUND_MUSIC
Es Handelt sich um Hintergrund Musik. Man denke etwa an Kaufhäuser in denen leise Radio läuft.
ROAR_ROLE_VOICE
Es handelt sich um eine Sprach Spur. Zum Beispiel eine Ansage oder ein Sänger.
ROAR_ROLE_INSTRUMENT
Es Handelt sich um ein Instrument.
ROAR_ROLE_RHYTHM
Es Handelt sich um ein Rhythmus-Instrument.
ROAR_ROLE_CLICK
Es handelt sich um einen Click-Track.
ROAR_ROLE_MIXED
Es Handelt sich um bereits aus mehren Quellen vorgemischtes. (Dies wird in aller Regel nur verwendet wenn mehre Sound System mit einander Verbunden werden).

Noop

Die Funktion roar_vs_noop() sendet einen NOOP Befehl an den Server. Dieser wird diesen immer mit einem OK beantworten. Diese Funktion kann als Beispiel verwendet werden um den Server zu pingen oder um eine Art Keep Alive durch zu führen. Sie wird selten benötigt.

Beispiel

int ret;

ret = roar_vs_noop(vss, &err);

Interaktion mit der Haupt API

Dieser Teil soll nur die Grundlagen der Interaktion mit der Haupt API erläutern. Die Verwendung dieser soll hier nicht beschreiben werden da dies viel zu umfangreich für dieses Dokument währe.

Zugriff auf das Connection-, das Stream- und das VIO-Objekt

Wie auch unter Verwendung der Haupt API befindet sich im inneren des VS Verbindungs-Objekts eine Connection-, ein Stream- und ein VIO-Objekt. Auf diese kann man wie im folgenden Beispiel gezeigt mittels der Funktionen roar_vs_connection_obj(), roar_vs_stream_obj() und roar_vs_vio_obj() zugreifen.

Beispiele

struct roar_connection * con;
struct roar_stream     * stream;
struct roar_vio_calls  * vio;

con    = roar_vs_connection_obj(vss, &err);
stream = roar_vs_stream_obj(vss, &err);
vio    = roar_vs_vio_obj(vss, &err);

Verwenden einer bereits offenen Verbindung zu einem Server

Sollte bereits eine Verbindung bestehen kann das vorhandene Connection-Objekt verwendet werden um VS Verbindungs-Objekte davon zu erzeugen. Wichtig hierbei ist das bei trennen der Verbindung zu erst alle VS Verbindungs-Objekte getrennt werden müssen und danach erst das Connection-Objekt.

Das Vorgehen ein Connection-Objekt kann als Beispiel dann sinnvoll sein, sollten vielen VS Verbindungs-Objekte benötigt werden um das ständige Neu verbinden zu unterdrücken. Dies reduziert auch deutlich die möglichen Fehler.

Zur Verwendung einer externen Verbindung wird die Funktion roar_vs_new_from_con() verwendet. Diese benötigt als Parameter lediglich das Connection-Objekt und den Fehlercode pointer.

Es wird das neue Verbindungs-Objekt oder NULL zurück gegeben.

Ein Stream muss anschließend wie im folgenden gezeigt mittels roar_vs_stream() erzeugt werden.

Beispiel

roar_vs_t * vss;

vss = roar_vs_new_from_con(con, &err);

Verwendung von VS Verbindungs-Objekts mit nachträglicher Stream Erzeugung

Ein VS Verbindungs-Objekt muss nicht von Anfang an mit einem Stream verbunden sein. Dies kann als Beispiel dann interessant sein sollte man mittels Haupt API weitere Parameter mit dem Server ab prüfen wollen bevor man den Stream erzeugt. Auch kann man so einen zweiten Versuch starten einen Stream zu öffnen (mit anderen Parametern) sollte der Server den Stream mit den gewünschten Parametern nicht annehmen ohne neu Verbinden zu müssen.

Zu erst muss dazu ein Nicht mit einem Stream verbundenes Verbinungs-Objekt erzeugt werden. Dies kann entweder mittels der oben beschriebenen Funktion roar_vs_new_from_con() oder mittels der Funktion roar_vs_new() geschehen.

Im Gegensatz zu roar_vs_new_from_con() erzeugt roar_vs_new() selbstständig eine Verbindung zum Server. roar_vs_new() erwartet um dies zu tun drei Parameter: Die Adresse des Servers (oder NULL um Defaults zu verwenden), den Namen unseres Klienten und den Fehlercode Pointer. Siehe hierzu auch das Beispiel am ende dieses Teils.

Um nun einen Stream zu erzeugen und zu Verbinden wird die Funktion roar_vs_stream() verwendet. Diese benötigt, neben dem Verbindungs-Objekt und dem Fehlercode Pointer, das Audio-Informations Struct und die Angabe der Stream Direction. Sollte diese Funktion Fehlschlagen ist es möglich erneut zu versuchen einen Stream (mit anderen Parametern) zu verbinden. Ausgenommen hiervon ist der Fall, dass das Objekt bereits verbunden ist da in diesem Fall es nicht sinnvoll ist diese Funktion auf zu rufen.

Beispiele

roar_vs_t * vss;
struct roar_audio_info info;
int ret;

info.bits     = 16;
info.rate     = 44100;
info.channels = 2;
info.codec    = ROAR_CODEC_DEFAULT;

vss = roar_vs_new(NULL, "MyApp", &err);

// Fehler hier Behandeln.

ret = roar_vs_stream(vss, &info, ROAR_DIR_PLAY, &err);

Siehe Auch

UUGRN-Wiki verbessern („Stub”)

Dieser Artikel ist leider sehr kurz. Also: Sei mutig und mache aus ihm bitte einen guten Artikel, wenn du mehr zum Thema „RoarAudio/Programmieren/VS” weißt.