ftp.nice.ch/pub/next/unix/communication/newam.0.1.s.tar.gz#/newam-0.1/src/snd2zsnd.c

This is snd2zsnd.c in view mode; [Download] [Up]

/*********************************************************************/
/*                                                                   */
/* Programmer:                                                       */
/*   Olaf Mueller <olaf@orest.escape.de>                             */
/*                                                                   */
/* Purpose:                                                          */
/*   Answering Machine                                               */
/*       converting NeXT sound to ZyXEL voice                        */
/*                                                                   */
/* History:                                                          */
/*   29-08-96   Initial Release           Olaf Mueller               */
/*                                                                   */
/* Notes:                                                            */
/*    I confess, i have no idea what I am programming here.          */
/*    The Zyxel algorithm is completeley unknown for me.             */
/*    This code is a result of reverse engineering of the old        */
/*    am.1.16 code.                                                  */
/*    Probably it is full of errors, but who cares. It works for me  */
/*          Olaf                                                     */
/*                                                                   */
/*********************************************************************/

#include "zyxel.h"


static unsigned char lin16_to_ad2 (short dataWord)
{
	int				M [] = { 0x3800 , 0x5600 } ;
	static	int		delta = 5 ;
	static	short	val = 0 ;
	char			signBit = 0 ;
	unsigned char	dataByte ;
	int				E ;


	E = (2 * (dataWord - val)) / delta ;
	val = dataWord ;
	if (E < 0)
	{
		signBit = 0x02 ;
		E = -E ;
	}
	if (E > 3)
		dataByte = 0x01 ;
	else
		dataByte = 0x00 ;

	delta = (M [dataByte] * delta + 0x2000) >> 14 ;
	if (delta < 5)
		delta = 5 ;

	return  signBit | dataByte ;
}


static unsigned char lin16_to_ad3 (short dataWord)
{
	int				M [] = { 0x399A , 0x3A9F , 0x4D14 , 0x6607 } ;
	static	int		delta = 5 ;
	static	short	val = 0 ;
	char			signBit = 0 ;
	unsigned char	dataByte ;
	int				E ;


	E = (2 * (dataWord - val)) / delta ;
	if (E < 0)
	{
		signBit = 0x04 ;
		E = -E ;
	}
	if (E > 6)
		dataByte = 0x03 ;
	else if (E > 4)
		dataByte = 0x02 ;
	else if (E > 2)
		dataByte = 0x01 ;
	else
		dataByte = 0x00 ;

	if ((delta & 1)  &&  !signBit)
		++val ;

	if (!signBit)
		val += dataByte * delta + delta >> 1 ;
	else
		val -= dataByte * delta + delta >> 1 ;

	delta = (M [dataByte] * delta + 0x2000) >> 14 ;
	if (delta < 5)
		delta = 5 ;

	return  signBit | dataByte ;
}



#include <libc.h>
#import <sound/sound.h>


static void snd_to_ad2 (SNDSoundStruct *snd,FILE *fpzsnd)
{
	short			sndsample ;
	short			*sounddata ;
	long			soundcount ;
	int				icnt = 4 ;
	unsigned char	zbyte = 0 ;


	sounddata = (short*) ((char*)snd + snd->dataLocation) ;
	soundcount = snd->dataSize / 2 ;

	while (soundcount--)
	{
		sndsample = NXSwapBigShortToHost (*sounddata++) ;
		switch (icnt)
		{
		case 4:
			zbyte = lin16_to_ad2 (sndsample) << 6 ;
			break ;
		case 3:
			zbyte |= lin16_to_ad2 (sndsample) << 4 ;
			break ;
		case 2:
			zbyte |= lin16_to_ad2 (sndsample) << 2 ;
			break ;
		case 1:
			zbyte |= lin16_to_ad2 (sndsample) ;
			fwrite (&zbyte,sizeof(unsigned char),1,fpzsnd) ;
			break ;
		}
		if (--icnt == 0)
			icnt = 4 ;
	}
}


static void snd_to_ad3 (SNDSoundStruct *snd,FILE *fpzsnd)
{
	short			sndsample ;
	short			*sounddata ;
	long			soundcount ;
	int				icnt = 8 , restbyte = 0 ;
	unsigned char	zbyte = 0 ;


	sounddata = (short*) ((char*)snd + snd->dataLocation) ;
	soundcount = snd->dataSize / 2 ;

	while (soundcount--)
	{
		sndsample = NXSwapBigShortToHost (*sounddata++) ;
		switch (icnt)
		{
		case 8:
			zbyte = lin16_to_ad3 (sndsample) << 5 ;
			break ;
		case 7:
			zbyte |= lin16_to_ad3 (sndsample) << 2 ;
			break ;
		case 6:
			restbyte = lin16_to_ad3 (sndsample) ;
			zbyte |= restbyte >> 1 ;
			fwrite (&zbyte,sizeof(unsigned char),1,fpzsnd) ;
			zbyte = restbyte << 7 ;
			break ;
		case 5:
			zbyte |= lin16_to_ad3 (sndsample) << 4 ;
			break ;
		case 4:
			zbyte |= lin16_to_ad3 (sndsample) << 1 ;
			break ;
		case 3:
			restbyte = lin16_to_ad3 (sndsample) ;
			zbyte |= restbyte >> 2 ;
			fwrite (&zbyte,sizeof(unsigned char),1,fpzsnd) ;
			zbyte = restbyte << 6 ;
			break ;
		case 2:
			zbyte |= lin16_to_ad3 (sndsample) << 3 ;
			break ;
		case 1:
			zbyte |= lin16_to_ad3 (sndsample) ;
			fwrite (&zbyte,sizeof(unsigned char),1,fpzsnd) ;
			break ;
		}
		if (--icnt == 0)
			icnt = 8 ;
	}
}


static void PrintUsage (void)
{
    printf ("usage: snd2zsnd [-h] [-f <Zyxel_format>] <NeXT_sound_file> <Zyxel_voice_file>\n") ;
    printf ("       Zyxel_format:  2 = ADPCM3 (default)\n") ;
    printf ("                      1 = ADPCM2\n") ;
}


int main (int argc,char *argv[])
{
	int				opt , optFormat = ZYX_AD3 ;
	SNDSoundStruct	*sndp , *sndpc , snd ;
	int				err ;
	ZyxelHeader		zyxhead = { 0 } ;
	FILE			*fpzsnd ;


	/*****
	 *****  we scan options and parameters
	 *****/
	while ((opt = getopt(argc,argv,"hf:")) != -1)
	{
		switch (opt)
		{
		case 'f':
			optFormat = atoi (optarg) ;
			if (optFormat != ZYX_AD3  &&  optFormat != ZYX_AD2)
			{
				PrintUsage () ;
				return  1 ;
			}
			break ;
		case 'h':
			PrintUsage () ;
			return  2 ;
		case '?' :
			return  1 ;
		}
	}
	if (argc - optind != 2)
	{
		PrintUsage () ;
		return  2 ;        
	}

	if ((err = SNDReadSoundfile(argv[optind],&sndp)) != SND_ERR_NONE)
	{
		printf ("Error reading sound file: %s\n",SNDSoundError(err)) ;
		return  1 ;
    }

    snd.magic = SND_MAGIC;
    snd.dataFormat = SND_FORMAT_LINEAR_16 ;
    snd.samplingRate = 9600 ;
    snd.channelCount = 1 ;
    sndpc = &snd ;

    if ((err = SNDConvertSound(sndp,&sndpc)) != SND_ERR_NONE)
	{
		printf ("Error converting sound file: %s\n",SNDSoundError(err)) ;
		return  1 ;
    }
	SNDFree (sndp) ;

    memcpy (zyxhead.title,ZYX_TITLE,strlen(ZYX_TITLE)) ;
    zyxhead.mode = ZYX_VOC ;
    zyxhead.voice = optFormat ;

	fpzsnd = fopen (argv[optind+1],"w") ;
	fwrite (&zyxhead,sizeof(ZyxelHeader),1,fpzsnd) ;
	switch (optFormat)
	{
	case ZYX_AD3:
		snd_to_ad3 (sndpc,fpzsnd) ;
		break ;
	case ZYX_AD2:
		snd_to_ad2 (sndpc,fpzsnd) ;
		break ;
	}
	fclose (fpzsnd) ;
	return  0 ;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.