示例#1
0
/* This is called whenever new data may be written to the stream */
static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
    pa_assert(s);
    pa_assert(length > 0);

    if (raw) {
        pa_assert(!sndfile);

        if (stdio_event)
            mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT);

        if (!buffer)
            return;

        do_stream_write(length);

    } else {
        sf_count_t bytes;
        void *data;

        pa_assert(sndfile);

        for (;;) {
            size_t data_length = length;

            if (pa_stream_begin_write(s, &data, &data_length) < 0) {
                pa_log(_("pa_stream_begin_write() failed: %s"), pa_strerror(pa_context_errno(context)));
                quit(1);
                return;
            }

            if (readf_function) {
                size_t k = pa_frame_size(&sample_spec);

                if ((bytes = readf_function(sndfile, data, (sf_count_t) (data_length/k))) > 0)
                    bytes *= (sf_count_t) k;

            } else
                bytes = sf_read_raw(sndfile, data, (sf_count_t) data_length);

            if (bytes > 0)
                pa_stream_write(s, data, (size_t) bytes, NULL, 0, PA_SEEK_RELATIVE);
            else
                pa_stream_cancel_write(s);

            /* EOF? */
            if (bytes < (sf_count_t) data_length) {
                start_drain();
                break;
            }

            /* Request fulfilled */
            if ((size_t) bytes >= length)
                break;

            length -= bytes;
        }
    }
}
示例#2
0
int pa_sound_file_load(
        pa_mempool *pool,
        const char *fname,
        pa_sample_spec *ss,
        pa_channel_map *map,
        pa_memchunk *chunk,
        pa_proplist *p) {

    SNDFILE *sf = NULL;
    SF_INFO sfi;
    int ret = -1;
    size_t l;
    sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL;
    void *ptr = NULL;
    int fd;

    pa_assert(fname);
    pa_assert(ss);
    pa_assert(chunk);

    pa_memchunk_reset(chunk);

    if ((fd = pa_open_cloexec(fname, O_RDONLY, 0)) < 0) {
        pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
        goto finish;
    }

#ifdef HAVE_POSIX_FADVISE
    if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) {
        pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno));
        goto finish;
    } else
        pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded.");
#endif

    pa_zero(sfi);
    if (!(sf = sf_open_fd(fd, SFM_READ, &sfi, 1))) {
        pa_log("Failed to open file %s", fname);
        goto finish;
    }

    fd = -1;

    if (pa_sndfile_read_sample_spec(sf, ss) < 0) {
        pa_log("Failed to determine file sample format.");
        goto finish;
    }

    if ((map && pa_sndfile_read_channel_map(sf, map) < 0)) {
        if (ss->channels > 2)
            pa_log("Failed to determine file channel map, synthesizing one.");
        pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
    }

    if (p)
        pa_sndfile_init_proplist(sf, p);

    if ((l = pa_frame_size(ss) * (size_t) sfi.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
        pa_log("File too large");
        goto finish;
    }

    chunk->memblock = pa_memblock_new(pool, l);
    chunk->index = 0;
    chunk->length = l;

    readf_function = pa_sndfile_readf_function(ss);

    ptr = pa_memblock_acquire(chunk->memblock);

    if ((readf_function && readf_function(sf, ptr, sfi.frames) != sfi.frames) ||
        (!readf_function && sf_read_raw(sf, ptr, (sf_count_t) l) != (sf_count_t) l)) {
        pa_log("Premature file end");
        goto finish;
    }

    ret = 0;

finish:

    if (sf)
        sf_close(sf);

    if (ptr)
        pa_memblock_release(chunk->memblock);

    if (ret != 0 && chunk->memblock)
        pa_memblock_unref(chunk->memblock);

    if (fd >= 0)
        pa_close(fd);

    return ret;
}
示例#3
0
文件: sound.c 项目: Keruspe/eventd
static void
_eventd_sound_read_file(const gchar *filename, void **data, gsize *length, gint *format, guint32 *rate, guint8 *channels)
{
    *data = NULL;
    *length = 0;
    *format = 0;
    *rate = 0;
    *channels = 0;

    if ( *filename == 0 )
        return;

    SNDFILE *f;
    SF_INFO sfi;
    if ( ( f = sf_open(filename, SFM_READ, &sfi) ) == NULL )
    {
        g_warning("Can't open sound file");
        return;
    }

    sndfile_readf_t readf_function;
    size_t factor;
    switch ( sfi.format & SF_FORMAT_SUBMASK )
    {
    case SF_FORMAT_PCM_16:
    case SF_FORMAT_PCM_U8:
    case SF_FORMAT_PCM_S8:
        readf_function = (sndfile_readf_t) sf_readf_short;
        factor = sizeof(short);
    break;
    case SF_FORMAT_PCM_24:
    case SF_FORMAT_PCM_32:
        readf_function = (sndfile_readf_t) sf_readf_int;
        factor = sizeof(int);
    break;
    case SF_FORMAT_FLOAT:
    case SF_FORMAT_DOUBLE:
        readf_function = (sndfile_readf_t) sf_readf_float;
        factor = sizeof(float);
    break;
    default:
        g_warning("Unsupported format");
        goto out;
    }

    *length = (size_t) sfi.frames * sfi.channels * factor;

    *data = g_malloc0(*length);

    if ( readf_function(f, *data, sfi.frames) < 0 )
    {
        g_warning("Error while reading sound file: %s", sf_strerror(f));
        g_free(*data);
        *data = NULL;
        *length = 0;
    }
    else
    {
        *format = sfi.format & SF_FORMAT_SUBMASK;
        *rate = (guint32) sfi.samplerate;
        *channels = (guint8) sfi.channels;
    }

out:
    sf_close(f);
}