comparison src/nas.c @ 375:a300bb07d72d r21-2b3

Import from CVS: tag r21-2b3
author cvs
date Mon, 13 Aug 2007 11:04:51 +0200
parents cc15677e0335
children 8626e4521993
comparison
equal deleted inserted replaced
374:4ebeb1a5388b 375:a300bb07d72d
47 * 10/8/94, rjc Changed names from netaudio to nas 47 * 10/8/94, rjc Changed names from netaudio to nas
48 * Added back asynchronous play if nas library has 48 * Added back asynchronous play if nas library has
49 * correct error facilities. 49 * correct error facilities.
50 * 4/11/94, rjc Added wait_for_sounds to be called when user wants to 50 * 4/11/94, rjc Added wait_for_sounds to be called when user wants to
51 * be sure all play has finished. 51 * be sure all play has finished.
52 * 1998-10-01 rlt Added support for WAVE files.
52 */ 53 */
53 54
54 #ifdef emacs 55 #ifdef emacs
55 #include <config.h> 56 #include <config.h>
56 #include "lisp.h" 57 #include "lisp.h"
72 #undef LITTLE_ENDIAN 73 #undef LITTLE_ENDIAN
73 #undef BIG_ENDIAN 74 #undef BIG_ENDIAN
74 #include <audio/audiolib.h> 75 #include <audio/audiolib.h>
75 #include <audio/soundlib.h> 76 #include <audio/soundlib.h>
76 #include <audio/snd.h> 77 #include <audio/snd.h>
78 #include <audio/wave.h>
77 #include <audio/fileutil.h> 79 #include <audio/fileutil.h>
78 80
79 #ifdef emacs 81 #ifdef emacs
80 82
81 # define XTOOLKIT 83 # define XTOOLKIT
484 if (SoundFileFormat (s) == SoundFileFormatSnd) 486 if (SoundFileFormat (s) == SoundFileFormatSnd)
485 { 487 {
486 /* hack, hack */ 488 /* hack, hack */
487 offset = ((SndInfo *) (s->formatInfo))->h.dataOffset; 489 offset = ((SndInfo *) (s->formatInfo))->h.dataOffset;
488 } 490 }
491 else if (SoundFileFormat (s) == SoundFileFormatWave)
492 {
493 offset = ((WaveInfo *) (s->formatInfo))->dataOffset;
494 }
489 else 495 else
490 { 496 {
491 warn ("only understand snd files at the moment"); 497 warn ("only understand snd and wave files at the moment");
492 SoundCloseFile (s); 498 SoundCloseFile (s);
493 #ifdef ROBUST_PLAY 499 #ifdef ROBUST_PLAY
494 signal (SIGPIPE, old_sigpipe); 500 signal (SIGPIPE, old_sigpipe);
495 #endif 501 #endif
496 return 0; 502 return 0;
574 aud = NULL; 580 aud = NULL;
575 sounds_in_play = 0; 581 sounds_in_play = 0;
576 longjmp (AuXtErrorJump, 1); 582 longjmp (AuXtErrorJump, 1);
577 583
578 #endif /* XTEVENTS */ 584 #endif /* XTEVENTS */
585 return 0;
579 } 586 }
580 587
581 SIGTYPE 588 SIGTYPE
582 sigpipe_handle (int signo) 589 sigpipe_handle (int signo)
583 { 590 {
709 si->fp=NULL; 716 si->fp=NULL;
710 717
711 return si; 718 return si;
712 } 719 }
713 720
721 /* Stuff taken from wave.c from NAS. Just like snd files, NAS can't
722 read wave data from memory, so these functions do that for us. */
723
724 #define Err() { return NULL; }
725 #define readFourcc(_f) dread(_f, sizeof(RIFF_FOURCC), 1)
726 #define cmpID(_x, _y) \
727 strncmp((char *) (_x), (char *) (_y), sizeof(RIFF_FOURCC))
728 #define PAD2(_x) (((_x) + 1) & ~1)
729
730 /* These functions here are for faking file I/O from buffer. */
731
732 /* The "file" position */
733 static int file_posn;
734 /* The length of the "file" */
735 static int file_len;
736 /* The actual "file" data. */
737 CONST static char* file_data;
738
739 /* Like fopen, but for a buffer in memory */
740 static void
741 dopen(CONST char* data, int length)
742 {
743 file_data = data;
744 file_len = length;
745 file_posn = 0;
746 }
747
748 /* Like fread, but for a buffer in memory */
749 static int
750 dread(char* buf, int size, int nitems)
751 {
752 int nread;
753
754 nread = size * nitems;
755
756 if (file_posn + nread <= file_len)
757 {
758 memcpy(buf, file_data + file_posn, size * nitems);
759 file_posn += nread;
760 return nitems;
761 }
762 else
763 {
764 return EOF;
765 }
766 }
767
768 /* Like fgetc, but for a buffer in memory */
769 static int
770 dgetc()
771 {
772 int ch;
773
774 if (file_posn < file_len)
775 return file_data[file_posn++];
776 else
777 return -1;
778 }
779
780 /* Like fseek, but for a buffer in memory */
781 static int
782 dseek(long offset, int from)
783 {
784 if (from == 0)
785 file_posn = offset;
786 else if (from == 1)
787 file_posn += offset;
788 else if (from == 2)
789 file_posn = file_len + offset;
790
791 return 0;
792 }
793
794 /* Like ftell, but for a buffer in memory */
795 static int
796 dtell()
797 {
798 return file_posn;
799 }
800
801 /* Data buffer analogs for FileReadS and FileReadL in NAS. */
802
803 static unsigned short
804 DataReadS(int swapit)
805 {
806 unsigned short us;
807
808 dread(&us, 2, 1);
809 if (swapit)
810 us = FileSwapS(us);
811 return us;
812 }
813
814 static AuUint32
815 DataReadL(int swapit)
816 {
817 AuUint32 ul;
818
819 dread(&ul, 4, 1);
820 if (swapit)
821 ul = FileSwapL(ul);
822 return ul;
823 }
824
825 static int
826 readChunk(RiffChunk *c)
827 {
828 int status;
829 char n;
830
831 if ((status = dread(c, sizeof(RiffChunk), 1)))
832 if (BIG_ENDIAN)
833 swapl(&c->ckSize, n);
834
835 return status;
836 }
837
838 /* A very straight-forward translation of WaveOpenFileForReading to
839 read the wave data from a buffer in memory. */
840
841 static WaveInfo *
842 WaveOpenDataForReading(CONST char *data,
843 int length)
844 {
845 RiffChunk ck;
846 RIFF_FOURCC fourcc;
847 AuInt32 fileSize;
848 WaveInfo *wi;
849
850
851 if (!(wi = (WaveInfo *) malloc(sizeof(WaveInfo))))
852 return NULL;
853
854 wi->comment = NULL;
855 wi->dataOffset = wi->format = wi->writing = 0;
856
857 dopen(data, length);
858
859 if (!readChunk(&ck) ||
860 cmpID(&ck.ckID, RIFF_RiffID) ||
861 !readFourcc(&fourcc) ||
862 cmpID(&fourcc, RIFF_WaveID))
863 Err();
864
865 fileSize = PAD2(ck.ckSize) - sizeof(RIFF_FOURCC);
866
867 while (fileSize >= sizeof(RiffChunk))
868 {
869 if (!readChunk(&ck))
870 Err();
871
872 fileSize -= sizeof(RiffChunk) + PAD2(ck.ckSize);
873
874 /* LIST chunk */
875 if (!cmpID(&ck.ckID, RIFF_ListID))
876 {
877 if (!readFourcc(&fourcc))
878 Err();
879
880 /* INFO chunk */
881 if (!cmpID(&fourcc, RIFF_ListInfoID))
882 {
883 ck.ckSize -= sizeof(RIFF_FOURCC);
884
885 while (ck.ckSize)
886 {
887 RiffChunk c;
888
889 if (!readChunk(&c))
890 Err();
891
892 /* ICMT chunk */
893 if (!cmpID(&c.ckID, RIFF_InfoIcmtID))
894 {
895 if (!(wi->comment = (char *) malloc(c.ckSize)) ||
896 !dread(wi->comment, c.ckSize, 1))
897 Err();
898
899 if (c.ckSize & 1)
900 dgetc(); /* eat the pad byte */
901 }
902 else
903 /* skip unknown chunk */
904 dseek(PAD2(c.ckSize), 1);
905
906 ck.ckSize -= sizeof(RiffChunk) + PAD2(c.ckSize);
907 }
908 }
909 else
910 /* skip unknown chunk */
911 dseek(PAD2(ck.ckSize) - sizeof(RIFF_FOURCC), 1);
912 }
913 /* wave format chunk */
914 else if (!cmpID(&ck.ckID, RIFF_WaveFmtID) && !wi->format)
915 {
916 AuInt32 dummy;
917
918 wi->format = DataReadS(BIG_ENDIAN);
919 wi->channels = DataReadS(BIG_ENDIAN);
920 wi->sampleRate = DataReadL(BIG_ENDIAN);
921
922 /* we don't care about the next two fields */
923 dummy = DataReadL(BIG_ENDIAN);
924 dummy = DataReadS(BIG_ENDIAN);
925
926 if (wi->format != RIFF_WAVE_FORMAT_PCM)
927 Err();
928
929 wi->bitsPerSample = DataReadS(BIG_ENDIAN);
930
931 /* skip any other format specific fields */
932 dseek(PAD2(ck.ckSize - 16), 1);
933 }
934 /* wave data chunk */
935 else if (!cmpID(&ck.ckID, RIFF_WaveDataID) && !wi->dataOffset)
936 {
937 long endOfFile;
938
939 wi->dataOffset = dtell();
940 wi->dataSize = ck.ckSize;
941 dseek(0, 2);
942 endOfFile = dtell();
943
944 /* seek past the data */
945 if (dseek(wi->dataOffset + PAD2(ck.ckSize), 0) ||
946 dtell() > endOfFile)
947 {
948 /* the seek failed, assume the size is bogus */
949 dseek(0, 2);
950 wi->dataSize = dtell() - wi->dataOffset;
951 }
952
953 wi->dataOffset -= sizeof(long);
954 }
955 else
956 /* skip unknown chunk */
957 dseek(PAD2(ck.ckSize), 1);
958 }
959
960 if (!wi->dataOffset)
961 Err();
962
963 wi->numSamples = wi->dataSize / wi->channels / (wi->bitsPerSample >> 3);
964
965 if (!wi->comment)
966 wi->comment = NameFromData (data + wi->dataOffset,
967 length - wi->dataOffset);
968
969 wi->fp = NULL;
970
971 return wi;
972 }
973
974
714 static Sound 975 static Sound
715 SoundOpenDataForReading (unsigned char *data, 976 SoundOpenDataForReading (unsigned char *data,
716 int length) 977 int length)
717 978
718 { 979 {
719 Sound s; 980 Sound s;
720 981
721 if (!(s = (Sound) malloc (sizeof (SoundRec)))) 982 if (!(s = (Sound) malloc (sizeof (SoundRec))))
722 return NULL; 983 return NULL;
723 984
724 if ((s->formatInfo = SndOpenDataForReading (data, length))==NULL) 985 if ((s->formatInfo = SndOpenDataForReading (data, length)) != NULL)
725 { 986 {
726 free (s); 987 if (!(SoundFileInfo[SoundFileFormatSnd].toSound) (s))
727 return NULL; 988 {
728 } 989 SndCloseFile (s->formatInfo);
729 990 free (s);
730 991 return NULL;
731 if (!(SoundFileInfo[SoundFileFormatSnd].toSound) (s)) 992 }
732 { 993 }
733 SndCloseFile (s->formatInfo); 994 else if ((s->formatInfo = WaveOpenDataForReading (data, length)) != NULL)
734 free (s); 995 {
735 return NULL; 996 if (!(SoundFileInfo[SoundFileFormatWave].toSound) (s))
997 {
998 WaveCloseFile (s->formatInfo);
999 free (s);
1000 return NULL;
1001 }
736 } 1002 }
737 1003
738 return s; 1004 return s;
739 } 1005 }
740 1006