[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