GSIF(3)

NAME
gsif (gsif_*) - sound & song loading and conversion functions (part of GSI - general sound interface)

SYNTAX
#include <gsi/gsif.h> Link the program with -lgsif

DESCRIPTION
Functions to load, save and convert formats:

struct gsi_sound *gsif_load_sample (char *filename, int offset);
    This loads a sound file with header in the progam that makes this call (i.e. a client, or the GSI server itself which uses these functions too). The type of the sample is determined by looking at the first 4 bytes of the file (to determine a 'signature').

struct gsi_sound *gsif_load_raw_sample (char *filename, int offset, int length, int snd_samplerate, int snd_channels, int snd_type);
    This loads a raw sound file (one that doesn't have a header, just sound data) in the progam that makes this call (i.e. a client, or the GSI server itself which uses these functions too). The format of the files is specified by the arguments passed.

struct gsi_sound *gsif_get_sample_structure (char *filename, int offset);
    Returns a gsi_sound and gsi_blocks with all the information from the file without loading the actual sound fragments into any gsi_block. returns NULL for an unidentified file format.

struct gsi_sound *gsif_get_structure (char *file_name, int read_header, int data_offset, int data_len, int samplerate, int channels, int type);
    This function is called by gsif_load_sample, gsif_load_raw_sample, gsif_get_sample_structure. If read_header =0 then a raw sample is loaded using the given samplerate etc. If not, the program will load the sample info using info in the file, except for filenames *.raw which are interpreted as samplerate-channels-type raw sample.

int gsif_save_raw_sample (char *filename, int save_format, int rate, int channels, int type, char *data, int data_length /*, int offset*/);
    [ NOT YET IMPLEMENTED ]

int gsif_save_sample (struct gsi_sound *snd, int file_type /*, int offset*/);
    [ NOT YET IMPLEMENTED ]

Functions dealing with sound blocks (the building blocks of the gsi_sound structure):

int gsif_load_sound_in_block (struct gsi_sound *snd, struct gsi_block *blk, int samplerate, int channels, int type);
    Load sample data from all blocks, convert to one format (the best format, based on the highest type, highest bits, highest channels from all blocks) and store it in one block. If samplerate >=0 then this overrides the best samplerate and ditto for channels, type.

int  gsif_load_sound_data (struct gsi_sound *snd);
    load sample data of all blocks in the sound (calls gsif_load_block_data).

void gsif_load_block_data (int fd, struct gsi_sound *snd, int block);
    load sample data of the given block number using the give file descriptor.

struct gsi_block *gsif_convert_block (struct gsi_block *blk, int samplerate, int channels, int type);
    Convert a sample to the given type.

Functions to manipulate sound structures:

int  gsif_free_sound (struct gsi_sound *snd);
    Free sound snd, all its blocks and allocated data for samples. NB. if you want to preserve some data in the sound, just copy the relevant pointer and make the one in snd NULL.

int  gsif_free_block (struct gsi_sound *snd, int i);
    Frees block i and allocated data.

Low level sample structure manipulation:

void gsif_add_block (struct gsi_sound *snd, int samplerate, int channels, int type, int data_start, int data_length);
    Add a block at the end of the linked list and initialize. Sample data is not loaded.

void gsif_make_linked_block_list (struct gsi_sound *snd);
    From an array of blocks (block) => linked list of blocks (prev, next).

void gsif_make_block_list (struct gsi_sound *snd);
    From a linked list of blocks (prev, next) => array of blocks (block).

Functions for songs:

struct gsi_song *gsif_load_song (char *filename, int offset);
    Loads a song (which is currently a midi/hmp/mus).

int gsif_convert_song_to_tracks (struct gsi_song *sng);
    Splits a midi buffer into tracks.

Functions to manipulate song structures:
(as with samples: this is all done with malloc/free)

int gsif_free_song (struct gsi_song *sng);
    Free a song, all its blocks and allocated data for tracks. NB. if you want to preserve some data in the sound, just copy the relevant pointer and make the one in sng NULL before calling this function.

int gsif_free_track (struct gsi_song *sng, int i);
    Frees a track and allocated data. Does not reorganize the linked/linear lists.

Low level song structure manipulation:

void gsif_make_linked_track_list (struct gsi_sound *sng);
    From an array of tracks (track) => linked list of tracks (prev,next).

void gsif_make_track_list (struct gsi_sound *sng);
    From a linked list of tracks (prev,next) => array of tracks (track).

MISCELANEOUS FUNCTIONS:

int gsif_sizeof_sample (int format);
    Bytes used per sample: 0 = query for invalid/unknown format, GSI_8BIT returns 1, GSI_16BIT 2 etc.

int gsif_fill_buffer (unsigned char *buffer, int num_samples, int channels, int type, int value);
    Fills a buffer with a given 32 bit value (rounded down to whatever accuracy the buffer uses). That is, to fill a 8 bit unsigned buffer (type = GSI_8BIT) with 1 you do: gsif_fill_buffer(buf, n, ch, type, 1<<24); To fill a buffer with silence: gsif_fill_buffer(buf, n, ch, type, 0);

ARGUMENTS

DATA TYPES
The following data types from GSI are available: 1. Samples enum { GSI_FILE_RAW, GSI_FILE_AU, GSI_FILE_AIFF, GSI_FILE_VOC, GSI_FILE_WAV }; struct gsi_block {
    int samplerate;
    int channels;
    int type;
    unsigned char *data;
    unsigned long data_length;
    unsigned long data_offset;
    int block_type;
    struct gsi_block *next;
    struct gsi_block *prev;
}; data_offset is the offset (relative to the gsi_sound's offset) into the file where the data is. block_type is 0 for samples, 1 for silence. In case of silence:
    duration = (data_length/(channels * bytes))/rate struct gsi_sound {
    char *filename;
    long offset;
    int file_format;
    char *comment;
    int blocks;
    struct gsi_block **block;
    struct gsi_block *first;
    struct gsi_block *last;
}; offset is the offset into the file were the header is located. first,last give access to the blocks via a linked list. Note that gsif_free_sound expects filename and comment to be malloced and tries to free(3) them if they are not NULL so take care if you manipulate gsi_sound structures directly. 2. Songs enum { GSI_FILE_MIDI, GSI_FILE_HMP, GSI_FILE_MUS }; struct gsi_track {
    unsigned char *data;
    unsigned long length;
    unsigned long offset;
}; offset is the offset into the file were the track is located. struct gsi_song {
    char *filename;
    unsigned long offset;
    int file_format;
    char *comment;
    int tracks;
    struct gsi_track **track;
    unsigned char *data;
    int data_length;
    int midi_division; /* time base division */
    int midi_format; /* type of midi */
    struct gsi_track *first;
    struct gsi_track *last;
}; offset is the offset into the file were the header is located. track is the midi data in midi file format (all tracks) (not needed after splitting to tracks). first,last give alternative access to the tracks via a linked list. Note that gsif_free_song expects filename and comment to be malloced and tries to free(3) them if they are not NULL so take care if you manipulate gsi_song structures directly. 2.1 Song status From <gsi/gsif_midi.h>: struct gsi_track_status {
    unsigned char *data;
    unsigned long data_length;
    unsigned long index;
    unsigned int ticks;
    unsigned char running;
}; data_length is the length of the track (bytes). index is the current position in the data. ticks is the current midi tick count. running is the running status (compresses midi's). struct gsi_song_status {
    int midi_format;
    int ticks;
    int last_ticks;
    double time;
    int last_synth_ticks;
    double song_end_time;
    int midi_division;
    int midi_tempo;
    int reverb;
    int chorus;
    int percussion_chn;
    int tracks;
    struct gsi_track_status *track;
}; midi_format is copied from the song struct for convenience. ticks is the number of ticks of the last midi event processed. last_ticks is the number of ticks of the previous midi event. time is the time (in seconds) of the last event processed. last_synth_ticks is the number of synth-ticks of the last seq_wait call. song_end_time is the duration of the song (in seconds), -1 if not (yet) known. percussion_chn is a bitmask of the channels used for percussion. MIDI default = 0x200 = channel 10. track is the current state for each track. struct gsi_song_event {
    int ticks;
    int track;
    int event;
    unsigned char *data;
    int length;
}; data is the pointer into the track data. length is the length of the event in bytes.

SUPPORTED FILE FORMATS
The formats supported by the library for samples are .snd/.au 8 bit mu-law, 8 bit uncompressed and 16 bit MSB (mono and stereo), standard .aif[fc], .voc, .wav. Raw sounds ("*.raw") are assumed to be 8 kHz mono 8 bit. Song formats can currently be MIDI, HMP (e.g. descent) and MUS (e.g. doom).

EXAMPLE APPLICATION
This program loads a sample (any format supported by the gsif library), converts it to ???, and saves it. [ THIS EXAMPLE DOESN'T WORK YET ] /*__________________INCLUDES___________________*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h> #include <gsi/gsif.h>
#include <gsi/mytypes.h> /* only for True/False defs */ /*__________________VARIABLES___________________*/ /*__________________PROGRAM___________________*/ int main(int argc, char *argv[]) {
    if (argc == 1) {
        exit(1);
    }
    new_snd = gsif_load_sample(argv[1], 0);
//    gsif_convert_data(new_snd, 8000, 1, GSI_8BIT);
    gsif_convert_block (new_snd->block[0], &new_blk, 8000, 1, GSI_8BIT);
    gsif_save_sample(new_snd, GSI_FILE_AIFF, 0);
    return 0;
}

BUGS & UNIMPLEMENTED FEATURES
Saving & samplerate conversion not done yet.

SEE ALSO
gsi(3)

AUTHOR
Wouter Scholten email: whs@xs4all.nl
WWW page: http://www.xs4all.nl/~whs/