3 Copyright (C) 2011 Ying-Chun Liu (PaulLiu) <paulliu@debian.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 * Create an empty dat file
31 * @param filename the filename of dat file
33 void wfd_init(const char *filename) {
35 file1 = fopen(filename,"w");
42 * convert micro seconds to samples
44 * @param time time in ms
47 int wfd_ms2samples(double time) {
50 samples_f = ((double)wfh_samplerate) * time / 1000.0;
51 samples = (int)samples_f;
56 * skip the file by microseconds
58 * @param inputfile the file descriptor
59 * @param time time in ms
61 void wfd_skip(FILE *inputfile, double time) {
63 samples = wfd_ms2samples(time);
64 fseek(inputfile,SEEK_CUR,samples*wfh_channels*(wfh_bits/8));
68 * Get volume factor by frame number
70 * @param frame Current frame number
71 * @param p the p vector, 7 elements, sort by time (ms)
72 * @param v the v vector, 7 elements, sort based on p (%)
73 * @return the volume factor for frame. (%)
75 double wfd_append_linear_volume(int frame, const int *p, const double *v) {
79 if (p[i] <= frame && frame < p[i+1]) {
80 ret = v[i] + (v[i+1]-v[i]) * (((double)(frame-p[i])) / (((double)(p[i+1]-p[i]))));
88 * mix sample A with sample B
92 * @return sample of A mix B
94 short wfd_mix(short a, short b) {
100 a_t = ((int)a)+32768;
101 b_t = ((int)b)+32768;
103 if (a_t <= 32768 && b_t <= 32768) {
104 r1 = (a_t * b_t) / 32768;
106 r1 = 2*(a_t+b_t) - (a_t*b_t)/32768 - 65536;
118 * append data to dat file
120 * @param outputfilename the filename of output file
121 * @param inputfilename the filename of input file
122 * @param offset skip the ms in input file
123 * @param length the time in ms have to be handled
124 * @param ovr the overlap of output file and input file (ms)
125 * @param p the p position array
126 * @param v the v volume array
127 * @return 0 - ok, nonzero - error
129 int wfd_append(const char *outputfilename, const char *inputfilename,
130 double offset, double length,
131 double ovr, const double *p, const double *v) {
134 SNDFILE *inputfile=NULL;
135 SF_INFO inputfileinfo;
146 memset(&inputfileinfo,0,sizeof(SF_INFO));
147 outfile = fopen(outputfilename,"r+");
148 fseek(outfile,0,SEEK_END);
150 inputfile = sf_open(inputfilename,SFM_READ,&inputfileinfo);
151 sf_command(inputfile,SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
155 outputFrames = wfd_ms2samples(length);
158 if (wfd_ms2samples(offset)>0) {
160 sf_seek(inputfile,wfd_ms2samples(offset),SEEK_SET);
164 /* pre-calculate volume */
166 for (i=0; i<2; i++) {
167 p_f[i+1] = wfd_ms2samples(p[i]) + p_f[i];
169 p_f[3] = wfd_ms2samples(p[4]) + p_f[2];
170 p_f[6] = outputFrames;
171 p_f[5] = p_f[6] - wfd_ms2samples(p[3]);
172 p_f[4] = p_f[5] - wfd_ms2samples(p[2]);
183 if (p_f[1]==p_f[2]) {
186 if (p_f[0]==p_f[1]) {
189 if (p_f[5]==p_f[4]) {
192 if (p_f[6]==p_f[5]) {
196 ovrFrames = wfd_ms2samples(ovr);
198 fseek(outfile,(-1)*wfh_channels*(wfh_bits/8)*ovrFrames,SEEK_END);
199 } else if (ovr < 0.0) {
200 /* output blank samples */
203 ovrSamples = wfd_ms2samples(-ovr);
204 for (i=0; i<ovrSamples; i++) {
205 for (j=0; j<wfh_channels; j++) {
206 for (k=0; k<(wfh_bits/8); k++) {
207 fwrite("\0",1,1,outfile);
211 fseek(outfile,0,SEEK_CUR);
217 buf = (short *)malloc(sizeof(short)*(inputfileinfo.channels));
218 memset(buf,0,sizeof(short)*(inputfileinfo.channels));
221 for ( ; outputFrames > 0; outputFrames--) {
224 result1 = sf_readf_short(inputfile,buf,1);
226 memset(buf,0,sizeof(short)*(inputfileinfo.channels));
231 /* simple mix if there are multi-channels */
233 for (i=0; i<inputfileinfo.channels; i++) {
236 /* modify the volume */
237 if (inputfileinfo.channels>0) {
239 sum = sum/inputfileinfo.channels;
240 vf = wfd_append_linear_volume(currentFrame,p_f,v_f);
241 sum = (short)(((double)sum)*(vf/100.0));
250 goto wfd_append_normal;
255 goto wfd_append_normal;
257 fseek(outfile,-2,SEEK_CUR);
258 d = (c1 & (0x00ff)) | (((c2 & 0x00ff) << 8) & 0xff00);
260 fputc( (char)(r & (0x00ff)), outfile);
261 fputc( (char)((r>>8) & 0x00ff), outfile);
262 fseek(outfile,0,SEEK_CUR);
266 fputc( (char)(sum & (0x00ff)), outfile);
267 fputc( (char)((sum>>8) & 0x00ff), outfile);
268 fseek(outfile,0,SEEK_CUR);
281 ret = ftell(outfile);