A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 283 lines 7.9 kB view raw
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*/