
Kommandozeilenparser
~~~~~~~~~~~~~~~~~~~~

Datenquellen
~~~~~~~~~~~~

Es sind nacheinander drei Datenquellen abzuscannen:

  - Systemweite Defaults
  - Userspezifische Defaults
  - Kommandozeile

Die systemweiten und userspezifischen Einstellungen sind ber ein Filehandle
zu bekommen, in dem Newline-terminierte Argumente stehen:

    extern int  GetProgrammDefaultsMachine ( const char* ProgramBaseName );
    extern int  GetProgrammDefaultsUser    ( const char* ProgramBaseName );

Die Kommandozeile erfhrt das Modul ber einen von auen zu ttigen
Aufruf:

    void  setargv ( int argc, char** argv );

Je nach Betriebssystem kann dabei argv schon Wildcards aufgelst haben oder nicht.


=================================================================================================

Lesen und Schreiben von PCM-Dateien
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Alle Interaktion der AUDIO-Lib geschehen ber einen Zeiger von Typ AUDIO.
Es handelt sich dabei um eine anonyme Struktur von einem hnlichen Schlage wie
die berhmte Struktur FILE, die in C fr gepufferte Ein- und Ausgaben benutzt
wird. Gewonnen wird sie durch die Funktionsaufrufe audio_open_XXXXX und
audio_create_XXXXX. Sie enthlt alle fr die AUDIO-Lib intern notwendigen
Daten. Vernichtet wird die Struktur mittels audio_close(AUDIO*);


typedef struct {
    unsigned long        AUDIO_Signature;               // Signatur zum Erkennen gltiger AUDIO*-Strukturen
    unsigned int         AUDIO_Length;                  // Lnge dieser Struktur (kann auch fr Version-Checks mibraucht werden)
    int                  AUDIO_fd;                      // HANDLE oder SOCKET (Windows) oder int (Unix)
    int                  MIXER_fd;
    long double          SampleFreq;                    // Sample Frequenz
    unsigned int         Channels;                      // Anzahl der Kanle
    unsigned long long   Length;                        // Gesamtlnge in Samples pro Channel (oder -1 falls unendlich)
    unsigned long long   Position;                      // Aktuelle Position
    unsigned int         BitsPerSample;                 // Benutzte Bits pro Sample
    enum                 Coding;                        // linear, alaw, law (ADPCM wrde ich nicht untersttzen)
    unsigned long long   HeaderSize;                    // Offset des ersten Samples in der Datei
    unsigned int         IsSeekable      : 1;           // seek() works
    unsigned int         IsSocket        : 1;           // socket(), es ist mit recv/recvfrom und send/sendto statt mit read/write zu arbeiten
    unsigned int         UsesPopen       : 1;           // 1, wenn Daten von einem Coproze generiert werden
    unsigned int         UseDither       : 1;           // Erst in den 2.xx-Versionen benutzt
    unsigned int         UseShapedDither : 1;           // Erst in den 2.xx-Versionen benutzt
    unsigned int         UseNoiseShaping : 1;           // Erst in den 2.xx-Versionen benutzt
    const signed short*  RecodingTable;                 // law, Alaw, DAT-LongPlay etc.
    float                DitherLevel;
    const float*         DitherShapingCoeff;            //
    const float*         NoiseShapingCoeffs;            // NoiseShapingCoeffs[16], immer NS 16. Ordnung
    ...
} AUDIO;


Normalerweise legt die Quelldatei (WAV, AIFF, CDDA) gewisse Parameter fest. Beim Schreiben von Daten
oder bei Ausgabe auf einer Audiokarte gibt es so was nicht, dort mssen solche Parameter zustzlich festgelegt
werden. Die real eingestellten Parameter knnen aber von den geforderten abweichen (z.B. Samplefrequenz)
oder vllig anders sein (16 bit trotz geforderter 24 bit). Dies ist durch die Inspect-Funktionen
herauszufinden (es wrde aber auch gehen, da die richtigen Werte in die Struct zurckgeschrieben werden).

typedef struct {
    unsigned int        Channels;
    unsigned int        BitsPerSample;
    enum                Coding;
    long double         SampleFreq;
} AUDIO_ioctl;


Audiostrme knnen aufgemacht zum Lesen werden mittels:

AUDIO*  audio_open_filename         ( const char* filename, unsigned int ChunkNumber );
AUDIO*  audio_open_filedescriptor   ( int fd, unsigned int ChunkNumber );
AUDIO*  audio_open_socket           ( const char* IP, unsigned short Port, unsigned char TTL, int socktype, int prototype, ... );
AUDIO*  audio_open_socketdescriptor ( int socket_fd );
AUDIO*  audio_open_http             ( const char* URL );
AUDIO*  audio_open_module           ( const char* ModuleName, ... );
AUDIO*  audio_open_device           ( const char* DeviceName, const char* MixerName, AUDIO_ioctl* format, ... );
AUDIO*  audio_open_cuesheet         ( const char* filename );

XXX_filename: Daten werden aus einem Filename-Descriptor spezifiziert. Es kann sich hierbei
um eine regulre Datei, eine Named Pipe oder einen lokalen Socket handeln. Audiodevices sollten
damit nicht aufgemacht werden, dafr ist XXX_device da, das u.a. ein Mixerdevice mit erhlt und bei dem
Formatspezifikationen via format bergeben werden knnen.
XXX_cuesheet liest das Cuesheet aus (Datei) und arbeitet alle enthaltenen Dateien der Reihe nach ab.
XXX_filedescriptor arbeitet wie XXX_filename, es wird aber kein Name, sondern ein Handle bergeben.
XXX_socket ffnet einen Socket auf der IP:Port u.s.w.. Alle Daten, die von diese socket kommen, sind
z.B. als MP3/WAV oder was auch immer Stream zu interpretieren (OSI Layer 3 oder 4 Stream).
XXX_socketdescriptor wird hnlich zu XXX_filedescriptor schon mit einem fertigen Socket-Handles.
XXX_http arbeitet auf OSI Layer 5, d.h. hier ist z.B. noch eine Filauswahl und hnliches mglich.
XXX_module bekommt den Namen eines *.so-Modules sowie Inititialisierungsparameter mit bergeben. Gedacht fr
berechnete Signale.


AUDIO*  audio_create_filename        ( const char* filename, AUDIO_ioctl* format, unsigned int ChunkNumber );
AUDIO*  audio_create_filedescriptor  ( int fd, AUDIO_ioctl* format );
AUDIO*  audio_create_socket          ( const char* IP, unsigned short Port, AUDIO_ioctl* format, unsigned char TTL, int socktype, int prototype, ... );
AUDIO*  audio_create_socketdescriptor( int socket_fd );
AUDIO*  audio_create_device          ( const char* DeviceName, const char* MixerName, AUDIO_ioctl* format, ... );

Das gleiche noch mal fr die Ausgabe. Unterschied zu den audio_open_XXX-Rufen ist, da hier eine Format-Spezifier Pflicht ist.


int     audio_flush               ( AUDIO* ap );
off_t   audio_seek                ( AUDIO* ap, int whence, signed long long offset ); // in samples statt in bytes
off_t   audio_tell                ( AUDIO* ap );                // in samples statt in bytes
off_t   audio_filelength          ( AUDIO* ap );                // in samples statt in bytes
int     audio_close               ( AUDIO* ap );
int     audio_eof                 ( AUDIO* ap );
int     audio_error               ( AUDIO* ap );
int     audio_channels            ( AUDIO* ap );
long double
        audio_samplefreq          ( AUDIO* ap );
int     audio_ioctl               ( AUDIO* ap, AUDIO_ioctl* format );


Nun die eigentlichen Funktionen zum Lesen und Schreiben:

size_t  audio_read_interleaved_int16    ( AUDIO* ap, int16_t*   dst, size_t len );
size_t  audio_read_interleaved_int32    ( AUDIO* ap, int32_t*   dst, size_t len );
size_t  audio_read_interleaved_float32  ( AUDIO* ap, float32_t* dst, size_t len );
size_t  audio_read_interleaved_float64  ( AUDIO* ap, float64_t* dst, size_t len );

size_t  audio_read_consequent_int16     ( AUDIO* ap, int16_t*   dst, size_t len );
size_t  audio_read_consequent_int32     ( AUDIO* ap, int32_t*   dst, size_t len );
size_t  audio_read_consequent_float32   ( AUDIO* ap, float32_t* dst, size_t len );
size_t  audio_read_consequent_float64   ( AUDIO* ap, float64_t* dst, size_t len );

size_t  audio_read_indirect_int16       ( AUDIO* ap, int16_t**   dst, size_t len );
size_t  audio_read_indirect_int32       ( AUDIO* ap, int32_t**   dst, size_t len );
size_t  audio_read_indirect_float32     ( AUDIO* ap, float32_t** dst, size_t len );
size_t  audio_read_indirect_float64     ( AUDIO* ap, float64_t** dst, size_t len );

size_t  audio_write_interleaved_int16   ( AUDIO* ap, const int16_t*   dst, size_t len );
size_t  audio_write_interleaved_int32   ( AUDIO* ap, const int32_t*   dst, size_t len );
size_t  audio_write_interleaved_float32 ( AUDIO* ap, const float32_t* dst, size_t len );
size_t  audio_write_interleaved_float64 ( AUDIO* ap, const float64_t* dst, size_t len );

size_t  audio_write_consequent_int16    ( AUDIO* ap, const int16_t*   dst, size_t len );
size_t  audio_write_consequent_int32    ( AUDIO* ap, const int32_t*   dst, size_t len );
size_t  audio_write_consequent_float32  ( AUDIO* ap, const float32_t* dst, size_t len );
size_t  audio_write_consequent_float64  ( AUDIO* ap, const float64_t* dst, size_t len );

size_t  audio_write_indirect_int16      ( AUDIO* ap, const int16_t**   dst, size_t len );
size_t  audio_write_indirect_int32      ( AUDIO* ap, const int32_t**   dst, size_t len );
size_t  audio_write_indirect_float32    ( AUDIO* ap, const float32_t** dst, size_t len );
size_t  audio_write_indirect_float64    ( AUDIO* ap, const float64_t** dst, size_t len );

Zu interpretieren:
*_int16:    Daten werden als 16 bit signed integer abgespeichert.
*_int32:    Daten werden als 32 bit signed integer abgespeichert.
*_float32:  Daten werden als 32 bit FP abgespeichert.
*_float64:  Daten werden als 64 bit FP abgespeichert.

*interleaved*:  Werte sind interleaved, dst-typ wre damit eigentlich so was wie int16 [len][channels];
*consequent*:   Werte sind hintereinander, dst-typ wre damit eigentlich so was wie int16 [channels][len];
*indirect*:     dst zeigt auf ein Array mit je einem Eintrag pro Channel. Dieser zeigt auf die Daten.
                dst-typ wre damit eigentlich so was wie *int16 [channels];



Pflicht fr die erste Implementierung:

AUDIO*  audio_open_filename         ( const char* filename, unsigned int ChunkNumber );
// Untersttzung von FLAC, LPAC, SZIP etc. ber Koprozesse

AUDIO*  audio_open_filedescriptor   ( int fd, unsigned int ChunkNumber );
AUDIO*  audio_open_device           ( const char* DeviceName, const char* MixerName, AUDIO_ioctl* format, ... );
                                                // Windows und Linux

AUDIO*  audio_create_filename       ( const char* filename, AUDIO_ioctl* format, unsigned int ChunkNumber );
AUDIO*  audio_create_filedescriptor ( int fd, AUDIO_ioctl* format );
AUDIO*  audio_create_device         ( const char* DeviceName, const char* MixerName, AUDIO_ioctl* format, ... );
                                                // Windows und Linux


size_t  audio_read_interleaved_int16    ( AUDIO* ap, int16_t*   dst, size_t len );
size_t  audio_read_interleaved_int32    ( AUDIO* ap, int32_t*   dst, size_t len );
size_t  audio_read_interleaved_float32  ( AUDIO* ap, float32_t* dst, size_t len );
size_t  audio_read_interleaved_float64  ( AUDIO* ap, float64_t* dst, size_t len );

size_t  audio_write_interleaved_int16   ( AUDIO* ap, const int16_t*   dst, size_t len );
size_t  audio_write_interleaved_int32   ( AUDIO* ap, const int32_t*   dst, size_t len );
size_t  audio_write_interleaved_float32 ( AUDIO* ap, const float32_t* dst, size_t len );
size_t  audio_write_interleaved_float64 ( AUDIO* ap, const float64_t* dst, size_t len );


int     audio_flush               ( AUDIO* ap );
off_t   audio_seek                ( AUDIO* ap, int whence, signed long long offset ); // in samples statt in bytes
off_t   audio_tell                ( AUDIO* ap );                // in samples statt in bytes
off_t   audio_filelength          ( AUDIO* ap );                // in samples statt in bytes
int     audio_close               ( AUDIO* ap );
int     audio_eof                 ( AUDIO* ap );
int     audio_error               ( AUDIO* ap );
int     audio_channels            ( AUDIO* ap );
long double
        audio_samplefreq          ( AUDIO* ap );
int     audio_ioctl               ( AUDIO* ap, AUDIO_ioctl* format );
