~hecanjog/pippi

7aaec34cb452b52ef4702c80bdbe379472df73bc — Erik Schoster 11 days ago 8425c1e
First pass astrid shared mem sampler
2 files changed, 347 insertions(+), 35 deletions(-)

M libpippi/src/astrid.c
M libpippi/src/astrid.h
M libpippi/src/astrid.c => libpippi/src/astrid.c +314 -33
@@ 8,18 8,254 @@
#include "pippi.h"
#include "astrid.h"

int lpsampler_get_length(lpsampler_t * sampler, size_t * length) {
    struct flock fl;
    fl.l_type = F_RDLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = sampler->length_offset;
    fl.l_len = sizeof(size_t);

    if(fcntl(sampler->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a read lock on sampler length.\n");
        return -1;
    } else {
        memcpy(length, sampler->buf+sampler->length_offset, sizeof(size_t));

        fl.l_type = F_UNLCK;
        if(fcntl(sampler->fd, F_SETLK, &fl) == -1) {
            fprintf(stderr, "Could not unlock sampler length read lock.\n");
            return -1;
        }
    }

    return 0;
}

int lpsampler_get_samplerate(lpsampler_t * sampler, int * samplerate) {
    struct flock fl;
    fl.l_type = F_RDLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = sampler->samplerate_offset;
    fl.l_len = sizeof(int);

    if(fcntl(sampler->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a read lock on sampler samplerate.\n");
        return -1;
    } else {
        memcpy(samplerate, sampler->buf+sampler->samplerate_offset, sizeof(int));

        fl.l_type = F_UNLCK;
        if(fcntl(sampler->fd, F_SETLK, &fl) == -1) {
            fprintf(stderr, "Could not unlock sampler samplerate read lock.\n");
            return -1;
        }
    }

    return 0;
}

int lpsampler_get_channels(lpsampler_t * sampler, int * channels) {
    struct flock fl;
    fl.l_type = F_RDLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = sampler->channels_offset;
    fl.l_len = sizeof(int);

    if(fcntl(sampler->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a read lock on sampler channels.\n");
        return -1;
    } else {
        memcpy(channels, sampler->buf+sampler->channels_offset, sizeof(int));

        fl.l_type = F_UNLCK;
        if(fcntl(sampler->fd, F_SETLK, &fl) == -1) {
            fprintf(stderr, "Could not unlock sampler channels read lock.\n");
            return -1;
        }
    }

    return 0;
}

lpsampler_t * lpsampler_create_from(int bankid, lpbuffer_t * buf) {
    lpsampler_t * sampler;

    sampler = (lpsampler_t *)calloc(sizeof(lpsampler_t), 1);
    sampler->name = calloc(SAMPLER_NAME_SIZE, sizeof(char));
    snprintf(sampler->name, SAMPLER_NAME_SIZE, SAMPLER_NAME_TEMPLATE, bankid);
    sampler->fd = shm_open(sampler->name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    if(sampler->fd == -1) {
        fprintf(stderr, "Could not get a handle to sampler shared memory.\n");
        return NULL;
    }

    /* FIXME get samplerate & channels from context */
    sampler->length = buf->length;
    sampler->samplerate = buf->samplerate;
    sampler->channels = buf->channels;

    sampler->length_offset = 0;
    sampler->samplerate_offset = sampler->length_offset + sizeof(size_t);
    sampler->channels_offset = sampler->samplerate_offset + sizeof(int);
    sampler->buffer_offset = sampler->channels_offset + sizeof(int);
    sampler->total_bytes = sampler->buffer_offset + (sizeof(lpfloat_t) * sampler->length * sampler->channels);

    if(ftruncate(sampler->fd, sampler->total_bytes) == -1) {
        fprintf(stderr, "Could not resize sampler.\n");
        return NULL;
    }

    sampler->buf = mmap(NULL, sampler->total_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, sampler->fd, 0);
    if(sampler->buf == MAP_FAILED) {
        fprintf(stderr, "Could not mmap sampler.\n");
        return NULL;
    }

    memcpy(sampler->buf+sampler->length_offset, &sampler->length, sizeof(size_t));
    memcpy(sampler->buf+sampler->samplerate_offset, &sampler->samplerate, sizeof(int));
    memcpy(sampler->buf+sampler->channels_offset, &sampler->channels, sizeof(int));
    memcpy(sampler->buf+sampler->buffer_offset, &buf->data, sizeof(lpfloat_t) * sampler->length);

    return sampler;
}

lpsampler_t * lpsampler_open(int bankid) {
    lpsampler_t * sampler;
    struct stat buffdstat;

    sampler = (lpsampler_t *)calloc(sizeof(lpsampler_t), 1);
    sampler->name = calloc(SAMPLER_NAME_SIZE, sizeof(char));
    snprintf(sampler->name, SAMPLER_NAME_SIZE, SAMPLER_NAME_TEMPLATE, bankid);
    sampler->fd = shm_open(sampler->name, O_RDONLY, 0);
    if(sampler->fd == -1) {
        fprintf(stderr, "lpadc_open: Could not open a handle to sampler shared memory.\n");
        return NULL;
    }

    /* fstat check size */
    if(fstat(sampler->fd, &buffdstat) == -1) {
        fprintf(stderr, "lpadc_open: Could not fstat sampler shared memory.\n");
        return NULL;
    }

    sampler->total_bytes = buffdstat.st_size;

    sampler->length_offset = 0;
    sampler->samplerate_offset = sampler->length_offset + sizeof(size_t);
    sampler->channels_offset = sampler->samplerate_offset + sizeof(int);
    sampler->buffer_offset = sampler->channels_offset + sizeof(int);

    sampler->buf = mmap(NULL, sampler->total_bytes, PROT_READ, MAP_SHARED, sampler->fd, 0);
    if(sampler->buf == MAP_FAILED) {
        fprintf(stderr, "lpadc_open: Could not mmap sampler.\n");
        return NULL;
    }

    if(lpsampler_get_length(sampler, &sampler->length) == -1) {
        fprintf(stderr, "Could not read sampler length from shm\n");
        return NULL;
    }

    if(lpsampler_get_samplerate(sampler, &sampler->samplerate) == -1) {
        fprintf(stderr, "Could not read sampler samplerate from shm\n");
        return NULL;
    }

    if(lpsampler_get_channels(sampler, &sampler->channels) == -1) {
        fprintf(stderr, "Could not read sampler channels from shm\n");
        return NULL;
    }

    return sampler;
}

lpsampler_t * lpsampler_dub(int bankid, lpbuffer_t * buf) {
    lpsampler_t * sampler;
    lpbuffer_t * tmpbuf;
    struct stat buffdstat;

    sampler = (lpsampler_t *)calloc(sizeof(lpsampler_t), 1);
    sampler->name = calloc(SAMPLER_NAME_SIZE, sizeof(char));
    snprintf(sampler->name, SAMPLER_NAME_SIZE, SAMPLER_NAME_TEMPLATE, bankid);
    sampler->fd = shm_open(sampler->name, O_RDWR, 0);
    if(sampler->fd == -1) {
        fprintf(stderr, "lpadc_open: Could not open a handle to sampler shared memory.\n");
        return NULL;
    }

    /* fstat check size */
    if(fstat(sampler->fd, &buffdstat) == -1) {
        fprintf(stderr, "lpadc_open: Could not fstat sampler shared memory.\n");
        return NULL;
    }

    sampler->total_bytes = buffdstat.st_size;

    sampler->length_offset = 0;
    sampler->samplerate_offset = sampler->length_offset + sizeof(size_t);
    sampler->channels_offset = sampler->samplerate_offset + sizeof(int);
    sampler->buffer_offset = sampler->channels_offset + sizeof(int);

    sampler->buf = mmap(NULL, sampler->total_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, sampler->fd, 0);
    if(sampler->buf == MAP_FAILED) {
        fprintf(stderr, "lpadc_open: Could not mmap sampler.\n");
        return NULL;
    }

    if(lpsampler_get_length(sampler, &sampler->length) == -1) {
        fprintf(stderr, "Could not read sampler length from shm\n");
        return NULL;
    }

    if(lpsampler_get_samplerate(sampler, &sampler->samplerate) == -1) {
        fprintf(stderr, "Could not read sampler samplerate from shm\n");
        return NULL;
    }

    if(lpsampler_get_channels(sampler, &sampler->channels) == -1) {
        fprintf(stderr, "Could not read sampler channels from shm\n");
        return NULL;
    }

    tmpbuf = LPBuffer.create(buf->length, buf->channels, buf->samplerate);
    LPBuffer.copy(buf, tmpbuf);
    memcpy(tmpbuf->data, sampler->buf+sampler->buffer_offset, sizeof(lpfloat_t) * sampler->length);
    LPBuffer.dub(tmpbuf, buf, 0);
    memcpy(sampler->buf+sampler->buffer_offset, tmpbuf->data, sizeof(lpfloat_t) * sampler->length);
    LPBuffer.destroy(tmpbuf);
    return sampler;
}

int lpsampler_close(lpsampler_t * sampler) {
    if(close(sampler->fd) == -1) {
        fprintf(stderr, "Could not close sampler fd.\n");
        return -1;
    }
    return 0;
}

int lpsampler_destroy(lpsampler_t * sampler) {
    if(shm_unlink(sampler->name) == -1) {
        fprintf(stderr, "Could not unlink sampler fd.\n");
        return -1;
    }
    free(sampler->name);
    free(sampler);
    return 0;
}

int lpadc_get_pos(lpadcbuf_t * adcbuf, size_t * pos) {
    struct flock fl;
    fl.l_type = F_RDLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_start = adcbuf->pos_offset;
    fl.l_len = sizeof(size_t);

    if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a lock on adcbuf pos lock.\n");
        return -1;
    } else {
        memcpy(pos, adcbuf->buf, sizeof(size_t));
        memcpy(pos, adcbuf->buf+adcbuf->pos_offset, sizeof(size_t));

        fl.l_type = F_UNLCK;
        if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {


@@ 35,14 271,14 @@ int lpadc_set_pos(lpadcbuf_t * adcbuf, size_t pos) {
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_start = adcbuf->pos_offset;
    fl.l_len = sizeof(size_t);

    if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a read lock on adcbuf pos.\n");
        return -1;
    } else {
        memcpy(adcbuf->buf, &pos, sizeof(size_t));
        memcpy(adcbuf->buf+adcbuf->pos_offset, &pos, sizeof(size_t));

        fl.l_type = F_UNLCK;
        if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {


@@ 58,18 294,18 @@ int lpadc_get_length(lpadcbuf_t * adcbuf, size_t * length) {
    struct flock fl;
    fl.l_type = F_RDLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = sizeof(size_t);
    fl.l_start = adcbuf->length_offset;
    fl.l_len = sizeof(size_t);

    if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a lock on adcbuf length lock.\n");
        fprintf(stderr, "Could not aquire a read lock on adcbuf length.\n");
        return -1;
    } else {
        memcpy(length, adcbuf->buf + sizeof(size_t), sizeof(size_t));
        memcpy(length, adcbuf->buf+adcbuf->length_offset, sizeof(size_t));

        fl.l_type = F_UNLCK;
        if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
            fprintf(stderr, "Could not unlock adcbuf length lock.\n");
            fprintf(stderr, "Could not unlock adcbuf length read lock.\n");
            return -1;
        }
    }


@@ 81,18 317,18 @@ int lpadc_set_length(lpadcbuf_t * adcbuf, size_t length) {
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = sizeof(size_t);
    fl.l_start = adcbuf->length_offset;
    fl.l_len = sizeof(size_t);

    if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a read lock on adcbuf length.\n");
        fprintf(stderr, "Could not aquire a write lock on adcbuf length.\n");
        return -1;
    } else {
        memcpy(adcbuf->buf + sizeof(size_t), &length, sizeof(size_t));
        memcpy(adcbuf->buf+adcbuf->length_offset, &length, sizeof(size_t));

        fl.l_type = F_UNLCK;
        if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
            fprintf(stderr, "Could not unlock read lock adcbuf length.\n");
            fprintf(stderr, "Could not unlock write lock adcbuf length.\n");
            return -1;
        }
    }


@@ 100,17 336,54 @@ int lpadc_set_length(lpadcbuf_t * adcbuf, size_t length) {
    return 0;
}

void lpadc_get_channels(lpadcbuf_t * adcbuf, int * channels) {
    memcpy(channels, adcbuf->buf + (sizeof(size_t)*2), sizeof(int));
int lpadc_get_channels(lpadcbuf_t * adcbuf, int * channels) {
    struct flock fl;
    fl.l_type = F_RDLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = adcbuf->channels_offset;
    fl.l_len = sizeof(size_t);

    if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a read lock on adcbuf channels.\n");
        return -1;
    } else {
        memcpy(channels, adcbuf->buf+adcbuf->channels_offset, sizeof(int));

        fl.l_type = F_UNLCK;
        if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
            fprintf(stderr, "Could not unlock adcbuf channel read lock.\n");
            return -1;
        }
    }

    return 0;
}

void lpadc_set_channels(lpadcbuf_t * adcbuf, int channels) {
    memcpy(adcbuf->buf + (sizeof(size_t)*2), &channels, sizeof(int));
int lpadc_set_channels(lpadcbuf_t * adcbuf, int channels) {
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = adcbuf->channels_offset;
    fl.l_len = sizeof(size_t);

    if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
        fprintf(stderr, "Could not aquire a write lock on adcbuf channels.\n");
        return -1;
    } else {
        memcpy(adcbuf->buf+adcbuf->channels_offset, &channels, sizeof(int));

        fl.l_type = F_UNLCK;
        if(fcntl(adcbuf->fd, F_SETLK, &fl) == -1) {
            fprintf(stderr, "Could not unlock write lock adcbuf channels.\n");
            return -1;
        }
    }

    return 0;
}

lpadcbuf_t * lpadc_create() {
    lpadcbuf_t * adcbuf;
    size_t bufoffset = 0;

    adcbuf = (lpadcbuf_t *)calloc(sizeof(lpadcbuf_t), 1);
    adcbuf->fd = shm_open(LPADC_BUFNAME, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);


@@ 122,28 395,30 @@ lpadcbuf_t * lpadc_create() {
    /* FIXME get samplerate & channels from context */
    adcbuf->length = (size_t)(ASTRID_ADCSECONDS * ASTRID_SAMPLERATE);
    adcbuf->channels = ASTRID_CHANNELS;
    adcbuf->headsize = sizeof(size_t) + sizeof(size_t) + sizeof(int);
    adcbuf->fullsize = adcbuf->headsize + (sizeof(lpfloat_t) * adcbuf->length * adcbuf->channels);
    adcbuf->buffer_offset = sizeof(size_t) + sizeof(size_t) + sizeof(int);
    adcbuf->pos = 0;

    if(ftruncate(adcbuf->fd, adcbuf->fullsize) == -1) {
    /* Store byte offsets for easy lookup */
    adcbuf->pos_offset = 0;
    adcbuf->length_offset = adcbuf->pos_offset + sizeof(size_t);
    adcbuf->channels_offset = adcbuf->length_offset + sizeof(size_t);
    adcbuf->buffer_offset = adcbuf->channels_offset + sizeof(int);
    adcbuf->total_bytes = adcbuf->buffer_offset + (sizeof(lpfloat_t) * adcbuf->length * adcbuf->channels);

    if(ftruncate(adcbuf->fd, adcbuf->total_bytes) == -1) {
        fprintf(stderr, "Could not resize adcbuf.\n");
        return NULL;
    }

    adcbuf->buf = mmap(NULL, adcbuf->fullsize, PROT_READ | PROT_WRITE, MAP_SHARED, adcbuf->fd, 0);
    adcbuf->buf = mmap(NULL, adcbuf->total_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, adcbuf->fd, 0);
    if(adcbuf->buf == MAP_FAILED) {
        fprintf(stderr, "Could not mmap adcbuf.\n");
        return NULL;
    }

    memcpy(adcbuf->buf, &adcbuf->pos, sizeof(size_t));
    bufoffset += sizeof(size_t);

    memcpy(adcbuf->buf+bufoffset, &adcbuf->length, sizeof(size_t));
    bufoffset += sizeof(size_t);

    memcpy(adcbuf->buf+bufoffset, &adcbuf->channels, sizeof(int));
    memcpy(adcbuf->buf+adcbuf->pos_offset, &adcbuf->pos, sizeof(size_t));
    memcpy(adcbuf->buf+adcbuf->length_offset, &adcbuf->length, sizeof(size_t));
    memcpy(adcbuf->buf+adcbuf->channels_offset, &adcbuf->channels, sizeof(int));

    return adcbuf;
}


@@ 165,15 440,21 @@ lpadcbuf_t * lpadc_open() {
        return NULL;
    }

    adcbuf->fullsize = buffdstat.st_size;
    adcbuf->total_bytes = buffdstat.st_size;

    adcbuf->buf = mmap(NULL, adcbuf->fullsize, PROT_READ, MAP_SHARED, adcbuf->fd, 0);
    adcbuf->buf = mmap(NULL, adcbuf->total_bytes, PROT_READ, MAP_SHARED, adcbuf->fd, 0);
    if(adcbuf->buf == MAP_FAILED) {
        fprintf(stderr, "lpadc_open: Could not mmap adcbuf.\n");
        return NULL;
    }

    adcbuf->headsize = sizeof(size_t) + sizeof(size_t) + sizeof(int);

    /* Store byte offsets for easy lookup */
    adcbuf->pos_offset = 0;
    adcbuf->length_offset = adcbuf->pos_offset + sizeof(size_t);
    adcbuf->channels_offset = adcbuf->length_offset + sizeof(size_t);
    adcbuf->buffer_offset = adcbuf->channels_offset + sizeof(int);

    lpadc_get_pos(adcbuf, &adcbuf->pos);
    lpadc_get_channels(adcbuf, &adcbuf->channels);
    lpadc_get_length(adcbuf, &adcbuf->length);


@@ 194,7 475,7 @@ lpfloat_t lpadc_read_sample(lpadcbuf_t * adcbuf, size_t frame, int channel) {
    frame = frame % length;

    // get offset to buf
    offset = adcbuf->headsize;
    offset = adcbuf->buffer_offset;
    offset += ((frame * channels + channel) * sizeof(lpfloat_t));

    // memcpy at offset to lpfloat_t


@@ 229,7 510,7 @@ size_t lpadc_write_sample(lpadcbuf_t * adcbuf, lpfloat_t sample, size_t frame, i

    frame = (frame + offset) % (*length);
    lpadc_get_channels(adcbuf, channels);
    writepos = adcbuf->headsize + (((frame * (*channels)) + channel) * sizeof(lpfloat_t));
    writepos = adcbuf->buffer_offset + (((frame * (*channels)) + channel) * sizeof(lpfloat_t));
    memcpy(adcbuf->buf + writepos, &sample, sizeof(lpfloat_t));

    free(length);

M libpippi/src/astrid.h => libpippi/src/astrid.h +33 -2
@@ 6,6 6,9 @@
#define ASTRID_SAMPLERATE 48000
#define ASTRID_ADCSECONDS 30

#define SAMPLER_NAME_SIZE 15
#define SAMPLER_NAME_TEMPLATE "/lpsampler%04d"

#define PLAY_MESSAGE "p"
#define STOP_MESSAGE "s"
#define SHUTDOWN_MESSAGE "k"


@@ 16,14 19,42 @@ char * serialize_buffer(lpbuffer_t * buf, char * instrument_name);
lpbuffer_t * deserialize_buffer(char * str, char ** name); 
void send_play_message(char * instrument_name);

typedef struct lpsampler_t {
    int fd;
    char * name;
    char * buf;
    size_t total_bytes;
    size_t length;
    int samplerate;
    int channels;

    size_t length_offset;
    size_t samplerate_offset;
    size_t channels_offset;
    size_t buffer_offset;
} lpsampler_t;

lpsampler_t * lpsampler_create_from(int bankid, lpbuffer_t * buf);
lpsampler_t * lpsampler_open(int bankid);
lpsampler_t * lpsampler_dub(int bankid, lpbuffer_t * buf);
int lpsampler_close(lpsampler_t *);
int lpsampler_destroy(lpsampler_t *);
int lpsampler_get_length(lpsampler_t * sampler, size_t * length);
int lpsampler_get_samplerate(lpsampler_t * sampler, int * samplerate);
int lpsampler_get_channels(lpsampler_t * sampler, int * channels);

typedef struct lpadcbuf_t {
    int fd;
    char * buf;
    size_t headsize;
    size_t fullsize;
    size_t total_bytes;
    size_t pos;
    size_t length;
    int channels;

    size_t pos_offset;
    size_t length_offset;
    size_t channels_offset;
    size_t buffer_offset;
} lpadcbuf_t;

lpadcbuf_t * lpadc_create();