Factor out some common code, for simplicity (I hope...) and to save size.
[kugel-rb.git] / tools / wavtrim.c
blob3d77b4e972ad03f2ee09b1f8d835bcfa5760a21a
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 datalen; /* Length of the data chunk */
79 unsigned char *databuf; /* Pointer to the data chunk payload */
80 int skip_head, skip_tail, pad_head, pad_tail;
81 int i;
82 int max_silence = 0;
83 signed char sample8;
84 short sample16;
86 if (argc < 2)
88 printf("wavtrim removes silence at the begin and end of a WAV file.\n");
89 printf("usage: wavtrim <filename.wav> [<max_silence>]\n");
90 return 0;
93 if (argc == 3)
95 max_silence = atoi(argv[2]);
98 pFile = fopen(argv[1], "rb");
99 if (pFile == NULL)
101 printf("Error opening file %s for reading\n", argv[1]);
102 return -1;
105 fseek(pFile, 0, SEEK_END);
106 lFileSize = ftell(pFile);
107 fseek(pFile, 0, SEEK_SET);
109 pBuf = malloc(lFileSize);
110 if (pBuf == NULL)
112 printf("Out of memory to allocate %ld bytes for file.\n", lFileSize);
113 fclose(pFile);
114 return -1;
117 lGot = fread(pBuf, 1, lFileSize, pFile);
118 fclose(pFile);
119 if (lGot != lFileSize)
121 printf("File read error, got only %ld bytes out of %ld.\n", lGot, lFileSize);
122 free(pBuf);
123 return -1;
126 bps = Read16(pBuf + 32);
127 datapos = 28 + Read16(pBuf + 16);
128 databuf = &pBuf[datapos];
130 if (Read32(pBuf) != 0x46464952 /* "RIFF" */
131 || Read32(pBuf+8) != 0x45564157 /* "WAVE" */
132 || Read32(pBuf+12) != 0x20746d66 /* "fmt " */
133 || Read32(pBuf+datapos-8) != 0x61746164) /* "data" */
135 printf("No valid input WAV file?\n", lGot, lFileSize);
136 free(pBuf);
137 return -1;
140 datalen = Read32(pBuf+datapos-4);
142 sps = Read32(pBuf + 24);
143 pad_head = sps * 10 / 1000; /* 10 ms */
144 pad_tail = sps * 10 / 1000; /* 10 ms */
146 if (bps == 1) /* 8 bit samples */
149 max_silence >>= 8;
151 /* clip the start */
152 for (i=0; i<datalen; i++)
154 sample8 = databuf[i] - 0x80;
155 if (abs(sample8) > max_silence)
156 break;
158 skip_head = i;
159 skip_head = (skip_head > pad_head) ? skip_head - pad_head : 0;
161 /* clip the end */
162 for (i=datalen-1; i>skip_head; i--)
164 sample8 = databuf[i] - 0x80;
165 if (abs(sample8) > max_silence)
166 break;
168 skip_tail = datalen - 1 - i;
169 skip_tail = (skip_tail > pad_tail) ? skip_tail - pad_tail : 0;
171 else if (bps == 2) /* 16 bit samples */
174 /* clip the start */
175 for (i=0; i<datalen; i+=2)
177 sample16 = *(short *)(databuf + i);
178 if (abs(sample16) > max_silence)
179 break;
181 skip_head = i;
182 skip_head = (skip_head > 2 * pad_head) ?
183 skip_head - 2 * pad_head : 0;
185 /* clip the end */
186 for (i=datalen-2; i>skip_head; i-=2)
188 sample16 = *(short *)(databuf + i);
189 if (abs(sample16) > max_silence)
190 break;
192 skip_tail = datalen - 2 - i;
193 skip_tail = (skip_tail > 2 * pad_tail) ?
194 skip_tail - 2 * pad_tail : 0;
197 /* update the size in the headers */
198 Write32(pBuf+4, Read32(pBuf+4) - skip_head - skip_tail);
199 Write32(pBuf+datapos-4, datalen - skip_head - skip_tail);
201 pFile = fopen(argv[1], "wb");
202 if (pFile == NULL)
204 printf("Error opening file %s for writing\n", argv[1]);
205 return -1;
208 /* write the new file */
209 fwrite(pBuf, 1, datapos, pFile); /* write header */
210 fwrite(pBuf + datapos + skip_head, 1, datalen - skip_head - skip_tail, pFile);
211 fclose(pFile);
213 free(pBuf);
214 return 0;
218 RIFF Chunk (12 bytes in length total)
219 0 - 3 "RIFF" (ASCII Characters)
220 4 - 7 Total Length Of Package To Follow (Binary, little endian)
221 8 - 11 "WAVE" (ASCII Characters)
224 FORMAT Chunk (24 or 26 bytes in length total) Byte Number
225 12 - 15 "fmt_" (ASCII Characters)
226 16 - 19 Length Of FORMAT Chunk (Binary, 0x10 or 0x12 seen)
227 20 - 21 Always 0x01
228 22 - 23 Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
229 24 - 27 Sample Rate (Binary, in Hz)
230 28 - 31 Bytes Per Second
231 32 - 33 Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
232 34 - 35 Bits Per Sample
235 DATA Chunk Byte Number
236 36 - 39 "data" (ASCII Characters)
237 40 - 43 Length Of Data To Follow
238 44 - end
239 Data (Samples)