Mercurial > hg > xemacs-beta
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 |