view src/shnplug/fixio.c @ 2284:d19b53359b24

cleaned up the sndfile wav plugin, currently limiting it ONLY TO WAV PLAYBACK. if somebody is more experienced with it and wants to restore the other formats, go ahead (maybe change the name of the plugin too?).
author mf0102 <0102@gmx.at>
date Wed, 09 Jan 2008 15:41:22 +0100
parents 51bf0e431e02
children
line wrap: on
line source

/******************************************************************************
*                                                                             *
*  Copyright (C) 1992-1995 Tony Robinson                                      *
*                                                                             *
*  See the file doc/LICENSE.shorten for conditions on distribution and usage  *
*                                                                             *
******************************************************************************/

/*
 * $Id: fixio.c,v 1.7 2003/08/26 05:34:04 jason Exp $
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "shorten.h"
#include "bitshift.h"

void swab(const void *from, void *to, ssize_t n);

#define CAPMAXSCHAR(x)  ((x > 127) ? 127 : x)
#define CAPMAXUCHAR(x)  ((x > 255) ? 255 : x)
#define CAPMAXSHORT(x)  ((x > 32767) ? 32767 : x)
#define CAPMAXUSHORT(x) ((x > 65535) ? 65535 : x)

static int sizeof_sample[TYPE_EOF];

void init_sizeof_sample() {
  sizeof_sample[TYPE_AU1]   = sizeof(uchar);
  sizeof_sample[TYPE_S8]    = sizeof(schar);
  sizeof_sample[TYPE_U8]    = sizeof(uchar);
  sizeof_sample[TYPE_S16HL] = sizeof(ushort);
  sizeof_sample[TYPE_U16HL] = sizeof(ushort);
  sizeof_sample[TYPE_S16LH] = sizeof(ushort);
  sizeof_sample[TYPE_U16LH] = sizeof(ushort);
  sizeof_sample[TYPE_ULAW]  = sizeof(uchar);
  sizeof_sample[TYPE_AU2]   = sizeof(uchar);
  sizeof_sample[TYPE_AU3]   = sizeof(uchar);
  sizeof_sample[TYPE_ALAW]  = sizeof(uchar);
}

/***************/
/* fixed write */
/***************/

void fwrite_type_init(shn_file *this_shn) {
  init_sizeof_sample();
  this_shn->decode_state->writebuf  = (schar*) NULL;
  this_shn->decode_state->writefub  = (schar*) NULL;
  this_shn->decode_state->nwritebuf = 0;
}

void fwrite_type_quit(shn_file *this_shn) {
  if(this_shn->decode_state->writebuf != NULL) {
    free(this_shn->decode_state->writebuf);
    this_shn->decode_state->writebuf = NULL;
  }
  if(this_shn->decode_state->writefub != NULL) {
    free(this_shn->decode_state->writefub);
    this_shn->decode_state->writefub = NULL;
  }
}

/* convert from signed ints to a given type and write */
void fwrite_type(slong **data,int ftype,int nchan,int nitem,shn_file *this_shn)
{
  int hiloint = 1, hilo = !(*((char*) &hiloint));
  int i, nwrite = 0, datasize = sizeof_sample[ftype], chan;
  slong *data0 = data[0];
  int bufAvailable = OUT_BUFFER_SIZE - this_shn->vars.bytes_in_buf;

  if(this_shn->decode_state->nwritebuf < nchan * nitem * datasize) {
    this_shn->decode_state->nwritebuf = nchan * nitem * datasize;
    if(this_shn->decode_state->writebuf != NULL) free(this_shn->decode_state->writebuf);
    if(this_shn->decode_state->writefub != NULL) free(this_shn->decode_state->writefub);
    this_shn->decode_state->writebuf = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn);
    if (!this_shn->decode_state->writebuf)
      return;
    this_shn->decode_state->writefub = (schar*) pmalloc((ulong) this_shn->decode_state->nwritebuf,this_shn);
    if (!this_shn->decode_state->writefub)
      return;
  }

  switch(ftype) {
  case TYPE_AU1: /* leave the conversion to fix_bitshift() */
  case TYPE_AU2: {
    uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	*writebufp++ = data0[i];
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  *writebufp++ = data[chan][i];
    break;
  }
  case TYPE_U8: {
    uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	*writebufp++ = CAPMAXUCHAR(data0[i]);
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  *writebufp++ =  CAPMAXUCHAR(data[chan][i]);
    break;
  }
  case TYPE_S8: {
    schar *writebufp = (schar*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	*writebufp++ = CAPMAXSCHAR(data0[i]);
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  *writebufp++ = CAPMAXSCHAR(data[chan][i]);
    break;
  }
  case TYPE_S16HL:
  case TYPE_S16LH: {
    short *writebufp = (short*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	*writebufp++ = CAPMAXSHORT(data0[i]);
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  *writebufp++ = CAPMAXSHORT(data[chan][i]);
    break;
  }
  case TYPE_U16HL:
  case TYPE_U16LH: {
    ushort *writebufp = (ushort*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	*writebufp++ = CAPMAXUSHORT(data0[i]);
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  *writebufp++ = CAPMAXUSHORT(data[chan][i]);
    break;
  }
  case TYPE_ULAW: {
    uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	*writebufp++ = Slinear2ulaw(CAPMAXSHORT((data0[i] << 3)));
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  *writebufp++ = Slinear2ulaw(CAPMAXSHORT((data[chan][i] << 3)));
    break;
  }
  case TYPE_AU3: {
    uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	if(data0[i] < 0)
	  *writebufp++ = (127 - data0[i]) ^ 0xd5;
	else
	  *writebufp++ = (data0[i] + 128) ^ 0x55;
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  if(data[chan][i] < 0)
	    *writebufp++ = (127 - data[chan][i]) ^ 0xd5;
	  else
	    *writebufp++ = (data[chan][i] + 128) ^ 0x55;
    break;
  }
  case TYPE_ALAW: {
    uchar *writebufp = (uchar*) this_shn->decode_state->writebuf;
    if(nchan == 1)
      for(i = 0; i < nitem; i++)
	*writebufp++ = Slinear2alaw(CAPMAXSHORT((data0[i] << 3)));
    else
      for(i = 0; i < nitem; i++)
	for(chan = 0; chan < nchan; chan++)
	  *writebufp++ = Slinear2alaw(CAPMAXSHORT((data[chan][i] << 3)));
    break;
  }
  }

  switch(ftype) {
  case TYPE_AU1:
  case TYPE_S8:
  case TYPE_U8:
  case TYPE_ULAW:
  case TYPE_AU2:
  case TYPE_AU3:
  case TYPE_ALAW:
    if (datasize*nchan*nitem <= bufAvailable) {
      memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem);
      this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
      nwrite = nitem;
    }
    else
      shn_debug("Buffer overrun in fwrite_type() [case 1]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
    break;
  case TYPE_S16HL:
  case TYPE_U16HL:
    if(hilo)
    {
      if (datasize*nchan*nitem <= bufAvailable) {
        memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem);
        this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
        nwrite = nitem;
      }
      else
        shn_debug("Buffer overrun in fwrite_type() [case 2]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
    }
    else
    {
      swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem);
      if (datasize*nchan*nitem <= bufAvailable) {
        memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem);
        this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
        nwrite = nitem;
      }
      else
        shn_debug("Buffer overrun in fwrite_type() [case 3]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
    }
    break;
  case TYPE_S16LH:
  case TYPE_U16LH:
    if(hilo)
    {
      swab(this_shn->decode_state->writebuf, this_shn->decode_state->writefub, datasize * nchan * nitem);
      if (datasize*nchan*nitem <= bufAvailable) {
        memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writefub,datasize*nchan*nitem);
        this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
        nwrite = nitem;
      }
      else
        shn_debug("Buffer overrun in fwrite_type() [case 4]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
    }
    else
    {
      if (datasize*nchan*nitem <= bufAvailable) {
        memcpy((void *)&this_shn->vars.buffer[this_shn->vars.bytes_in_buf],(const void *)this_shn->decode_state->writebuf,datasize*nchan*nitem);
        this_shn->vars.bytes_in_buf += datasize*nchan*nitem;
        nwrite = nitem;
      }
      else
        shn_debug("Buffer overrun in fwrite_type() [case 5]: %d bytes to read, but only %d bytes are available",datasize*nchan*nitem,bufAvailable);
    }
    break;
  }

  if(nwrite != nitem)
    shn_error_fatal(this_shn,"Failed to write decompressed stream -\npossible corrupt or truncated file");
}

/*************/
/* bitshifts */
/*************/

void fix_bitshift(buffer, nitem, bitshift, ftype) slong *buffer; int nitem,
       bitshift, ftype; {
  int i;

  if(ftype == TYPE_AU1)
    for(i = 0; i < nitem; i++)
      buffer[i] = ulaw_outward[bitshift][buffer[i] + 128];
  else if(ftype == TYPE_AU2)
    for(i = 0; i < nitem; i++) {
      if(buffer[i] >= 0)
	buffer[i] = ulaw_outward[bitshift][buffer[i] + 128];
      else if(buffer[i] == -1)
	buffer[i] =  NEGATIVE_ULAW_ZERO;
      else
	buffer[i] = ulaw_outward[bitshift][buffer[i] + 129];
    }
  else
    if(bitshift != 0)
      for(i = 0; i < nitem; i++)
	buffer[i] <<= bitshift;
}