1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004 by Jörg Hohensohn
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 * Details at http://www.rockbox.org/twiki/bin/view/Main/VoiceBuilding
22 ****************************************************************************/
25 #include <stdio.h> /* for file I/O */
26 #include <stdlib.h> /* for malloc */
31 #define snprintf _snprintf
34 /* place a 32 bit value into memory, little endian */
35 void Write32(unsigned char* pByte
, unsigned long value
)
37 pByte
[0] = (unsigned char)value
;
38 pByte
[1] = (unsigned char)(value
>> 8);
39 pByte
[2] = (unsigned char)(value
>> 16);
40 pByte
[3] = (unsigned char)(value
>> 24) ;
44 /* read a 32 bit value from memory, little endian */
45 unsigned long Read32(unsigned char* pByte
)
47 unsigned long value
= 0;
49 value
|= (unsigned long)pByte
[0];
50 value
|= (unsigned long)pByte
[1] << 8;
51 value
|= (unsigned long)pByte
[2] << 16;
52 value
|= (unsigned long)pByte
[3] << 24;
58 /* place a 16 bit value into memory, little endian */
59 void Write16(unsigned char* pByte
, unsigned short value
)
61 pByte
[0] = (unsigned char)value
;
62 pByte
[1] = (unsigned char)(value
>> 8);
66 /* read a 16 bit value from memory, little endian */
67 unsigned long Read16(unsigned char* pByte
)
69 unsigned short value
= 0;
71 value
|= (unsigned short)pByte
[0];
72 value
|= (unsigned short)pByte
[1] << 8;
77 int wavtrim(char * filename
, int maxsilence
,char* errstring
,int errsize
)
82 int bps
; /* byte per sample */
83 int sps
; /* samples per second */
84 int datapos
; /* where the payload starts */
85 int datalen
; /* Length of the data chunk */
86 unsigned char *databuf
; /* Pointer to the data chunk payload */
87 int skip_head
, skip_tail
, pad_head
, pad_tail
;
89 int max_silence
= maxsilence
;
93 pFile
= fopen(filename
, "rb");
96 snprintf(errstring
,errsize
,"Error opening file %s for reading\n", filename
);
100 fseek(pFile
, 0, SEEK_END
);
101 lFileSize
= ftell(pFile
);
102 fseek(pFile
, 0, SEEK_SET
);
104 pBuf
= malloc(lFileSize
);
107 snprintf(errstring
,errsize
,"Out of memory to allocate %ld bytes for file.\n", lFileSize
);
112 lGot
= fread(pBuf
, 1, lFileSize
, pFile
);
114 if (lGot
!= lFileSize
)
116 snprintf(errstring
,errsize
,"File read error, got only %ld bytes out of %ld.\n", lGot
, lFileSize
);
122 bps
= Read16(pBuf
+ 32);
123 datapos
= 28 + Read16(pBuf
+ 16);
124 databuf
= &pBuf
[datapos
];
126 if (Read32(pBuf
) != 0x46464952 /* "RIFF" */
127 || Read32(pBuf
+8) != 0x45564157 /* "WAVE" */
128 || Read32(pBuf
+12) != 0x20746d66 /* "fmt " */
129 || Read32(pBuf
+datapos
-8) != 0x61746164) /* "data" */
131 snprintf(errstring
,errsize
,"No valid input WAV file?\n");
136 datalen
= Read32(pBuf
+datapos
-4);
137 skip_head
= skip_tail
= 0;
139 sps
= Read32(pBuf
+ 24);
140 pad_head
= sps
* 10 / 1000; /* 10 ms */
141 pad_tail
= sps
* 10 / 1000; /* 10 ms */
143 if (bps
== 1) /* 8 bit samples */
149 for (i
=0; i
<datalen
; i
++)
151 sample8
= databuf
[i
] - 0x80;
152 if (abs(sample8
) > max_silence
)
156 skip_head
= (skip_head
> pad_head
) ? skip_head
- pad_head
: 0;
159 for (i
=datalen
-1; i
>skip_head
; i
--)
161 sample8
= databuf
[i
] - 0x80;
162 if (abs(sample8
) > max_silence
)
165 skip_tail
= datalen
- 1 - i
;
166 skip_tail
= (skip_tail
> pad_tail
) ? skip_tail
- pad_tail
: 0;
168 else if (bps
== 2) /* 16 bit samples */
172 for (i
=0; i
<datalen
; i
+=2)
174 /* samples are little endian */
175 sample16
= (*(databuf
+ i
+ 1) << 8) | *(databuf
+ i
);
177 if (abs(sample16
) > max_silence
)
181 skip_head
= (skip_head
> 2 * pad_head
) ?
182 skip_head
- 2 * pad_head
: 0;
185 for (i
=datalen
-2; i
>skip_head
; i
-=2)
187 /* samples are little endian */
188 sample16
= (*(databuf
+ i
+ 1) << 8) | *(databuf
+ i
);
189 if (abs(sample16
) > max_silence
)
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(filename
, "wb");
204 snprintf(errstring
,errsize
,"Error opening file %s for writing\n",filename
);
209 /* write the new file */
210 if ((int)fwrite(pBuf
, 1, datapos
, pFile
) != datapos
) /* write header */
212 snprintf(errstring
,errsize
,"Error writing file %s header\n",filename
);
217 if ((int)fwrite(pBuf
+ datapos
+ skip_head
, 1, datalen
- skip_head
- skip_tail
, pFile
)
218 != datalen
- skip_head
- skip_tail
)
220 snprintf(errstring
,errsize
,"Error writing file %s data\n",filename
);
233 int main (int argc
, char** argv
)
241 printf("wavtrim removes silence at the begin and end of a WAV file.\n");
242 printf("usage: wavtrim <filename.wav> [<max_silence>]\n");
248 max_silence
= atoi(argv
[2]);
252 ret
= wavtrim(argv
[1],max_silence
,errbuffer
,255 );
255 printf("%s", errbuffer
);
261 RIFF Chunk (12 bytes in length total)
262 0 - 3 "RIFF" (ASCII Characters)
263 4 - 7 Total Length Of Package To Follow (Binary, little endian)
264 8 - 11 "WAVE" (ASCII Characters)
267 FORMAT Chunk (24 or 26 bytes in length total) Byte Number
268 12 - 15 "fmt_" (ASCII Characters)
269 16 - 19 Length Of FORMAT Chunk (Binary, 0x10 or 0x12 seen)
271 22 - 23 Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
272 24 - 27 Sample Rate (Binary, in Hz)
273 28 - 31 Bytes Per Second
274 32 - 33 Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
275 34 - 35 Bits Per Sample
278 DATA Chunk Byte Number
279 36 - 39 "data" (ASCII Characters)
280 40 - 43 Length Of Data To Follow