Rename InstallProgress form to ProgressLogger as it's a generic logger window now.
[Rockbox.git] / tools / wavtrim.c
blobfe212ef93c89018739ac5ddbff01f5bc468d003e
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 #include "wavtrim.h"
28 /* place a 32 bit value into memory, little endian */
29 void Write32(unsigned char* pByte, unsigned long value)
31 pByte[0] = (unsigned char)value;
32 pByte[1] = (unsigned char)(value >> 8);
33 pByte[2] = (unsigned char)(value >> 16);
34 pByte[3] = (unsigned char)(value >> 24) ;
38 /* read a 32 bit value from memory, little endian */
39 unsigned long Read32(unsigned char* pByte)
41 unsigned long value = 0;
43 value |= (unsigned long)pByte[0];
44 value |= (unsigned long)pByte[1] << 8;
45 value |= (unsigned long)pByte[2] << 16;
46 value |= (unsigned long)pByte[3] << 24;
48 return value;
52 /* place a 16 bit value into memory, little endian */
53 void Write16(unsigned char* pByte, unsigned short value)
55 pByte[0] = (unsigned char)value;
56 pByte[1] = (unsigned char)(value >> 8);
60 /* read a 16 bit value from memory, little endian */
61 unsigned long Read16(unsigned char* pByte)
63 unsigned short value = 0;
65 value |= (unsigned short)pByte[0];
66 value |= (unsigned short)pByte[1] << 8;
68 return value;
71 int wavtrim(char * filename, int maxsilence ,char* errstring,int errsize)
73 FILE* pFile;
74 long lFileSize, lGot;
75 unsigned char* pBuf;
76 int bps; /* byte per sample */
77 int sps; /* samples per second */
78 int datapos; /* where the payload starts */
79 int datalen; /* Length of the data chunk */
80 unsigned char *databuf; /* Pointer to the data chunk payload */
81 int skip_head, skip_tail, pad_head, pad_tail;
82 int i;
83 int max_silence = maxsilence;
84 signed char sample8;
85 short sample16;
87 pFile = fopen(filename, "rb");
88 if (pFile == NULL)
90 snprintf(errstring,errsize,"Error opening file %s for reading\n", filename);
91 return -1;
94 fseek(pFile, 0, SEEK_END);
95 lFileSize = ftell(pFile);
96 fseek(pFile, 0, SEEK_SET);
98 pBuf = malloc(lFileSize);
99 if (pBuf == NULL)
101 snprintf(errstring,errsize,"Out of memory to allocate %ld bytes for file.\n", lFileSize);
102 fclose(pFile);
103 return -1;
106 lGot = fread(pBuf, 1, lFileSize, pFile);
107 fclose(pFile);
108 if (lGot != lFileSize)
110 snprintf(errstring,errsize,"File read error, got only %ld bytes out of %ld.\n", lGot, lFileSize);
111 free(pBuf);
112 return -1;
116 bps = Read16(pBuf + 32);
117 datapos = 28 + Read16(pBuf + 16);
118 databuf = &pBuf[datapos];
120 if (Read32(pBuf) != 0x46464952 /* "RIFF" */
121 || Read32(pBuf+8) != 0x45564157 /* "WAVE" */
122 || Read32(pBuf+12) != 0x20746d66 /* "fmt " */
123 || Read32(pBuf+datapos-8) != 0x61746164) /* "data" */
125 snprintf(errstring,errsize,"No valid input WAV file?\n");
126 free(pBuf);
127 return -1;
130 datalen = Read32(pBuf+datapos-4);
132 sps = Read32(pBuf + 24);
133 pad_head = sps * 10 / 1000; /* 10 ms */
134 pad_tail = sps * 10 / 1000; /* 10 ms */
136 if (bps == 1) /* 8 bit samples */
139 max_silence >>= 8;
141 /* clip the start */
142 for (i=0; i<datalen; i++)
144 sample8 = databuf[i] - 0x80;
145 if (abs(sample8) > max_silence)
146 break;
148 skip_head = i;
149 skip_head = (skip_head > pad_head) ? skip_head - pad_head : 0;
151 /* clip the end */
152 for (i=datalen-1; i>skip_head; i--)
154 sample8 = databuf[i] - 0x80;
155 if (abs(sample8) > max_silence)
156 break;
158 skip_tail = datalen - 1 - i;
159 skip_tail = (skip_tail > pad_tail) ? skip_tail - pad_tail : 0;
161 else if (bps == 2) /* 16 bit samples */
164 /* clip the start */
165 for (i=0; i<datalen; i+=2)
167 sample16 = *(short *)(databuf + i);
168 if (abs(sample16) > max_silence)
169 break;
171 skip_head = i;
172 skip_head = (skip_head > 2 * pad_head) ?
173 skip_head - 2 * pad_head : 0;
175 /* clip the end */
176 for (i=datalen-2; i>skip_head; i-=2)
178 sample16 = *(short *)(databuf + i);
179 if (abs(sample16) > max_silence)
180 break;
182 skip_tail = datalen - 2 - i;
183 skip_tail = (skip_tail > 2 * pad_tail) ?
184 skip_tail - 2 * pad_tail : 0;
187 /* update the size in the headers */
188 Write32(pBuf+4, Read32(pBuf+4) - skip_head - skip_tail);
189 Write32(pBuf+datapos-4, datalen - skip_head - skip_tail);
191 pFile = fopen(filename, "wb");
192 if (pFile == NULL)
194 snprintf(errstring,errsize,"Error opening file %s for writing\n",filename);
195 return -1;
198 /* write the new file */
199 fwrite(pBuf, 1, datapos, pFile); /* write header */
200 fwrite(pBuf + datapos + skip_head, 1, datalen - skip_head - skip_tail, pFile);
201 fclose(pFile);
203 free(pBuf);
204 return 0;
208 #ifndef RBUTIL
209 int main (int argc, char** argv)
211 int max_silence = 0;
212 char errbuffer[255];
213 int ret=0;
215 if (argc < 2)
217 printf("wavtrim removes silence at the begin and end of a WAV file.\n");
218 printf("usage: wavtrim <filename.wav> [<max_silence>]\n");
219 return 0;
222 if (argc == 3)
224 max_silence = atoi(argv[2]);
228 ret = wavtrim(argv[1],max_silence,errbuffer,255 );
229 if( ret< 0)
231 printf(errbuffer);
233 return ret;
235 #endif
237 RIFF Chunk (12 bytes in length total)
238 0 - 3 "RIFF" (ASCII Characters)
239 4 - 7 Total Length Of Package To Follow (Binary, little endian)
240 8 - 11 "WAVE" (ASCII Characters)
243 FORMAT Chunk (24 or 26 bytes in length total) Byte Number
244 12 - 15 "fmt_" (ASCII Characters)
245 16 - 19 Length Of FORMAT Chunk (Binary, 0x10 or 0x12 seen)
246 20 - 21 Always 0x01
247 22 - 23 Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
248 24 - 27 Sample Rate (Binary, in Hz)
249 28 - 31 Bytes Per Second
250 32 - 33 Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
251 34 - 35 Bits Per Sample
254 DATA Chunk Byte Number
255 36 - 39 "data" (ASCII Characters)
256 40 - 43 Length Of Data To Follow
257 44 - end
258 Data (Samples)