A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jörg Hohensohn
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 * A tool to generate the Rockbox "voicefont", a collection of all the UI
21 * strings.
22 *
23 * Details at http://www.rockbox.org/wiki/VoiceBuilding
24 *
25 ****************************************************************************/
26
27#include "voicefont.h"
28
29#include <stdio.h>
30#include <string.h>
31
32#define HEADER_SIZE (20)
33#define MAX_NAME_LEN (80)
34#define MAX_VOICE_ENTRIES (2048)
35/* endian conversion macros */
36#if defined(__BIG_ENDIAN__)
37#define UINT_TO_BE(x) (x)
38#else
39#define UINT_TO_BE(x) ((((unsigned)(x)>>24) & 0x000000ff) |\
40 (((unsigned)(x)>>8) & 0x0000ff00) |\
41 (((unsigned)(x)<<8) & 0x00ff0000) |\
42 (((unsigned)(x)<<24) & 0xff000000))
43#endif
44
45int voicefont(FILE* voicefontids,int targetnum,char* filedir, FILE* output, unsigned int version)
46{
47
48 int i,j;
49
50 /* two tables, one for normal strings, one for voice-only (>0x8000) */
51 static char names[MAX_VOICE_ENTRIES][MAX_NAME_LEN]; /* worst-case space */
52 char name[MAX_NAME_LEN]; /* one string ID */
53 static int pos[MAX_VOICE_ENTRIES]; /* position of sample */
54 static int size[MAX_VOICE_ENTRIES]; /* length of clip */
55 int voiceonly[MAX_VOICE_ENTRIES]; /* flag if this is voice only */
56 int count = 0;
57 int count_voiceonly = 0;
58 unsigned int value; /* value to be written to file */
59 static unsigned char buffer[65535]; /* clip buffer, allow only 64K */
60 int fields;
61 char line[255]; /* one line from the .lang file */
62 char encfilename1[1024];
63 char encfilename2[1024];
64 char* encfilename;
65 FILE* pEncFile;
66
67 memset(voiceonly, 0, sizeof(voiceonly));
68 while (!feof(voicefontids))
69 {
70 if (!fgets(line, sizeof(line), voicefontids))
71 break;
72 if (line[0] == '#') /* comment */
73 continue;
74
75 fields = sscanf(line, " id: %s", name);
76 if (fields == 1)
77 {
78 strcpy(names[count], name);
79 if (strncmp("VOICE_", name, 6) == 0) /* voice-only id? */
80 {
81 count_voiceonly++;
82 voiceonly[count] = 1;
83 }
84 count++; /* next entry started */
85 continue;
86 }
87 }
88 fclose(voicefontids);
89
90 if (count > MAX_VOICE_ENTRIES)
91 {
92 return -1;
93 }
94
95 fseek(output, HEADER_SIZE + count*8, SEEK_SET); /* space for header */
96
97 for (i=0; i<count; i++)
98 {
99 pos[i] = ftell(output);
100 sprintf(encfilename1, "%s%s.enc", filedir, names[i]);
101 sprintf(encfilename2, "%s%s.wav.enc", filedir, names[i]);
102 encfilename = encfilename1;
103 pEncFile = fopen(encfilename, "rb");
104 if (pEncFile == NULL)
105 { /* alternatively, try the lame default filename */
106 encfilename = encfilename2;
107 pEncFile = fopen(encfilename, "rb");
108 if (pEncFile == NULL)
109 {
110 printf("enc file %s not found!\n", encfilename1);
111 size[i] = 0;
112 continue;
113 }
114 }
115 printf("processing %s", encfilename);
116
117 size[i] = fread(buffer, 1, sizeof(buffer), pEncFile);
118 fclose(pEncFile);
119 fwrite(buffer, 1, size[i], output);
120
121 printf(": %d %s %d\n", i, names[i], size[i]); /* debug */
122 } /* for i */
123
124
125 fseek(output, 0, SEEK_SET);
126
127 /* Create the file format: */
128
129 /* 1st 32 bit value in the file is the version number */
130 value = UINT_TO_BE(version);
131 fwrite(&value, sizeof(value), 1, output);
132
133 /* 2nd 32 bit value in the file is the id number for the target
134 we made the voce file for */
135 value = UINT_TO_BE(targetnum);
136 fwrite(&value, sizeof(value), 1, output);
137
138 /* 3rd 32 bit value in the file is the header size (= 1st table position) */
139 value = UINT_TO_BE(HEADER_SIZE); /* version, target id, header size, number1, number2 */
140 fwrite(&value, sizeof(value), 1, output);
141
142 /* 4th 32 bit value in the file is the number of clips in 1st table */
143 value = UINT_TO_BE(count-count_voiceonly);
144 fwrite(&value, sizeof(value), 1, output);
145
146 /* 5th bit value in the file is the number of clips in 2nd table */
147 value = UINT_TO_BE(count_voiceonly);
148 fwrite(&value, sizeof(value), 1, output);
149
150 /* then followed by offset/size pairs for each clip */
151 for (j=0; j<2; j++) /* now 2 tables */
152 {
153 for (i=0; i<count; i++)
154 {
155 if (j == 0) /* first run, skip the voice only ones */
156 {
157 if (voiceonly[i] == 1)
158 continue;
159 }
160 else /* second run, skip the non voice only ones */
161 {
162 if (!(voiceonly[i] == 1))
163 continue;
164 }
165
166 value = UINT_TO_BE(pos[i]); /* position */
167 fwrite(&value, sizeof(value), 1,output);
168 value = UINT_TO_BE(size[i]); /* size */
169 fwrite(&value, sizeof(value), 1, output);
170 printf(": [%d]%s : %s {%x, %x}\n", i,
171 (voiceonly[i] ==1 ? "[V]":""), names[i],
172 UINT_TO_BE(pos[i]), UINT_TO_BE(size[i])); /* debug */
173 } /* for i */
174 } /* for j */
175
176 fclose(output);
177
178 return 0;
179
180
181}
182#ifndef RBUTIL
183int main (int argc, char** argv)
184{
185 FILE *ids, *output;
186
187 if (argc < 2)
188 {
189 printf("Makes a Rockbox voicefont from a collection of encoded clips.\n");
190 printf("Usage: voicefont <string id list file> <target id> <enc path> <output file>\n");
191 printf("\n");
192 printf("Example: \n");
193 printf("voicefont voicefontids.txt 2 voice/ voicefont.bin\n");
194 return -1;
195 }
196
197 ids = fopen(argv[1], "r");
198 if (ids == NULL)
199 {
200 printf("Error opening language file %s\n", argv[1]);
201 return -2;
202 }
203
204 output = fopen(argv[4], "wb");
205 if (output == NULL)
206 {
207 printf("Error opening output file %s\n", argv[4]);
208 return -2;
209 }
210
211 if (voicefont(ids, atoi(argv[2]),argv[3],output, 400) < 0)
212 {
213 printf("Error too many voicefont entries!\n");
214 return -3;
215 }
216 return 0;
217}
218#endif