1 /**
2  * @file   wrwav.c
3  *
4  * <JA>
5  * @brief  �����ȷ��ǡ����� WAV �ե��������¸����
6  * </JA>
7  * <EN>
8  * @brief  Write waveform data to WAV file
9  * </EN>
10  *
11  * @author Akinobu LEE
12  * @date   Tue Feb 15 01:02:18 2005
13  *
14  * $Revision: 1.2 $
15  *
16  */
17 /*
18  * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
19  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
20  * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
21  * All rights reserved
22  */
23 
24 #include <sent/stddefs.h>
25 #include <sent/speech.h>
26 
27 /// Total number of samples written to the file.
28 static int totallen;
29 
30 /**
31  * Write speech data in little endian.
32  *
33  * @param buf [in] speech data
34  * @param unitbyte [in] unit size in bytes
35  * @param unitnum [in] number of units to be written
36  * @param fp [in] file pointer
37  *
38  * @return TRUE on success (specified number of data has been written), FALSE on failure.
39  */
40 static boolean
mywrite(void * buf,size_t unitbyte,int unitnum,FILE * fp)41 mywrite(void *buf, size_t unitbyte, int unitnum, FILE *fp)
42 {
43   int tmp;
44 #ifdef WORDS_BIGENDIAN
45   if (unitbyte > 1) swap_bytes(buf, unitbyte, unitnum);
46 #endif
47   if ((tmp = myfwrite(buf, unitbyte, unitnum, fp)) < unitnum) {
48     return(FALSE);
49   }
50 #ifdef WORDS_BIGENDIAN
51   if (unitbyte > 1) swap_bytes(buf, unitbyte, unitnum);
52 #endif
53   return(TRUE);
54 }
55 
56 /// Function macro to mywrite() with error handling.
57 #define MYWRITE(A,B,C,D)  if (!mywrite(A, B, C, D)) {jlog("Error: wrwav: failed to write wave data\n"); fclose_writefile(fp); return NULL;}
58 
59 /* open/create a WAVE file for writing, and write header */
60 /* return file pointer, NULL on failure */
61 /**
62  * @brief Open/create a WAVE file and write header.
63  *
64  * Open or creat a new WAV file and prepare for later data writing.
65  * The frame length written here is dummy, and will be overwritten when
66  * closed by wrwav_close().
67  *
68  * @param filename [in] file name
69  * @param sfreq [in] sampling frequency of the data you are going to write
70  *
71  * @return the file pointer.
72  */
73 FILE *
wrwav_open(char * filename,int sfreq)74 wrwav_open(char *filename, int sfreq)
75 {
76   FILE *fp;
77   unsigned int i;
78   unsigned short s;
79 
80   /* open file for writing */
81   if ((fp = fopen_writefile(filename)) == NULL) return NULL;
82 
83   /* write header */
84   /* first 4 byte: 'R' 'I' 'F' 'F' */
85   MYWRITE("RIFF", 1, 4, fp);
86   /* 4 byte: byte num of rest: dummy for now */
87   i = 0; MYWRITE(&i, 4, 1, fp);
88 
89   /* first part: WAVE format specifications */
90   /* 8 byte: 'W' 'A' 'V' 'E' 'f' 'm' 't' ' ' */
91   MYWRITE("WAVEfmt ", 1, 8, fp);
92   /* 4byte: byte size of the next part (16 bytes here) */
93   i = 16; MYWRITE(&i, 4, 1, fp);
94   /* 2byte: data format */
95   s = 1; MYWRITE(&s, 2, 1, fp);	/* PCM */
96   /* 2byte: channel num */
97   s = 1; MYWRITE(&s, 2, 1, fp);	/* mono */
98   /* 4byte: sampling rate */
99   i = sfreq; MYWRITE(&i, 4, 1, fp);
100   /* 4byte: bytes per second */
101   i = sfreq * sizeof(SP16); MYWRITE(&i, 4, 1, fp);
102   /* 2bytes: bytes per frame ( = (bytes per sample) x channel ) */
103   s = sizeof(SP16); MYWRITE(&s, 2, 1, fp);
104   /* 2bytes: bits per sample */
105   s = sizeof(SP16) * 8; MYWRITE(&s, 2, 1, fp);
106 
107   /* data part header */
108   MYWRITE("data", 1, 4, fp);
109   /* data length: dummy for now */
110   i = 0; MYWRITE(&i, 4, 1, fp);
111 
112   totallen = 0;			/* reset total length */
113 
114   return(fp);
115 }
116 
117 /**
118  * Write speech samples.
119  *
120  * @param fp [in] file descriptor
121  * @param buf [in] speech data to be written
122  * @param len [in] length of above
123  *
124  * @return actual number of written samples.
125  */
126 boolean
wrwav_data(FILE * fp,SP16 * buf,int len)127 wrwav_data(FILE *fp, SP16 *buf, int len)
128 {
129   boolean ret;
130   ret = mywrite(buf, sizeof(SP16), len, fp);
131   if (ret) totallen += len;
132   return(ret);
133 }
134 
135 /* close file */
136 /**
137  * @brief  Close the file.
138  *
139  * The frame length in the header part is overwritten by the actual value
140  * before file close.
141  *
142  * @param fp [in] file pointer to close, previously opened by wrwav_open().
143  *
144  * @return TRUE on success, FALSE on failure.
145  */
146 boolean
wrwav_close(FILE * fp)147 wrwav_close(FILE *fp)
148 {
149   unsigned int i;
150 
151   /* overwrite data length after recording */
152   /* at 5-8(len+36), 41-44 (len) */
153   if (fseek(fp, 40, SEEK_SET) != 0) { /* error */
154     jlog("Error: wrwav: failed to seek for header\n");
155     return(FALSE);
156   }
157   i = totallen * sizeof(SP16);
158   if (!mywrite(&i, 4, 1, fp)) {
159     jlog("Error: wrwav: failed to re-write header\n");
160     return(FALSE);
161   }
162   if (fseek(fp, 4, SEEK_SET) != 0) { /* error */
163     jlog("Error: wrwav: failed to seek for header\n");
164     return(FALSE);
165   }
166   i = totallen * sizeof(SP16) + 36;
167   if (!mywrite(&i, 4, 1, fp)) {
168     jlog("Error: wrwav: failed to re-write header\n");
169     return(FALSE);
170   }
171 
172   /* close file */
173   fclose_writefile(fp);
174 
175   return(TRUE);
176 }
177