A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jörg Hohensohn
11 *
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.
16 *
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/wiki/VoiceBuilding
21 *
22 ****************************************************************************/
23
24
25#include <stdio.h> /* for file I/O */
26#include <stdlib.h> /* for malloc */
27
28#include "wavtrim.h"
29
30#ifdef _MSC_VER
31#define snprintf _snprintf
32#endif
33
34/* place a 32 bit value into memory, little endian */
35void Write32(unsigned char* pByte, unsigned long value)
36{
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) ;
41}
42
43
44/* read a 32 bit value from memory, little endian */
45unsigned long Read32(unsigned char* pByte)
46{
47 unsigned long value = 0;
48
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;
53
54 return value;
55}
56
57
58/* place a 16 bit value into memory, little endian */
59void Write16(unsigned char* pByte, unsigned short value)
60{
61 pByte[0] = (unsigned char)value;
62 pByte[1] = (unsigned char)(value >> 8);
63}
64
65
66/* read a 16 bit value from memory, little endian */
67unsigned long Read16(unsigned char* pByte)
68{
69 unsigned short value = 0;
70
71 value |= (unsigned short)pByte[0];
72 value |= (unsigned short)pByte[1] << 8;
73
74 return value;
75}
76
77int wavtrim(char * filename, int maxsilence ,char* errstring,int errsize)
78{
79 FILE* pFile;
80 long lFileSize, lGot;
81 unsigned char* pBuf;
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;
88 int i;
89 int max_silence = maxsilence;
90 signed char sample8;
91 short sample16;
92
93 pFile = fopen(filename, "rb");
94 if (pFile == NULL)
95 {
96 snprintf(errstring,errsize,"Error opening file %s for reading\n", filename);
97 return -1;
98 }
99
100 fseek(pFile, 0, SEEK_END);
101 lFileSize = ftell(pFile);
102 fseek(pFile, 0, SEEK_SET);
103
104 pBuf = malloc(lFileSize);
105 if (pBuf == NULL)
106 {
107 snprintf(errstring,errsize,"Out of memory to allocate %ld bytes for file.\n", lFileSize);
108 fclose(pFile);
109 return -1;
110 }
111
112 lGot = fread(pBuf, 1, lFileSize, pFile);
113 fclose(pFile);
114 if (lGot != lFileSize)
115 {
116 snprintf(errstring,errsize,"File read error, got only %ld bytes out of %ld.\n", lGot, lFileSize);
117 free(pBuf);
118 return -1;
119 }
120
121
122 bps = Read16(pBuf + 32);
123 datapos = 28 + Read16(pBuf + 16);
124 databuf = &pBuf[datapos];
125
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" */
130 {
131 snprintf(errstring,errsize,"No valid input WAV file?\n");
132 free(pBuf);
133 return -1;
134 }
135
136 datalen = Read32(pBuf+datapos-4);
137 skip_head = skip_tail = 0;
138
139 sps = Read32(pBuf + 24);
140 pad_head = sps * 10 / 1000; /* 10 ms */
141 pad_tail = sps * 10 / 1000; /* 10 ms */
142
143 if (bps == 1) /* 8 bit samples */
144 {
145
146 max_silence >>= 8;
147
148 /* clip the start */
149 for (i=0; i<datalen; i++)
150 {
151 sample8 = databuf[i] - 0x80;
152 if (abs(sample8) > max_silence)
153 break;
154 }
155 skip_head = i;
156 skip_head = (skip_head > pad_head) ? skip_head - pad_head : 0;
157
158 /* clip the end */
159 for (i=datalen-1; i>skip_head; i--)
160 {
161 sample8 = databuf[i] - 0x80;
162 if (abs(sample8) > max_silence)
163 break;
164 }
165 skip_tail = datalen - 1 - i;
166 skip_tail = (skip_tail > pad_tail) ? skip_tail - pad_tail : 0;
167 }
168 else if (bps == 2) /* 16 bit samples */
169 {
170
171 /* clip the start */
172 for (i=0; i<datalen; i+=2)
173 {
174 /* samples are little endian */
175 sample16 = (*(databuf + i + 1) << 8) | *(databuf + i);
176
177 if (abs(sample16) > max_silence)
178 break;
179 }
180 skip_head = i;
181 skip_head = (skip_head > 2 * pad_head) ?
182 skip_head - 2 * pad_head : 0;
183
184 /* clip the end */
185 for (i=datalen-2; i>skip_head; i-=2)
186 {
187 /* samples are little endian */
188 sample16 = (*(databuf + i + 1) << 8) | *(databuf + i);
189 if (abs(sample16) > max_silence)
190 break;
191 }
192 skip_tail = datalen - 2 - i;
193 skip_tail = (skip_tail > 2 * pad_tail) ?
194 skip_tail - 2 * pad_tail : 0;
195 }
196
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);
200
201 pFile = fopen(filename, "wb");
202 if (pFile == NULL)
203 {
204 snprintf(errstring,errsize,"Error opening file %s for writing\n",filename);
205 free(pBuf);
206 return -1;
207 }
208
209 /* write the new file */
210 if ((int)fwrite(pBuf, 1, datapos, pFile) != datapos) /* write header */
211 {
212 snprintf(errstring,errsize,"Error writing file %s header\n",filename);
213 fclose(pFile);
214 free(pBuf);
215 return -1;
216 }
217 if ((int)fwrite(pBuf + datapos + skip_head, 1, datalen - skip_head - skip_tail, pFile)
218 != datalen - skip_head - skip_tail)
219 {
220 snprintf(errstring,errsize,"Error writing file %s data\n",filename);
221 fclose(pFile);
222 free(pBuf);
223 return -1;
224 }
225 fclose(pFile);
226
227 free(pBuf);
228 return 0;
229
230}
231
232#ifndef RBUTIL
233int main (int argc, char** argv)
234{
235 int max_silence = 0;
236 char errbuffer[255];
237 int ret=0;
238
239 if (argc < 2)
240 {
241 printf("wavtrim removes silence at the begin and end of a WAV file.\n");
242 printf("usage: wavtrim <filename.wav> [<max_silence>]\n");
243 return 0;
244 }
245
246 if (argc == 3)
247 {
248 max_silence = atoi(argv[2]);
249 }
250
251
252 ret = wavtrim(argv[1],max_silence,errbuffer,255 );
253 if( ret< 0)
254 {
255 printf("%s", errbuffer);
256 }
257 return ret;
258}
259#endif
260/*
261RIFF Chunk (12 bytes in length total)
2620 - 3 "RIFF" (ASCII Characters)
2634 - 7 Total Length Of Package To Follow (Binary, little endian)
2648 - 11 "WAVE" (ASCII Characters)
265
266
267FORMAT Chunk (24 or 26 bytes in length total) Byte Number
26812 - 15 "fmt_" (ASCII Characters)
26916 - 19 Length Of FORMAT Chunk (Binary, 0x10 or 0x12 seen)
27020 - 21 Always 0x01
27122 - 23 Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
27224 - 27 Sample Rate (Binary, in Hz)
27328 - 31 Bytes Per Second
27432 - 33 Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
27534 - 35 Bits Per Sample
276
277
278DATA Chunk Byte Number
27936 - 39 "data" (ASCII Characters)
28040 - 43 Length Of Data To Follow
28144 - end
282 Data (Samples)
283*/