[MPlayer-dev-eng] Export audio filter: a few patches
Gustavo Sverzut Barbieri
gsbarbieri at yahoo.com.br
Fri Nov 14 12:10:31 CET 2003
Thank you for improving the code!
When I wrote that, I only used in visualization, so if few things were
lost, I didn't care that much... as you mentioned.
Thank you,
Gustavo
--- ed at catmur.co.uk escreveu:
> I've been hacking on the export filter (trying to use it to import
> audio
> into XMMS), and have generated a few alterations.
>
> First off, the treatment of the sample count argument
> (export=/path/to/file:<SAMPLES>) is broken; the sscanf is out by one:
>
> - sscanf(str + i, "%d", &(s->sz));
> + sscanf(str + i + 1, "%d", &(s->sz));
>
> Also, in two places the default sample count is used where the user
> provided count is available:
>
> - s->buf[i] = s->buf[0] + i*DEF_SZ*af->data->bps;
> + s->buf[i] = s->buf[0] + i*s->sz*af->data->bps;
>
> When using the export as audio, it's more important that no data is
> lost
> (than using it in e.g. a visualisation). My solution is to export the
> data whenever the buffer is filled, but then continue to copy that
> audio
> chunk into the beginning of the buffer. This means changing the
> nesting
> of the loops that deinterleave the data.
>
> + int len = c->len/c->bps/c->nch; // Number of samples in
> data
> chunk
> ...
> + for(i = 0; i < len; i++){
> + for(ch = 0; ch < nch; ch++){
> + int16_t *b = s->buf[ch]; // Current channel's buffer
> + b[wi] = a[i * nch + ch]; // Write sample into buffer
> + }
> + wi++;
> + if(wi >= sz){ // If this buffer is full
> ...
> + // Export this buffer to mapped area (allocated as one block)
> + memcpy(s->mmap_area + SIZE_HEADER, s->buf[0], sz * c->bps *
> nch);
> + s->count++; // increment counter (to sync)
> + memcpy(s->mmap_area + SIZE_HEADER - sizeof(s->count),
> + &(s->count), sizeof(s->count));
> + wi = 0; // Start a new buffer
> }
>
>
> Also, to make sure that a client process has a chance to read in the
> data, I have put in a sleep of half the time the buffer holds,
> triggered
> if the play function exports more than once from the same input audio
> chunk. (I'm using nanosleep because the usleep man page said it was
> deprecated...) By checking the mmapped area every quarter loop, I can
> then guarantee to pick up when the buffer is updated, and no sound is
> lost.
> + struct timespec wait = { 0, 1000000000l/c->rate*len/2 }; // half a
> sample
> ...
> + if(!exported)
> + exported = 1;
> + else // we have already exported
> data: give
> + nanosleep(&wait, NULL); // client processes a chance
> to
> see it!
>
> Also, I have corrected a few spelling mistakes.
>
> I hope this all makes sense; thanks for reading this!
>
> Ed
> > ---
>
/var/tmp/portage/mplayer-1.0_pre2/work/MPlayer-1.0pre2/libaf/af_export.c
> 2003-09-21 13:16:16.000000000 +0100
> +++ af_export.c 2003-11-14 04:28:03.000000000 +0000
> @@ -12,6 +12,7 @@
> #include <string.h>
> #include <inttypes.h>
> #include <unistd.h>
> +#include <time.h>
> #include "../config.h"
>
> #ifdef HAVE_SYS_MMAN_H
> @@ -69,7 +70,7 @@
> if(s->fd)
> close(s->fd);
>
> - // Accept only int16_t as input fomat (which sucks)
> + // Accept only int16_t as input format (which sucks)
> af->data->rate = ((af_data_t*)arg)->rate;
> af->data->nch = ((af_data_t*)arg)->nch;
> af->data->format = AF_FORMAT_SI | AF_FORMAT_NE;
> @@ -79,12 +80,12 @@
> if(s->sz == 0)
> s->sz = DEF_SZ;
>
> - // Allocate new buffers (as one continous block)
> - s->buf[0] = calloc(DEF_SZ*af->data->nch, af->data->bps);
> + // Allocate new buffers (as one continuous block)
> + s->buf[0] = calloc(s->sz*af->data->nch, af->data->bps);
> if(NULL == s->buf[0])
> af_msg(AF_MSG_FATAL, "[export] Out of memory\n");
> for(i = 1; i < af->data->nch; i++)
> - s->buf[i] = s->buf[0] + i*DEF_SZ*af->data->bps;
> + s->buf[i] = s->buf[0] + i*s->sz*af->data->bps;
>
> // Init memory mapping
> s->fd = open(s->filename, O_RDWR | O_CREAT | O_TRUNC, 0640);
> @@ -139,7 +140,7 @@
> memcpy(s->filename, str, i);
> s->filename[i] = 0;
>
> - sscanf(str + i, "%d", &(s->sz));
> + sscanf(str + i + 1, "%d", &(s->sz));
>
> return af->control(af, AF_CONTROL_EXPORT_SZ | AF_CONTROL_SET,
> &s->sz);
> }
> @@ -163,7 +164,6 @@
> */
> static void uninit( struct af_instance_s* af )
> {
> - int i;
> if (af->data){
> free(af->data);
> af->data = NULL;
> @@ -197,38 +197,40 @@
> {
> af_data_t* c = data; // Current working data
> af_export_t* s = af->setup; // Setup for this instance
> - int16_t* a = c->audio; // Incomming sound
> + int16_t* a = c->audio; // Incoming sound
> int nch = c->nch; // Number of channels
> - int len = c->len/c->bps; // Number of sample in data chunk
> + int len = c->len/c->bps/c->nch; // Number of samples in data
> chunk
> int sz = s->sz; // buffer size (in samples)
> - int flag = 0; // Set to 1 if buffer is filled
>
> - int ch, i;
> -
> - // Fill all buffers
> - for(ch = 0; ch < nch; ch++){
> - int wi = s->wi; // Reset write index
> - int16_t* b = s->buf[ch]; // Current buffer
> -
> - // Copy data to export buffers
> - for(i = ch; i < len; i += nch){
> - b[wi++] = a[i];
> - if(wi >= sz){ // Don't write outside the end of the buffer
> - flag = 1;
> - break;
> - }
> + int wi = s->wi; // write index
> + int ch, i; // Channel index, sample index
> + int exported = 0; // exported anything yet
> + struct timespec wait = { 0, 1000000000l/c->rate*len/2 }; // half a
> sample
> + if (wait.tv_nsec < 0) wait.tv_nsec = 0;
> + if (wait.tv_nsec > 100000) wait.tv_nsec = 100000;
> +
> + // Sort data into the right order in the buffer
> + // (input is interleaved; export is non-interleaved)
> + for(i = 0; i < len; i++){
> + for(ch = 0; ch < nch; ch++){
> + int16_t *b = s->buf[ch]; // Current channel's buffer
> + b[wi] = a[i * nch + ch]; // Write sample into buffer
> + }
> + wi++;
> + if(wi >= sz){ // If this buffer is full
> + if(!exported)
> + exported = 1;
> + else // we have already exported data: give
> + nanosleep(&wait, NULL); // client processes a chance to see
> it!
> + // Export this buffer to mapped area (allocated as one block)
> + memcpy(s->mmap_area + SIZE_HEADER, s->buf[0], sz * c->bps *
> nch);
> + s->count++; // increment counter (to sync)
> + memcpy(s->mmap_area + SIZE_HEADER - sizeof(s->count),
> + &(s->count), sizeof(s->count));
> + wi = 0; // Start a new buffer
> }
> - s->wi = wi % s->sz;
> - }
> -
> - // Export buffer to mmaped area
> - if(flag){
> - // update buffer in mapped area
> - memcpy(s->mmap_area + SIZE_HEADER, s->buf[0], sz * c->bps *
> nch);
> - s->count++; // increment counter (to sync)
> - memcpy(s->mmap_area + SIZE_HEADER - sizeof(s->count),
> - &(s->count), sizeof(s->count));
> }
> + s->wi = wi; // Store write index
>
> // We don't modify data, just export it
> return data;
> > _______________________________________________
> MPlayer-dev-eng mailing list
> MPlayer-dev-eng at mplayerhq.hu
> http://mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
>
______________________________________________________________________
Yahoo! Mail: 6MB, anti-spam e antivírus gratuito! Crie sua conta agora:
http://mail.yahoo.com.br
More information about the MPlayer-dev-eng
mailing list