summaryrefslogtreecommitdiff
path: root/tools/voicefont.c
diff options
context:
space:
mode:
authorJonas Häggqvist <rasher@rasher.dk>2006-11-03 21:47:52 +0000
committerJonas Häggqvist <rasher@rasher.dk>2006-11-03 21:47:52 +0000
commitda071d0d7c0067be55b2a6177ef01ee1ec5e88b8 (patch)
treeef33236850e37dd5595a53cb767f54311ccf4a9c /tools/voicefont.c
parentb403c6007ac1db68f3732952a12fbebe1ad7a6ea (diff)
downloadrockbox-da071d0d7c0067be55b2a6177ef01ee1ec5e88b8.tar.gz
rockbox-da071d0d7c0067be55b2a6177ef01ee1ec5e88b8.zip
Voice update, most useful for non-Windows systems. Voice file building using Festival, Flite or eSpeak from the configure script. Compressing with Speex and Vorbis possible, but won't create useable voicefiles. Adds voicefont.c and wavtrim.c by Jörg Hohensohn. Also includes a script to generate talk clips.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11426 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'tools/voicefont.c')
-rw-r--r--tools/voicefont.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/tools/voicefont.c b/tools/voicefont.c
new file mode 100644
index 0000000000..0a6d0a2121
--- /dev/null
+++ b/tools/voicefont.c
@@ -0,0 +1,218 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jörg Hohensohn
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 * A tool to generate the Rockbox "voicefont", a collection of all the UI
19 * strings.
20 *
21 * Details at http://www.rockbox.org/twiki/bin/view/Main/VoiceBuilding
22 *
23 ****************************************************************************/
24
25#include <stdio.h>
26#include <string.h>
27
28/* endian conversion macros */
29#define SWAP2(x) ((((unsigned)(x)>>8) & 0x00ff) | (((unsigned)(x)<<8) & 0xff00))
30#define SWAP4(x) ((((unsigned)(x)>>24) & 0x000000ff) |\
31 (((unsigned)(x)>>8) & 0x0000ff00) |\
32 (((unsigned)(x)<<8) & 0x00ff0000) |\
33 (((unsigned)(x)<<24) & 0xff000000))
34
35
36/* bitswap audio bytes, LSB becomes MSB and vice versa */
37int BitswapAudio (unsigned char* pDest, unsigned char* pSrc, size_t len)
38{
39 static const unsigned char Lookup[256] =
40 {
41 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
42 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
43 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
44 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
45 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
46 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
47 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
48 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
49 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
50 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
51 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
52 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
53 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
54 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
55 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
56 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF,
57 };
58
59 while (len--)
60 *pDest++ = Lookup[*pSrc++];
61
62 return 0;
63}
64
65
66int main (int argc, char** argv)
67{
68 FILE* pFile;
69
70 int i,j;
71
72 /* two tables, one for normal strings, one for voice-only (>0x8000) */
73 static char names[1000][80]; /* worst-case space */
74 char name[80]; /* one string ID */
75 static int pos[1000]; /* position of sample */
76 static int size[1000]; /* length of clip */
77 int voiceonly[1000]; /* flag if this is voice only */
78 int count = 0;
79 int count_voiceonly = 0;
80 unsigned int value; /* value to be written to file */
81 static unsigned char buffer[65535]; /* clip buffer, allow only 64K */
82 int fields;
83 char line[255]; /* one line from the .lang file */
84 char mp3filename1[1024];
85 char mp3filename2[1024];
86 char* mp3filename;
87 FILE* pMp3File;
88
89
90 if (argc < 2)
91 {
92 printf("Makes a Rockbox voicefont from a collection of mp3 clips.\n");
93 printf("Usage: voicefont <language file> <mp3 path> <output file>\n");
94 printf("\n");
95 printf("Example: \n");
96 printf("voicefont english.lang voice\\ voicefont.bin\n");
97 return -1;
98 }
99
100 pFile = fopen(argv[1], "r");
101 if (pFile == NULL)
102 {
103 printf("Error opening language file %s\n", argv[1]);
104 return -2;
105 }
106
107 memset(voiceonly, 0, sizeof(voiceonly));
108 while (!feof(pFile))
109 {
110 fgets(line, sizeof(line), pFile);
111 if (line[0] == '#') /* comment */
112 continue;
113
114 fields = sscanf(line, " id: %s", name);
115 if (fields == 1)
116 {
117 count++; /* next entry started */
118 strcpy(names[count-1], name);
119 if (strncmp("VOICE_", name, 6) == 0) /* voice-only id? */
120 voiceonly[count-1] = 1;
121 continue;
122 }
123 }
124 fclose(pFile);
125
126 pFile = fopen(argv[3], "wb");
127 if (pFile == NULL)
128 {
129 printf("Error opening output file %s\n", argv[3]);
130 return -2;
131 }
132 fseek(pFile, 16 + count*8, SEEK_SET); /* space for header */
133
134 for (i=0; i<count; i++)
135 {
136 if (voiceonly[i] == 1)
137 count_voiceonly++;
138
139 pos[i] = ftell(pFile);
140 sprintf(mp3filename1, "%s%s.mp3", argv[2], names[i]);
141 sprintf(mp3filename2, "%s%s.wav.mp3", argv[2], names[i]);
142 mp3filename = mp3filename1;
143 pMp3File = fopen(mp3filename, "rb");
144 if (pMp3File == NULL)
145 { /* alternatively, try the lame default filename */
146 mp3filename = mp3filename2;
147 pMp3File = fopen(mp3filename, "rb");
148 if (pMp3File == NULL)
149 {
150 printf("mp3 file %s not found!\n", mp3filename1);
151 size[i] = 0;
152 continue;
153 }
154 }
155 printf("processing %s\n", mp3filename);
156
157 size[i] = fread(buffer, 1, sizeof(buffer), pMp3File);
158 fclose(pMp3File);
159 BitswapAudio(buffer, buffer, size[i]);
160 fwrite(buffer, 1, size[i], pFile);
161
162 printf("%d %s %d\n", i, names[i], size[i]); /* debug */
163 } /* for i */
164
165
166 fseek(pFile, 0, SEEK_SET);
167
168 /* Create the file format: */
169
170 /* 1st 32 bit value in the file is the version number */
171 value = SWAP4(200); /* 2.00 */
172 fwrite(&value, sizeof(value), 1, pFile);
173
174 /* 2nd 32 bit value in the file is the header size (= 1st table position) */
175 value = SWAP4(16); /* 16 bytes: for version, header size, number1, number2 */
176 fwrite(&value, sizeof(value), 1, pFile);
177
178 /* 3rd 32 bit value in the file is the number of clips in 1st table */
179 value = SWAP4(count-count_voiceonly);
180 fwrite(&value, sizeof(value), 1, pFile);
181
182 /* 4th bit value in the file is the number of clips in 2nd table */
183 value = SWAP4(count_voiceonly);
184 fwrite(&value, sizeof(value), 1, pFile);
185
186 /* then followed by offset/size pairs for each clip */
187 for (j=0; j<2; j++) /* now 2 tables */
188 {
189 for (i=0; i<count; i++)
190 {
191 if (j == 0) /* first run, skip the voice only ones */
192 {
193 if (voiceonly[i] == 1)
194 continue;
195 }
196 else /* second run, skip the non voice only ones */
197 {
198 if (!voiceonly[i] == 1)
199 continue;
200 }
201
202 value = SWAP4(pos[i]); /* position */
203 fwrite(&value, sizeof(value), 1, pFile);
204 value = SWAP4(size[i]); /* size */
205 fwrite(&value, sizeof(value), 1, pFile);
206 } /* for i */
207 } /* for j */
208
209
210 /*
211 * after this the actual bitswapped mp3 data follows,
212 * which we already have written, see above.
213 */
214
215 fclose(pFile);
216
217 return 0;
218}