This is zsndplay.c in view mode; [Download] [Up]
/*********************************************************************/ /* */ /* Programmer: */ /* Olaf Mueller <olaf@orest.escape.de> */ /* */ /* Purpose: */ /* Answering Machine */ /* playing ZyXEL voice on NeXT sound system */ /* */ /* 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 short ad2_to_lin16 (unsigned char dataByte) { int M [] = { 0x3800 , 0x5600 } ; static int delta = 5 ; static int val = 0 ; char signBit = dataByte & 0x02 ; dataByte &= 0x01 ; if (!signBit) val += dataByte * delta + delta >> 1 ; else val -= dataByte * delta + delta >> 1 ; if (val < -0x7ffe) val = -0x7ffe ; else if (val > 0x7ffe) val = 0x7ffe ; delta = (M [dataByte] * delta + 0x2000) >> 14 ; if (delta < 5) delta = 5 ; return (short) val ; } static short ad3_to_lin16 (unsigned char dataByte) { int M [] = { 0x399A , 0x3A9F , 0x4D14 , 0x6607 } ; static int delta = 5 ; static int val = 0 ; char signBit = dataByte & 0x04 ; dataByte &= 0x03 ; /******* This part is modified for the Firmware > 6.10 **************/ val = (val * 3973 + 2048) / 4096 ; /********************************************************************/ if ((delta & 1) && !signBit) ++val ; if (!signBit) val += dataByte * delta + delta >> 1 ; else val -= dataByte * delta + delta >> 1 ; #if 0 if (val <= -0x7ffe || val >= 0x7ffe) val = 0; #endif if (val < -0x7ffe) val = -0x7ffe ; else if (val > 0x7ffe) val = 0x7ffe ; delta = (M [dataByte] * delta + 0x2000) >> 14 ; if (delta < 5) delta = 5 ; return (short) val ; } #include <libc.h> static long ad2_to_snd (ZyxelSND *zsnd,short *data) { long sndsamples = 0 ; unsigned char zbyte ; int ii ; for (ii = 0 ; ii < zsnd->voicelen ; ii++) { zbyte = *(zsnd->voice + ii) ; *data++ = NXSwapHostShortToBig (ad2_to_lin16(zbyte >> 6)) ; *data++ = NXSwapHostShortToBig (ad2_to_lin16(zbyte >> 4)) ; *data++ = NXSwapHostShortToBig (ad2_to_lin16(zbyte >> 2)) ; *data++ = NXSwapHostShortToBig (ad2_to_lin16(zbyte)) ; sndsamples += 4 ; } return sndsamples ; } static long ad3_to_snd (ZyxelSND *zsnd,short *data) { long sndsamples = 0 ; unsigned char zbyte ; int ii ; int icnt = 3 , restbyte = 0 ; for (ii = 0 ; ii < zsnd->voicelen ; ii++) { zbyte = *(zsnd->voice + ii) ; switch (icnt) { case 3: *data++ = NXSwapHostShortToBig (ad3_to_lin16(zbyte >> 5)) ; *data++ = NXSwapHostShortToBig (ad3_to_lin16(zbyte >> 2)) ; restbyte = zbyte << 1 ; sndsamples += 2 ; break ; case 2: *data++ = NXSwapHostShortToBig (ad3_to_lin16(restbyte | (zbyte >> 7))) ; *data++ = NXSwapHostShortToBig (ad3_to_lin16(zbyte >> 4)) ; *data++ = NXSwapHostShortToBig (ad3_to_lin16(zbyte >> 1)) ; restbyte = zbyte << 2 ; sndsamples += 3 ; break ; case 1: *data++ = NXSwapHostShortToBig (ad3_to_lin16(restbyte | (zbyte >> 6))) ; *data++ = NXSwapHostShortToBig (ad3_to_lin16(zbyte >> 3)) ; *data++ = NXSwapHostShortToBig (ad3_to_lin16(zbyte)) ; sndsamples += 3 ; break ; } if (--icnt == 0) icnt = 3 ; } return sndsamples ; } static void PrintUsage (void) { printf ("usage: zsndplay [-h] [-c] <Zyxel_voice_file>\n") ; printf (" use option -c for converting to 8012Hz, 8bit mulaw\n") ; } #import <sound/sound.h> static int endSound (SNDSoundStruct *sound,int tag,int err) { exit (0) ; } int main (int argc,char *argv[]) { int rc , opt , optconvert = 0 , slen = 0 ; ZyxelSND zsnd ; SNDSoundStruct *sndp ; char *soundfile = NULL ; /***** ***** we scan options and parameters *****/ while ((opt = getopt(argc,argv,"ch")) != -1) { switch (opt) { case 'c': optconvert = 1 ; break ; case 'h': PrintUsage () ; return 2 ; case '?' : return 1 ; } } if (argc - optind != 1) { PrintUsage () ; return 2 ; } if ((rc = ZSNDread (argv[optind],&zsnd)) != 0) { switch (rc) { case ZYX_NOZYXELSTRUCT: printf ("zsndplay: Not a ZyXEL voice file.\n") ; break ; case ZYX_NOMODE: printf ("zsndplay: Not a ZyXEL voice file (Mode is not voice).\n") ; break ; case ZYX_NOVOICE: printf ("zsndplay: Not a ZyXEL voice file (Unknown voice type).\n") ; break ; default: printf ("zsndplay: General problems reading ZyXEL voice file.\n") ; break ; } return 1 ; } if (zsnd.zyxel.voice == ZYX_CLP) { printf ("zsndplay: Unsupported ZyXEL voice format CELP.\n") ; return 1 ; } switch (zsnd.zyxel.voice) { case ZYX_AD3: printf ("zsnd2snd: Playing ZyXEL voice file with format ADPCM3.\n") ; slen = zsnd.voicelen * 8 / 3 ; soundfile = malloc (sizeof(SNDSoundStruct) + slen * sizeof(short)) ; ad3_to_snd (&zsnd,(short*)(soundfile+sizeof(SNDSoundStruct))) ; break ; case ZYX_AD2: printf ("zsnd2snd: Playing ZyXEL voice file with format ADPCM2.\n") ; slen = zsnd.voicelen * 4 ; soundfile = malloc (sizeof(SNDSoundStruct) + slen * sizeof(short)) ; ad2_to_snd (&zsnd,(short*)(soundfile+sizeof(SNDSoundStruct))) ; break ; } ZSNDfree (&zsnd) ; sndp = (SNDSoundStruct*)soundfile ; sndp->magic = SND_MAGIC ; sndp->dataLocation = sizeof(SNDSoundStruct) ; sndp->dataSize = slen * sizeof(short) ; sndp->dataFormat = SND_FORMAT_LINEAR_16 ; sndp->samplingRate = 9600 ; sndp->channelCount = 1 ; if (optconvert) { SNDSoundStruct *sndpc , snd ; snd.magic = SND_MAGIC; snd.dataFormat = SND_FORMAT_MULAW_8 ; snd.samplingRate = 8012 ; snd.channelCount = 1 ; sndpc = &snd ; SNDConvertSound (sndp,&sndpc) ; sndp = sndpc ; } SNDStartPlaying (sndp,0,0,0,SND_NULL_FUN,endSound) ; while (1) sleep (1000) ; return 0 ; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.