blob: 86fec7e256a84319af7ee8e980615c3c90bfe0aa [file] [log] [blame]
Jonas Häggqvistda071d02006-11-03 21:47:52 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
Nicolas Pennequin357ffb32008-05-05 10:32:46 +000010 * Copyright (C) 2004 by Jörg Hohensohn
Jonas Häggqvistda071d02006-11-03 21:47:52 +000011 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Jonas Häggqvistda071d02006-11-03 21:47:52 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 * Details at http://www.rockbox.org/twiki/bin/view/Main/VoiceBuilding
21 *
22 ****************************************************************************/
23
24
25#include <stdio.h> /* for file I/O */
26#include <stdlib.h> /* for malloc */
27
Dominik Wenger5be33292008-01-11 23:46:10 +000028#include "wavtrim.h"
29
Jonas Häggqvistda071d02006-11-03 21:47:52 +000030/* place a 32 bit value into memory, little endian */
31void Write32(unsigned char* pByte, unsigned long value)
32{
33 pByte[0] = (unsigned char)value;
34 pByte[1] = (unsigned char)(value >> 8);
35 pByte[2] = (unsigned char)(value >> 16);
36 pByte[3] = (unsigned char)(value >> 24) ;
37}
38
39
40/* read a 32 bit value from memory, little endian */
41unsigned long Read32(unsigned char* pByte)
42{
43 unsigned long value = 0;
44
45 value |= (unsigned long)pByte[0];
46 value |= (unsigned long)pByte[1] << 8;
47 value |= (unsigned long)pByte[2] << 16;
48 value |= (unsigned long)pByte[3] << 24;
49
50 return value;
51}
52
53
54/* place a 16 bit value into memory, little endian */
55void Write16(unsigned char* pByte, unsigned short value)
56{
57 pByte[0] = (unsigned char)value;
58 pByte[1] = (unsigned char)(value >> 8);
59}
60
61
62/* read a 16 bit value from memory, little endian */
63unsigned long Read16(unsigned char* pByte)
64{
65 unsigned short value = 0;
66
67 value |= (unsigned short)pByte[0];
68 value |= (unsigned short)pByte[1] << 8;
69
70 return value;
71}
72
Dominik Wenger5be33292008-01-11 23:46:10 +000073int wavtrim(char * filename, int maxsilence ,char* errstring,int errsize)
74{
Jonas Häggqvistda071d02006-11-03 21:47:52 +000075 FILE* pFile;
76 long lFileSize, lGot;
77 unsigned char* pBuf;
78 int bps; /* byte per sample */
79 int sps; /* samples per second */
80 int datapos; /* where the payload starts */
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +000081 int datalen; /* Length of the data chunk */
82 unsigned char *databuf; /* Pointer to the data chunk payload */
Jonas Häggqvistda071d02006-11-03 21:47:52 +000083 int skip_head, skip_tail, pad_head, pad_tail;
84 int i;
Dominik Wenger5be33292008-01-11 23:46:10 +000085 int max_silence = maxsilence;
Jonas Häggqvistda071d02006-11-03 21:47:52 +000086 signed char sample8;
87 short sample16;
88
Dominik Wenger5be33292008-01-11 23:46:10 +000089 pFile = fopen(filename, "rb");
Jonas Häggqvistda071d02006-11-03 21:47:52 +000090 if (pFile == NULL)
91 {
Dominik Wenger5be33292008-01-11 23:46:10 +000092 snprintf(errstring,errsize,"Error opening file %s for reading\n", filename);
Jonas Häggqvistda071d02006-11-03 21:47:52 +000093 return -1;
94 }
Dominik Wenger5be33292008-01-11 23:46:10 +000095
Jonas Häggqvistda071d02006-11-03 21:47:52 +000096 fseek(pFile, 0, SEEK_END);
97 lFileSize = ftell(pFile);
98 fseek(pFile, 0, SEEK_SET);
99
100 pBuf = malloc(lFileSize);
101 if (pBuf == NULL)
102 {
Dominik Wenger5be33292008-01-11 23:46:10 +0000103 snprintf(errstring,errsize,"Out of memory to allocate %ld bytes for file.\n", lFileSize);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000104 fclose(pFile);
105 return -1;
106 }
107
108 lGot = fread(pBuf, 1, lFileSize, pFile);
109 fclose(pFile);
110 if (lGot != lFileSize)
111 {
Dominik Wenger5be33292008-01-11 23:46:10 +0000112 snprintf(errstring,errsize,"File read error, got only %ld bytes out of %ld.\n", lGot, lFileSize);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000113 free(pBuf);
114 return -1;
115 }
Dominik Wenger5be33292008-01-11 23:46:10 +0000116
117
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000118 bps = Read16(pBuf + 32);
119 datapos = 28 + Read16(pBuf + 16);
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000120 databuf = &pBuf[datapos];
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000121
122 if (Read32(pBuf) != 0x46464952 /* "RIFF" */
123 || Read32(pBuf+8) != 0x45564157 /* "WAVE" */
124 || Read32(pBuf+12) != 0x20746d66 /* "fmt " */
125 || Read32(pBuf+datapos-8) != 0x61746164) /* "data" */
126 {
Dominik Wenger5be33292008-01-11 23:46:10 +0000127 snprintf(errstring,errsize,"No valid input WAV file?\n");
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000128 free(pBuf);
129 return -1;
130 }
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000131
132 datalen = Read32(pBuf+datapos-4);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000133
134 sps = Read32(pBuf + 24);
135 pad_head = sps * 10 / 1000; /* 10 ms */
136 pad_tail = sps * 10 / 1000; /* 10 ms */
137
138 if (bps == 1) /* 8 bit samples */
139 {
140
141 max_silence >>= 8;
142
143 /* clip the start */
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000144 for (i=0; i<datalen; i++)
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000145 {
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000146 sample8 = databuf[i] - 0x80;
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000147 if (abs(sample8) > max_silence)
148 break;
149 }
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000150 skip_head = i;
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000151 skip_head = (skip_head > pad_head) ? skip_head - pad_head : 0;
152
153 /* clip the end */
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000154 for (i=datalen-1; i>skip_head; i--)
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000155 {
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000156 sample8 = databuf[i] - 0x80;
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000157 if (abs(sample8) > max_silence)
158 break;
159 }
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000160 skip_tail = datalen - 1 - i;
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000161 skip_tail = (skip_tail > pad_tail) ? skip_tail - pad_tail : 0;
162 }
163 else if (bps == 2) /* 16 bit samples */
164 {
165
166 /* clip the start */
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000167 for (i=0; i<datalen; i+=2)
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000168 {
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000169 sample16 = *(short *)(databuf + i);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000170 if (abs(sample16) > max_silence)
171 break;
172 }
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000173 skip_head = i;
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000174 skip_head = (skip_head > 2 * pad_head) ?
175 skip_head - 2 * pad_head : 0;
176
177 /* clip the end */
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000178 for (i=datalen-2; i>skip_head; i-=2)
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000179 {
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000180 sample16 = *(short *)(databuf + i);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000181 if (abs(sample16) > max_silence)
182 break;
183 }
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000184 skip_tail = datalen - 2 - i;
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000185 skip_tail = (skip_tail > 2 * pad_tail) ?
186 skip_tail - 2 * pad_tail : 0;
187 }
188
189 /* update the size in the headers */
190 Write32(pBuf+4, Read32(pBuf+4) - skip_head - skip_tail);
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000191 Write32(pBuf+datapos-4, datalen - skip_head - skip_tail);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000192
Dominik Wenger5be33292008-01-11 23:46:10 +0000193 pFile = fopen(filename, "wb");
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000194 if (pFile == NULL)
195 {
Dominik Wenger5be33292008-01-11 23:46:10 +0000196 snprintf(errstring,errsize,"Error opening file %s for writing\n",filename);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000197 return -1;
198 }
199
200 /* write the new file */
201 fwrite(pBuf, 1, datapos, pFile); /* write header */
Linus Nielsen Feltzing9d66a282007-08-07 10:21:03 +0000202 fwrite(pBuf + datapos + skip_head, 1, datalen - skip_head - skip_tail, pFile);
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000203 fclose(pFile);
204
205 free(pBuf);
206 return 0;
Dominik Wenger5be33292008-01-11 23:46:10 +0000207
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000208}
209
Dominik Wenger5be33292008-01-11 23:46:10 +0000210#ifndef RBUTIL
211int main (int argc, char** argv)
212{
213 int max_silence = 0;
214 char errbuffer[255];
215 int ret=0;
216
217 if (argc < 2)
218 {
219 printf("wavtrim removes silence at the begin and end of a WAV file.\n");
220 printf("usage: wavtrim <filename.wav> [<max_silence>]\n");
221 return 0;
222 }
223
224 if (argc == 3)
225 {
226 max_silence = atoi(argv[2]);
227 }
228
229
230 ret = wavtrim(argv[1],max_silence,errbuffer,255 );
231 if( ret< 0)
232 {
233 printf(errbuffer);
234 }
235 return ret;
236}
237#endif
Jonas Häggqvistda071d02006-11-03 21:47:52 +0000238/*
239RIFF Chunk (12 bytes in length total)
2400 - 3 "RIFF" (ASCII Characters)
2414 - 7 Total Length Of Package To Follow (Binary, little endian)
2428 - 11 "WAVE" (ASCII Characters)
243
244
245FORMAT Chunk (24 or 26 bytes in length total) Byte Number
24612 - 15 "fmt_" (ASCII Characters)
24716 - 19 Length Of FORMAT Chunk (Binary, 0x10 or 0x12 seen)
24820 - 21 Always 0x01
24922 - 23 Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
25024 - 27 Sample Rate (Binary, in Hz)
25128 - 31 Bytes Per Second
25232 - 33 Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
25334 - 35 Bits Per Sample
254
255
256DATA Chunk Byte Number
25736 - 39 "data" (ASCII Characters)
25840 - 43 Length Of Data To Follow
25944 - end
260 Data (Samples)
261*/