First stab at porting rbutil to Qt4. Currently only installing a current or archived...
[Rockbox.git] / tools / wavtrim.c
blob86434235bae8587fd325b337a70be2a3ef463366
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 by Jörg Hohensohn
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 * Details at http://www.rockbox.org/twiki/bin/view/Main/VoiceBuilding
20 ****************************************************************************/
23 #include <stdio.h> /* for file I/O */
24 #include <stdlib.h> /* for malloc */
26 /* place a 32 bit value into memory, little endian */
27 void Write32(unsigned char* pByte, unsigned long value)
29 pByte[0] = (unsigned char)value;
30 pByte[1] = (unsigned char)(value >> 8);
31 pByte[2] = (unsigned char)(value >> 16);
32 pByte[3] = (unsigned char)(value >> 24) ;
36 /* read a 32 bit value from memory, little endian */
37 unsigned long Read32(unsigned char* pByte)
39 unsigned long value = 0;
41 value |= (unsigned long)pByte[0];
42 value |= (unsigned long)pByte[1] << 8;
43 value |= (unsigned long)pByte[2] << 16;
44 value |= (unsigned long)pByte[3] << 24;
46 return value;
50 /* place a 16 bit value into memory, little endian */
51 void Write16(unsigned char* pByte, unsigned short value)
53 pByte[0] = (unsigned char)value;
54 pByte[1] = (unsigned char)(value >> 8);
58 /* read a 16 bit value from memory, little endian */
59 unsigned long Read16(unsigned char* pByte)
61 unsigned short value = 0;
63 value |= (unsigned short)pByte[0];
64 value |= (unsigned short)pByte[1] << 8;
66 return value;
70 int main (int argc, char** argv)
72 FILE* pFile;
73 long lFileSize, lGot;
74 unsigned char* pBuf;
75 int bps; /* byte per sample */
76 int sps; /* samples per second */
77 int datapos; /* where the payload starts */
78 int skip_head, skip_tail, pad_head, pad_tail;
79 int i;
80 int max_silence = 0;
81 signed char sample8;
82 short sample16;
84 if (argc < 2)
86 printf("wavtrim removes silence at the begin and end of a WAV file.\n");
87 printf("usage: wavtrim <filename.wav> [<max_silence>]\n");
88 return 0;
91 if (argc == 3)
93 max_silence = atoi(argv[2]);
96 pFile = fopen(argv[1], "rb");
97 if (pFile == NULL)
99 printf("Error opening file %s for reading\n", argv[1]);
100 return -1;
103 fseek(pFile, 0, SEEK_END);
104 lFileSize = ftell(pFile);
105 fseek(pFile, 0, SEEK_SET);
107 pBuf = malloc(lFileSize);
108 if (pBuf == NULL)
110 printf("Out of memory to allocate %ld bytes for file.\n", lFileSize);
111 fclose(pFile);
112 return -1;
115 lGot = fread(pBuf, 1, lFileSize, pFile);
116 fclose(pFile);
117 if (lGot != lFileSize)
119 printf("File read error, got only %ld bytes out of %ld.\n", lGot, lFileSize);
120 free(pBuf);
121 return -1;
124 bps = Read16(pBuf + 32);
125 datapos = 28 + Read16(pBuf + 16);
127 if (Read32(pBuf) != 0x46464952 /* "RIFF" */
128 || Read32(pBuf+8) != 0x45564157 /* "WAVE" */
129 || Read32(pBuf+12) != 0x20746d66 /* "fmt " */
130 || Read32(pBuf+datapos-8) != 0x61746164) /* "data" */
132 printf("No valid input WAV file?\n", lGot, lFileSize);
133 free(pBuf);
134 return -1;
137 sps = Read32(pBuf + 24);
138 pad_head = sps * 10 / 1000; /* 10 ms */
139 pad_tail = sps * 10 / 1000; /* 10 ms */
141 if (bps == 1) /* 8 bit samples */
144 max_silence >>= 8;
146 /* clip the start */
147 for (i=datapos; i<lFileSize; i++)
149 sample8 = pBuf[i] - 0x80;
150 if (abs(sample8) > max_silence)
151 break;
153 skip_head = i - datapos;
154 skip_head = (skip_head > pad_head) ? skip_head - pad_head : 0;
156 /* clip the end */
157 for (i=lFileSize-1; i>datapos+skip_head; i--)
159 sample8 = pBuf[i] - 0x80;
160 if (abs(sample8) > max_silence)
161 break;
163 skip_tail = lFileSize - 1 - i;
164 skip_tail = (skip_tail > pad_tail) ? skip_tail - pad_tail : 0;
166 else if (bps == 2) /* 16 bit samples */
169 /* clip the start */
170 for (i=datapos; i<lFileSize; i+=2)
172 sample16 = *(short *)(pBuf + i);
173 if (abs(sample16) > max_silence)
174 break;
176 skip_head = i - datapos;
177 skip_head = (skip_head > 2 * pad_head) ?
178 skip_head - 2 * pad_head : 0;
180 /* clip the end */
181 for (i=lFileSize-2; i>datapos+skip_head; i-=2)
183 sample16 = *(short *)(pBuf + i);
184 if (abs(sample16) > max_silence)
185 break;
187 skip_tail = lFileSize - 2 - i;
188 skip_tail = (skip_tail > 2 * pad_tail) ?
189 skip_tail - 2 * pad_tail : 0;
192 /* update the size in the headers */
193 Write32(pBuf+4, Read32(pBuf+4) - skip_head - skip_tail);
194 Write32(pBuf+datapos-4, Read32(pBuf+datapos-4) - skip_head - skip_tail);
196 pFile = fopen(argv[1], "wb");
197 if (pFile == NULL)
199 printf("Error opening file %s for writing\n", argv[1]);
200 return -1;
203 /* write the new file */
204 fwrite(pBuf, 1, datapos, pFile); /* write header */
205 fwrite(pBuf + datapos + skip_head, 1, lFileSize - datapos - skip_head - skip_tail, pFile);
206 fclose(pFile);
208 free(pBuf);
209 return 0;
213 RIFF Chunk (12 bytes in length total)
214 0 - 3 "RIFF" (ASCII Characters)
215 4 - 7 Total Length Of Package To Follow (Binary, little endian)
216 8 - 11 "WAVE" (ASCII Characters)
219 FORMAT Chunk (24 or 26 bytes in length total) Byte Number
220 12 - 15 "fmt_" (ASCII Characters)
221 16 - 19 Length Of FORMAT Chunk (Binary, 0x10 or 0x12 seen)
222 20 - 21 Always 0x01
223 22 - 23 Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
224 24 - 27 Sample Rate (Binary, in Hz)
225 28 - 31 Bytes Per Second
226 32 - 33 Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
227 34 - 35 Bits Per Sample
230 DATA Chunk Byte Number
231 36 - 39 "data" (ASCII Characters)
232 40 - 43 Length Of Data To Follow
233 44 - end
234 Data (Samples)