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