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/>.
30 * Create an empty dat file
32 * @param filename the filename of dat file
34 void wfd_init(const char *filename) {
36 file1 = fopen(filename,"w");
43 * convert micro seconds to samples
45 * @param time time in ms
48 int wfd_ms2samples(double time) {
51 samples_f = ((double)wfh_samplerate) * time / 1000.0;
52 samples = (int)samples_f;
57 * skip the file by microseconds
59 * @param inputfile the file descriptor
60 * @param time time in ms
62 void wfd_skip(FILE *inputfile, double time) {
64 samples = wfd_ms2samples(time);
65 fseek(inputfile,SEEK_CUR,samples*wfh_channels*(wfh_bits/8));
69 * Get volume factor by frame number
71 * @param frame Current frame number
72 * @param p the p vector, 7 elements, sort by time (ms)
73 * @param v the v vector, 7 elements, sort based on p (%)
74 * @return the volume factor for frame. (%)
76 double wfd_append_linear_volume(int frame, const int *p, const double *v) {
80 if (p[i] <= frame && frame < p[i+1]) {
81 ret = v[i] + (v[i+1]-v[i]) * (((double)(frame-p[i])) / (((double)(p[i+1]-p[i]))));
89 * mix sample A with sample B
93 * @return sample of A mix B
95 int16_t wfd_mix(int16_t a, int16_t b) {
101 a_t = ((int)a)+32768;
102 b_t = ((int)b)+32768;
104 if (a_t <= 32768 && b_t <= 32768) {
105 r1 = (a_t * b_t) / 32768;
107 r1 = 2*(a_t+b_t) - (a_t*b_t)/32768 - 65536;
119 * append data to dat file
121 * @param outputfilename the filename of output file
122 * @param inputfilename the filename of input file
123 * @param offset skip the ms in input file
124 * @param length the time in ms have to be handled
125 * @param ovr the overlap of output file and input file (ms)
126 * @param p the p position array
127 * @param v the v volume array
128 * @return 0 - ok, nonzero - error
130 int wfd_append(const char *outputfilename, const char *inputfilename,
131 double offset, double length,
132 double ovr, const double *p, const double *v) {
135 SNDFILE *inputfile=NULL;
136 SF_INFO inputfileinfo;
147 memset(&inputfileinfo,0,sizeof(SF_INFO));
148 outfile = fopen(outputfilename,"r+b");
149 fseek(outfile,0,SEEK_END);
151 inputfile = sf_open(inputfilename,SFM_READ,&inputfileinfo);
152 sf_command(inputfile,SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
156 outputFrames = wfd_ms2samples(length);
159 if (wfd_ms2samples(offset)>0) {
161 sf_seek(inputfile,wfd_ms2samples(offset),SEEK_SET);
165 /* pre-calculate volume */
167 for (i=0; i<2; i++) {
168 p_f[i+1] = wfd_ms2samples(p[i]) + p_f[i];
170 p_f[3] = wfd_ms2samples(p[4]) + p_f[2];
171 p_f[6] = outputFrames;
172 p_f[5] = p_f[6] - wfd_ms2samples(p[3]);
173 p_f[4] = p_f[5] - wfd_ms2samples(p[2]);
184 if (p_f[1]==p_f[2]) {
187 if (p_f[0]==p_f[1]) {
190 if (p_f[5]==p_f[4]) {
193 if (p_f[6]==p_f[5]) {
197 ovrFrames = wfd_ms2samples(ovr);
199 fseek(outfile,(-1)*wfh_channels*(wfh_bits/8)*ovrFrames,SEEK_END);
200 } else if (ovr < 0.0) {
201 /* output blank samples */
204 ovrSamples = wfd_ms2samples(-ovr);
205 for (i=0; i<ovrSamples; i++) {
206 for (j=0; j<wfh_channels; j++) {
207 for (k=0; k<(wfh_bits/8); k++) {
208 fwrite("\0",1,1,outfile);
213 fseek(outfile,0,SEEK_CUR);
219 buf = (int16_t *)malloc(sizeof(int16_t)*(inputfileinfo.channels));
220 memset(buf,0,sizeof(int16_t)*(inputfileinfo.channels));
223 for ( ; outputFrames > 0; outputFrames--) {
226 result1 = (int)sf_readf_short(inputfile,buf,1);
228 memset(buf,0,sizeof(int16_t)*(inputfileinfo.channels));
233 /* simple mix if there are multi-channels */
235 for (i=0; i<inputfileinfo.channels; i++) {
238 /* modify the volume */
239 if (inputfileinfo.channels>0) {
241 sum = sum/inputfileinfo.channels;
242 vf = wfd_append_linear_volume(currentFrame,p_f,v_f);
243 sum = (int16_t)(((double)sum)*(vf/100.0));
252 goto wfd_append_normal;
257 goto wfd_append_normal;
259 fseek(outfile,-2,SEEK_CUR);
260 d = (c1 & (0x00ff)) | (((c2 & 0x00ff) << 8) & 0xff00);
262 fputc( (int)((r) & (0x00ff)), outfile);
263 fputc( (int)((r>>8) & 0x00ff), outfile);
265 fseek(outfile,0,SEEK_CUR);
269 fputc( (int)((sum) & (0x00ff)), outfile);
270 fputc( (int)((sum>>8) & 0x00ff), outfile);
272 fseek(outfile,0,SEEK_CUR);
285 ret = ftell(outfile);